mirror of
https://github.com/fergalmoran/chrometophone.git
synced 2025-12-22 09:41:51 +00:00
Phone to Chrome support
This commit is contained in:
@@ -12,8 +12,9 @@
|
|||||||
|
|
||||||
<!-- Permissions for internet access and account access -->
|
<!-- Permissions for internet access and account access -->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<!-- App must have this permission to use the library -->
|
<!-- App must have this permission to use the library -->
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
|
|
||||||
@@ -31,14 +32,21 @@
|
|||||||
<activity android:name=".HelpActivity"
|
<activity android:name=".HelpActivity"
|
||||||
android:screenOrientation="portrait">
|
android:screenOrientation="portrait">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<!-- In order to use the c2dm library, an
|
<activity android:name=".ShareLinkActivity">
|
||||||
application must declare a class with the name C2DMReceiver, in its
|
<intent-filter>
|
||||||
own package, extending com.google.android.c2dm.C2DMBaseReceiver
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<!-- In order to use the c2dm library, an
|
||||||
|
application must declare a class with the name C2DMReceiver, in its
|
||||||
|
own package, extending com.google.android.c2dm.C2DMBaseReceiver
|
||||||
|
|
||||||
It must also include this section in the manifest, replacing
|
It must also include this section in the manifest, replacing
|
||||||
"com.google.android.apps.chrometophone" with its package name.
|
"com.google.android.apps.chrometophone" with its package name. -->
|
||||||
-->
|
|
||||||
<service android:name=".C2DMReceiver" />
|
<service android:name=".C2DMReceiver" />
|
||||||
|
|
||||||
<!-- Only google service can send data messages for the app. If permission is not set -
|
<!-- Only google service can send data messages for the app. If permission is not set -
|
||||||
|
|||||||
@@ -77,6 +77,18 @@
|
|||||||
<!-- Notification shown when text from the desktop is copied to Android's clipboard (user can now paste the text) [CHAR LIMIT=NONE] -->
|
<!-- Notification shown when text from the desktop is copied to Android's clipboard (user can now paste the text) [CHAR LIMIT=NONE] -->
|
||||||
<string name="copied_desktop_clipboard">Copied desktop clipboard</string>
|
<string name="copied_desktop_clipboard">Copied desktop clipboard</string>
|
||||||
|
|
||||||
|
<!-- Brief notification that appears when user sends link from phone to desktop [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="sending_link_toast">Sending link...</string>
|
||||||
|
|
||||||
|
<!-- Brief notification that appears when user has sent link from phone to desktop [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="link_sent_toast">Link sent</string>
|
||||||
|
|
||||||
|
<!-- Brief notification that appears when link cannot be sent from phone to desktop [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="link_not_sent_toast">Link not sent</string>
|
||||||
|
|
||||||
|
<!-- Brief notification that appears when link cannot be sent from phone to desktop (because of auth issue) [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="link_not_sent_auth_toast">Link not sent - authentication required</string>
|
||||||
|
|
||||||
<!-- Introduction text at start of setup flow. Preserve occurrences of <br>, <a href="{tos_link}">, <a href="{pp_link}">, and <a/> [CHAR LIMIT=NONE] -->
|
<!-- Introduction text at start of setup flow. Preserve occurrences of <br>, <a href="{tos_link}">, <a href="{pp_link}">, and <a/> [CHAR LIMIT=NONE] -->
|
||||||
<string name="intro_text">
|
<string name="intro_text">
|
||||||
Chrome to Phone lets you easily share links, maps, and currently selected phone numbers and text
|
Chrome to Phone lets you easily share links, maps, and currently selected phone numbers and text
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.apps.chrometophone;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.params.HttpClientParams;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.params.BasicHttpParams;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.accounts.AccountManagerFuture;
|
||||||
|
import android.accounts.AuthenticatorException;
|
||||||
|
import android.accounts.OperationCanceledException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AppEngine client. Handles auth.
|
||||||
|
*/
|
||||||
|
public class AppEngineClient {
|
||||||
|
private static final String TAG = "AppEngineClient";
|
||||||
|
|
||||||
|
static final String BASE_URL = "https://chrometophone.appspot.com";
|
||||||
|
private static final String AUTH_URL = BASE_URL + "/_ah/login";
|
||||||
|
private static final String AUTH_TOKEN_TYPE = "ah";
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final String mAccountName;
|
||||||
|
|
||||||
|
public AppEngineClient(Context context, String accountName) {
|
||||||
|
this.mContext = context;
|
||||||
|
this.mAccountName = accountName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpResponse makeRequest(String urlPath, List<NameValuePair> params) throws Exception {
|
||||||
|
HttpResponse res = makeRequestNoRetry(urlPath, params, false);
|
||||||
|
if (res.getStatusLine().getStatusCode() == 500) {
|
||||||
|
res = makeRequestNoRetry(urlPath, params, true);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpResponse makeRequestNoRetry(String urlPath, List<NameValuePair> params, boolean newToken)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
// Get auth token for account
|
||||||
|
Account account = new Account(mAccountName, "com.google");
|
||||||
|
String authToken = getAuthToken(mContext, account);
|
||||||
|
if (authToken == null) throw new PendingAuthException(mAccountName);
|
||||||
|
if (newToken) { // invalidate the cached token
|
||||||
|
AccountManager accountManager = AccountManager.get(mContext);
|
||||||
|
accountManager.invalidateAuthToken(account.type, authToken);
|
||||||
|
authToken = getAuthToken(mContext, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get ACSID cookie
|
||||||
|
DefaultHttpClient client = new DefaultHttpClient();
|
||||||
|
String continueURL = BASE_URL;
|
||||||
|
URI uri = new URI(AUTH_URL + "?continue=" +
|
||||||
|
URLEncoder.encode(continueURL, "UTF-8") +
|
||||||
|
"&auth=" + authToken);
|
||||||
|
HttpGet method = new HttpGet(uri);
|
||||||
|
final HttpParams getParams = new BasicHttpParams();
|
||||||
|
HttpClientParams.setRedirecting(getParams, false); // continue is not used
|
||||||
|
method.setParams(getParams);
|
||||||
|
|
||||||
|
HttpResponse res = client.execute(method);
|
||||||
|
Header[] headers = res.getHeaders("Set-Cookie");
|
||||||
|
if (res.getStatusLine().getStatusCode() != 302 ||
|
||||||
|
headers.length == 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ascidCookie = null;
|
||||||
|
for (Header header: headers) {
|
||||||
|
if (header.getValue().indexOf("ACSID=") >=0) {
|
||||||
|
// let's parse it
|
||||||
|
String value = header.getValue();
|
||||||
|
String[] pairs = value.split(";");
|
||||||
|
ascidCookie = pairs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make POST request
|
||||||
|
uri = new URI(BASE_URL + urlPath);
|
||||||
|
HttpPost post = new HttpPost(uri);
|
||||||
|
UrlEncodedFormEntity entity =
|
||||||
|
new UrlEncodedFormEntity(params, "UTF-8");
|
||||||
|
post.setEntity(entity);
|
||||||
|
post.setHeader("Cookie", ascidCookie);
|
||||||
|
post.setHeader("X-Same-Domain", "1"); // XSRF
|
||||||
|
res = client.execute(post);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAuthToken(Context context, Account account) {
|
||||||
|
String authToken = null;
|
||||||
|
AccountManager accountManager = AccountManager.get(context);
|
||||||
|
try {
|
||||||
|
AccountManagerFuture<Bundle> future =
|
||||||
|
accountManager.getAuthToken (account, AUTH_TOKEN_TYPE, false, null, null);
|
||||||
|
Bundle bundle = future.getResult();
|
||||||
|
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
|
||||||
|
// User will be asked for "App Engine" permission.
|
||||||
|
if (authToken == null) {
|
||||||
|
// No auth token - will need to ask permission from user.
|
||||||
|
Intent intent = new Intent(MainActivity.AUTH_PERMISSION_ACTION);
|
||||||
|
intent.putExtra("AccountManagerBundle", bundle);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
} catch (OperationCanceledException e) {
|
||||||
|
Log.w(TAG, e.getMessage());
|
||||||
|
} catch (AuthenticatorException e) {
|
||||||
|
Log.w(TAG, e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PendingAuthException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public PendingAuthException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.chrometophone;
|
package com.google.android.apps.chrometophone;
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
@@ -76,7 +75,7 @@ public class C2DMReceiver extends C2DMBaseReceiver {
|
|||||||
// turn this on for a small percentage of requests or for users
|
// turn this on for a small percentage of requests or for users
|
||||||
// who report issues.
|
// who report issues.
|
||||||
DefaultHttpClient client = new DefaultHttpClient();
|
DefaultHttpClient client = new DefaultHttpClient();
|
||||||
HttpGet get = new HttpGet(DeviceRegistrar.BASE_URL + "/debug?id="
|
HttpGet get = new HttpGet(AppEngineClient.BASE_URL + "/debug?id="
|
||||||
+ extras.get("collapse_key"));
|
+ extras.get("collapse_key"));
|
||||||
// No auth - the purpose is only to generate a log/confirm delivery
|
// No auth - the purpose is only to generate a log/confirm delivery
|
||||||
// (to avoid overhead of getting the token)
|
// (to avoid overhead of getting the token)
|
||||||
|
|||||||
@@ -15,38 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.apps.chrometophone;
|
package com.google.android.apps.chrometophone;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.client.params.HttpClientParams;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
import org.apache.http.params.BasicHttpParams;
|
|
||||||
import org.apache.http.params.HttpParams;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.accounts.AccountManagerFuture;
|
|
||||||
import android.accounts.AuthenticatorException;
|
|
||||||
import android.accounts.OperationCanceledException;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register with the chrometophone appengine server.
|
* Register/unregister with the Chrome to Phone App Engine server.
|
||||||
* Will pass the registration id and user, authenticating with app engine.
|
|
||||||
*/
|
*/
|
||||||
public class DeviceRegistrar {
|
public class DeviceRegistrar {
|
||||||
public static final String STATUS_EXTRA = "Status";
|
public static final String STATUS_EXTRA = "Status";
|
||||||
@@ -57,14 +39,9 @@ public class DeviceRegistrar {
|
|||||||
|
|
||||||
private static final String TAG = "DeviceRegistrar";
|
private static final String TAG = "DeviceRegistrar";
|
||||||
static final String SENDER_ID = "stp.chrome@gmail.com";
|
static final String SENDER_ID = "stp.chrome@gmail.com";
|
||||||
static final String BASE_URL = "https://chrometophone.appspot.com";
|
|
||||||
|
|
||||||
// Appengine authentication
|
private static final String REGISTER_PATH = "/register";
|
||||||
private static final String AUTH_URL = BASE_URL + "/_ah/login";
|
private static final String UNREGISTER_PATH = "/unregister";
|
||||||
private static final String AUTH_TOKEN_TYPE = "ah";
|
|
||||||
|
|
||||||
private static final String REGISTER_URL = BASE_URL + "/register";
|
|
||||||
private static final String UNREGISTER_URL = BASE_URL + "/unregister";
|
|
||||||
|
|
||||||
public static void registerWithServer(final Context context,
|
public static void registerWithServer(final Context context,
|
||||||
final String deviceRegistrationID) {
|
final String deviceRegistrationID) {
|
||||||
@@ -72,7 +49,7 @@ public class DeviceRegistrar {
|
|||||||
public void run() {
|
public void run() {
|
||||||
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
|
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
|
||||||
try {
|
try {
|
||||||
HttpResponse res = makeRequest(context, deviceRegistrationID, REGISTER_URL);
|
HttpResponse res = makeRequest(context, deviceRegistrationID, REGISTER_PATH);
|
||||||
if (res.getStatusLine().getStatusCode() == 200) {
|
if (res.getStatusLine().getStatusCode() == 200) {
|
||||||
SharedPreferences settings = Prefs.get(context);
|
SharedPreferences settings = Prefs.get(context);
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
@@ -87,7 +64,7 @@ public class DeviceRegistrar {
|
|||||||
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
||||||
}
|
}
|
||||||
context.sendBroadcast(updateUIIntent);
|
context.sendBroadcast(updateUIIntent);
|
||||||
} catch (PendingAuthException e) {
|
} catch (AppEngineClient.PendingAuthException pae) {
|
||||||
// Ignore - we'll reregister later
|
// Ignore - we'll reregister later
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Registration error " + e.getMessage());
|
Log.w(TAG, "Registration error " + e.getMessage());
|
||||||
@@ -100,132 +77,41 @@ public class DeviceRegistrar {
|
|||||||
|
|
||||||
public static void unregisterWithServer(final Context context,
|
public static void unregisterWithServer(final Context context,
|
||||||
final String deviceRegistrationID) {
|
final String deviceRegistrationID) {
|
||||||
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
|
new Thread(new Runnable() {
|
||||||
try {
|
public void run() {
|
||||||
HttpResponse res = makeRequest(context, deviceRegistrationID, UNREGISTER_URL);
|
Intent updateUIIntent = new Intent("com.google.ctp.UPDATE_UI");
|
||||||
if (res.getStatusLine().getStatusCode() == 200) {
|
try {
|
||||||
SharedPreferences settings = Prefs.get(context);
|
HttpResponse res = makeRequest(context, deviceRegistrationID, UNREGISTER_PATH);
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
if (res.getStatusLine().getStatusCode() == 200) {
|
||||||
editor.remove("deviceRegistrationID");
|
SharedPreferences settings = Prefs.get(context);
|
||||||
editor.commit();
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
updateUIIntent.putExtra(STATUS_EXTRA, UNREGISTERED_STATUS);
|
editor.remove("deviceRegistrationID");
|
||||||
} else {
|
editor.commit();
|
||||||
Log.w(TAG, "Unregistration error " +
|
updateUIIntent.putExtra(STATUS_EXTRA, UNREGISTERED_STATUS);
|
||||||
String.valueOf(res.getStatusLine().getStatusCode()));
|
} else {
|
||||||
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
Log.w(TAG, "Unregistration error " +
|
||||||
}
|
String.valueOf(res.getStatusLine().getStatusCode()));
|
||||||
} catch (Exception e) {
|
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
||||||
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
}
|
||||||
Log.w(TAG, "Unegistration error " + e.getMessage());
|
} catch (Exception e) {
|
||||||
}
|
updateUIIntent.putExtra(STATUS_EXTRA, ERROR_STATUS);
|
||||||
|
Log.w(TAG, "Unegistration error " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
// Update dialog activity
|
// Update dialog activity
|
||||||
context.sendBroadcast(updateUIIntent);
|
context.sendBroadcast(updateUIIntent);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpResponse makeRequest(Context context, String deviceRegistrationID,
|
private static HttpResponse makeRequest(Context context, String deviceRegistrationID,
|
||||||
String url) throws Exception {
|
String urlPath) throws Exception {
|
||||||
HttpResponse res = makeRequestNoRetry(context, deviceRegistrationID, url,
|
|
||||||
false);
|
|
||||||
if (res.getStatusLine().getStatusCode() == 500) {
|
|
||||||
res = makeRequestNoRetry(context, deviceRegistrationID, url,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpResponse makeRequestNoRetry(Context context, String deviceRegistrationID,
|
|
||||||
String url, boolean newToken) throws Exception {
|
|
||||||
// Get chosen user account
|
|
||||||
SharedPreferences settings = Prefs.get(context);
|
SharedPreferences settings = Prefs.get(context);
|
||||||
String accountName = settings.getString("accountName", null);
|
String accountName = settings.getString("accountName", null);
|
||||||
if (accountName == null) throw new Exception("No account");
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("devregid", deviceRegistrationID));
|
||||||
|
|
||||||
// Get auth token for account
|
AppEngineClient client = new AppEngineClient(context, accountName);
|
||||||
Account account = new Account(accountName, "com.google");
|
return client.makeRequest(urlPath, params);
|
||||||
String authToken = getAuthToken(context, account);
|
|
||||||
if (authToken == null) {
|
|
||||||
throw new PendingAuthException(accountName);
|
|
||||||
}
|
|
||||||
if (newToken) {
|
|
||||||
// Invalidate the cached token
|
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
|
||||||
accountManager.invalidateAuthToken(account.type, authToken);
|
|
||||||
authToken = getAuthToken(context, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register device with server
|
|
||||||
DefaultHttpClient client = new DefaultHttpClient();
|
|
||||||
String continueURL = BASE_URL;
|
|
||||||
|
|
||||||
URI uri = new URI(AUTH_URL + "?continue=" +
|
|
||||||
URLEncoder.encode(continueURL, "UTF-8") +
|
|
||||||
"&auth=" + authToken);
|
|
||||||
HttpGet method = new HttpGet(uri);
|
|
||||||
// No redirect following - continue is not used
|
|
||||||
final HttpParams params = new BasicHttpParams();
|
|
||||||
HttpClientParams.setRedirecting(params, false);
|
|
||||||
method.setParams(params);
|
|
||||||
|
|
||||||
HttpResponse res = client.execute(method);
|
|
||||||
Header[] headers = res.getHeaders("Set-Cookie");
|
|
||||||
if (res.getStatusLine().getStatusCode() != 302 ||
|
|
||||||
headers.length == 0) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
String ascidCookie = null;
|
|
||||||
for (Header header: headers) {
|
|
||||||
if (header.getValue().indexOf("ACSID=") >=0) {
|
|
||||||
// let's parse it
|
|
||||||
String value = header.getValue();
|
|
||||||
String[] pairs = value.split(";");
|
|
||||||
ascidCookie = pairs[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = new URI(url);
|
|
||||||
HttpPost post = new HttpPost(uri);
|
|
||||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
|
||||||
formparams.add(new BasicNameValuePair("devregid", deviceRegistrationID));
|
|
||||||
UrlEncodedFormEntity entity =
|
|
||||||
new UrlEncodedFormEntity(formparams, "UTF-8");
|
|
||||||
post.setEntity(entity);
|
|
||||||
post.setHeader("Cookie", ascidCookie);
|
|
||||||
post.setHeader("X-Same-Domain", "1"); // XSRF
|
|
||||||
res = client.execute(post);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getAuthToken(Context context, Account account) {
|
|
||||||
String authToken = null;
|
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
|
||||||
try {
|
|
||||||
AccountManagerFuture<Bundle> future =
|
|
||||||
accountManager.getAuthToken (account, AUTH_TOKEN_TYPE, false, null, null);
|
|
||||||
Bundle bundle = future.getResult();
|
|
||||||
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
|
|
||||||
// User will be asked for "App Engine" permission.
|
|
||||||
if (authToken == null) {
|
|
||||||
// No auth token - will need to ask permission from user.
|
|
||||||
Intent intent = new Intent(MainActivity.AUTH_PERMISSION_ACTION);
|
|
||||||
intent.putExtra("AccountManagerBundle", bundle);
|
|
||||||
context.sendBroadcast(intent);
|
|
||||||
}
|
|
||||||
} catch (OperationCanceledException e) {
|
|
||||||
Log.w(TAG, e.getMessage());
|
|
||||||
} catch (AuthenticatorException e) {
|
|
||||||
Log.w(TAG, e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, e.getMessage());
|
|
||||||
}
|
|
||||||
return authToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class PendingAuthException extends Exception {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public PendingAuthException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,37 +23,38 @@ public class HelpActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getTOSLink() {
|
public static String getTOSLink() {
|
||||||
String link = "http://m.google.com/toscountry"; // default
|
return constructLink(Locale.getDefault(), "/tospage", "/toscountry");
|
||||||
|
|
||||||
String locale = Locale.getDefault().toString();
|
|
||||||
if (locale.equals(Locale.US.toString())) {
|
|
||||||
link = "http://m.google.com/tospage";
|
|
||||||
} else if (locale.equals(Locale.UK.toString())) {
|
|
||||||
link = "http://m.google.co.uk/tospage";
|
|
||||||
} else if (locale.equals(Locale.CANADA.toString())) {
|
|
||||||
link = "http://m.google.ca/tospage";
|
|
||||||
} else if (locale.equals(Locale.CANADA_FRENCH.toString())) {
|
|
||||||
link = "http://m.google.ca/tospage?hl=fr";
|
|
||||||
} else if (locale.equals(Locale.FRANCE.toString())) {
|
|
||||||
link = "http://m.google.fr/tospage";
|
|
||||||
}
|
|
||||||
return link;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPPLink() {
|
public static String getPPLink() {
|
||||||
String link = "http://m.google.com/privacy"; // default
|
return constructLink(Locale.getDefault(), "/privacy", "/privacy");
|
||||||
|
}
|
||||||
|
|
||||||
String locale = Locale.getDefault().toString();
|
private static String constructLink(Locale locale, String path, String defaultPath) {
|
||||||
if (locale.toString().equals(Locale.US.toString())) {
|
String link = "http://m.google.com" + defaultPath;
|
||||||
link = "http://m.google.com/privacy";
|
String localeString = locale.toString();
|
||||||
} else if (locale.toString().equals(Locale.UK.toString())) {
|
if (localeString.equals(Locale.CANADA.toString())) {
|
||||||
link = "http://m.google.co.uk/privacy";
|
link = "http://m.google.ca" + path;
|
||||||
} else if (locale.toString().equals(Locale.CANADA.toString())) {
|
} else if (localeString.equals(Locale.CANADA_FRENCH.toString())) {
|
||||||
link = "http://m.google.ca/privacy";
|
link = "http://m.google.ca" + path + "?hl=fr";
|
||||||
} else if (locale.toString().equals(Locale.CANADA_FRENCH.toString())) {
|
} else if (localeString.equals(Locale.CHINA.toString())) {
|
||||||
link = "http://m.google.ca/privacy?hl=fr";
|
link = "http://m.google.cn" + path;
|
||||||
} else if (locale.toString().equals(Locale.FRANCE.toString())) {
|
} else if (localeString.equals(Locale.FRANCE.toString())) {
|
||||||
link = "http://m.google.fr/privacy";
|
link = "http://m.google.fr" + path;
|
||||||
|
} else if (localeString.equals(Locale.GERMAN.toString())) {
|
||||||
|
link = "http://m.google.de" + path;
|
||||||
|
} else if (localeString.equals(Locale.ITALY.toString())) {
|
||||||
|
link = "http://m.google.it" + path;
|
||||||
|
} else if (localeString.equals(Locale.JAPAN.toString())) {
|
||||||
|
link = "http://m.google.co.jp" + path;
|
||||||
|
} else if (localeString.equals(Locale.KOREA.toString())) {
|
||||||
|
link = "http://m.google.co.kr" + path;
|
||||||
|
} else if (localeString.equals(Locale.TAIWAN.toString())) {
|
||||||
|
link = "http://m.google.tw" + path;
|
||||||
|
} else if (localeString.equals(Locale.UK.toString())) {
|
||||||
|
link = "http://m.google.co.uk" + path;
|
||||||
|
} else if (localeString.equals(Locale.US.toString())) {
|
||||||
|
link = "http://m.google.com" + path;
|
||||||
}
|
}
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.apps.chrometophone;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class ShareLink implements Handler.Callback {
|
||||||
|
private static final String TOAST = "toast";
|
||||||
|
private static final String BROWSER_CHANNEL_PATH = "/browserchannel";
|
||||||
|
private static ShareLink mInstance;
|
||||||
|
private final Handler mHandler;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
private ShareLink(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mHandler = new Handler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized ShareLink getInstance(Context context) {
|
||||||
|
if (mInstance == null) {
|
||||||
|
mInstance = new ShareLink(context);
|
||||||
|
}
|
||||||
|
return mInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(final String link) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
sendToast(mContext.getString(R.string.sending_link_toast));
|
||||||
|
try {
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("data", link));
|
||||||
|
SharedPreferences settings = Prefs.get(mContext);
|
||||||
|
final String accountName = settings.getString("accountName", null);
|
||||||
|
|
||||||
|
AppEngineClient client = new AppEngineClient(mContext, accountName);
|
||||||
|
HttpResponse res = client.makeRequest(BROWSER_CHANNEL_PATH, params);
|
||||||
|
if (res.getStatusLine().getStatusCode() == 200) {
|
||||||
|
sendToast(mContext.getString(R.string.link_sent_toast));
|
||||||
|
} else {
|
||||||
|
sendToast(mContext.getString(R.string.link_not_sent_toast));
|
||||||
|
}
|
||||||
|
} catch (AppEngineClient.PendingAuthException e) {
|
||||||
|
sendToast(mContext.getString(R.string.link_not_sent_auth_toast));
|
||||||
|
} catch (Exception e) {
|
||||||
|
sendToast(mContext.getString(R.string.link_not_sent_toast));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendToast(String toastMessage) {
|
||||||
|
Message msg = new Message();
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putString(TOAST, toastMessage);
|
||||||
|
msg.setData(data);
|
||||||
|
mHandler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleMessage(Message msg) {
|
||||||
|
Toast.makeText(mContext, msg.getData().getString(TOAST), Toast.LENGTH_LONG).show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.apps.chrometophone;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when user selects "Share page" in the browser. Sends link
|
||||||
|
* to AppEngine server.
|
||||||
|
*/
|
||||||
|
public class ShareLinkActivity extends Activity {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (Intent.ACTION_SEND.equals(getIntent().getAction())) {
|
||||||
|
String link = getIntent().getExtras().getString(Intent.EXTRA_TEXT);
|
||||||
|
ShareLink.getInstance(this).send(link);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user