<!-- Makes .BrowserActivity the search target for any activity in Browser -->
<meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" />
+ <!-- Application code for RLZ tracking. RLZ assigns non-unique, non-personally identifiable
+ tracking labels to client products; these labels sometimes appear in Google search
+ queries. See http://code.google.com/p/rlz for more info.
+
+ This value signifies to the RLZ client that this application uses RLZ tracking. -->
+ <meta-data android:name="com.google.android.partnersetup.RLZ_ACCESS_POINT"
+ android:value="@string/rlz_access_point" />
+ <receiver android:name=".RlzReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.RLZ_VALUES_UPDATED"/>
+ </intent-filter>
+ </receiver>
+
<receiver android:name=".OpenDownloadReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
<string name="error_console_eval_text_hint" translatable="false">Evaluate JavaScript</string>
<string name="error_console_eval_button_text" translatable="false">Evaluate</string>
+ <!-- Access point for RLZ tracking. -->
+ <string name="rlz_access_point" translatable="false">Y1</string>
</resources>
// Keep a settings instance handy.
mSettings = BrowserSettings.getInstance();
+ mSettings.updateRlzValues(this);
+
// If this was a web search request, pass it on to the default web
// search provider and finish this activity.
if (handleWebSearchIntent(getIntent())) {
headers.put(key, pairs.getString(key));
}
}
+
+ // AppId will be set to the Browser for Search Bar initiated searches
+ final String appId = intent.getStringExtra(Browser.EXTRA_APPLICATION_ID);
+ if (getPackageName().equals(appId)) {
+ String rlz = mSettings.getRlzValue();
+ Uri uri = Uri.parse(url);
+ if (!rlz.isEmpty() && needsRlz(uri)) {
+ Uri rlzUri = addRlzParameter(uri, rlz);
+ url = rlzUri.toString();
+ }
+ }
}
} else if (Intent.ACTION_SEARCH.equals(action)
|| MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
};
/* package */ static final UrlData EMPTY_URL_DATA = new UrlData(null);
+
+ private static boolean needsRlz(Uri uri) {
+ if ((uri.getQueryParameter("rlz") == null) &&
+ (uri.getQueryParameter("q") != null) &&
+ UrlUtils.isGoogleUri(uri)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static Uri addRlzParameter(Uri uri, String rlz) {
+ if (rlz.isEmpty()) {
+ return uri;
+ }
+ return uri.buildUpon().appendQueryParameter("rlz", rlz).build();
+ }
}
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Handler;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
+import android.provider.Browser.BookmarkColumns;
import android.provider.Settings;
import android.util.Log;
import android.webkit.CookieManager;
// a ListView
public final static int MAX_TEXTVIEW_LEN = 80;
+ public static final String RLZ_PROVIDER = "com.google.android.partnersetup.rlzappprovider";
+ public static final Uri RLZ_PROVIDER_URI = Uri.parse("content://" + RLZ_PROVIDER + "/");
+
+ private String mRlzValue = "";
+
private TabControl mTabControl;
// Single instance of the BrowserSettings for use in the Browser app.
geolocationEnabled = true;
workersEnabled = true; // only affects V8. JSC does not have a similar setting
}
+
+ /*package*/ String getRlzValue() {
+ return mRlzValue;
+ }
+
+ /*package*/ void updateRlzValues(Context context) {
+ // Use AsyncTask because this queries both RlzProvider and Bookmarks URIs
+ new RlzUpdateTask(context).execute();
+ }
+
+ private class RlzUpdateTask extends AsyncTask<Void, Void, Void> {
+ private final Context context;
+
+ public RlzUpdateTask(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ protected Void doInBackground(Void...unused) {
+ String rlz = retrieveRlzValue(context);
+ if (!rlz.isEmpty()) {
+ mRlzValue = rlz;
+ updateHomePageRlzParameter(context);
+ updateBookmarksRlzParameter(context);
+ }
+ return null;
+ }
+ }
+
+ // Update RLZ value if present in Home page
+ private void updateHomePageRlzParameter(Context context) {
+ Uri uri = Uri.parse(homeUrl);
+ if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) {
+ String newHomeUrl = updateRlzParameter(homeUrl);
+ if (!homeUrl.equals(newHomeUrl)) {
+ setHomePage(context, newHomeUrl);
+ }
+ }
+ }
+
+ // Update RLZ value if present in bookmarks
+ private void updateBookmarksRlzParameter(Context context) {
+ Cursor cur = null;
+ try {
+ cur = context.getContentResolver().query(Browser.BOOKMARKS_URI,
+ new String[] { BookmarkColumns._ID, BookmarkColumns.URL },
+ "url LIKE '%rlz=%'", null, null);
+ if ((cur == null) || (cur.getCount() == 0)) {
+ return;
+ }
+ for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {
+ long id = cur.getLong(0);
+ String url = cur.getString(1);
+ if ((url == null) || url.isEmpty()) {
+ continue;
+ }
+
+ Uri uri = Uri.parse(url);
+ if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) {
+ String newUrl = updateRlzParameter(url);
+ if (!url.equals(newUrl)) {
+ ContentValues values = new ContentValues();
+ values.put(BookmarkColumns.URL, newUrl);
+ Uri bookmarkUri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI, id);
+ context.getContentResolver().update(bookmarkUri, values, null, null);
+ }
+ }
+ }
+ } finally {
+ if (cur != null) {
+ cur.close();
+ }
+ }
+ }
+
+ private String updateRlzParameter(String url) {
+ Uri uri = Uri.parse(url);
+ String oldRlz = uri.getQueryParameter("rlz");
+ if (oldRlz != null) {
+ return url.replace("rlz=" + oldRlz, "rlz=" + mRlzValue);
+ }
+ return url;
+ }
+
+ // Retrieve the RLZ value from the Rlz Provider
+ private static String retrieveRlzValue(Context context) {
+ String rlz = "";
+ PackageManager pm = context.getPackageManager();
+ if (pm.resolveContentProvider(RLZ_PROVIDER, 0) == null) {
+ return rlz;
+ }
+
+ String ap = context.getResources().getString(R.string.rlz_access_point);
+ if (ap.isEmpty()) {
+ return rlz;
+ }
+
+ Uri rlzUri = Uri.withAppendedPath(RLZ_PROVIDER_URI, ap);
+ Cursor cur = null;
+ try {
+ cur = context.getContentResolver().query(rlzUri, null, null, null, null);
+ if (cur != null && cur.moveToFirst() && !cur.isNull(0)) {
+ rlz = cur.getString(0);
+ }
+ } finally {
+ if (cur != null) {
+ cur.close();
+ }
+ }
+ return rlz;
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.android.browser;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * This {@link BroadcastReceiver} handles RLZ broadcast notifications.
+ */
+public class RlzReceiver extends BroadcastReceiver {
+ public static final String RLZ_VALUES_UPDATED_ACTION =
+ "android.intent.action.RLZ_VALUES_UPDATED";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (RLZ_VALUES_UPDATED_ACTION.equals(action)) {
+ BrowserSettings settings = BrowserSettings.getInstance();
+ settings.updateRlzValues(context);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.browser;
+
+import android.net.Uri;
+
+/**
+ * Utility methods for Url manipulation
+ */
+public class UrlUtils {
+ // Determine if this URI appears to be a Google property
+ /* package */ static boolean isGoogleUri(Uri uri) {
+ String scheme = uri.getScheme();
+ if (!"http".equals(scheme) && !"https".equals(scheme)) {
+ return false;
+ }
+
+ String host = uri.getHost();
+ if (host == null) {
+ return false;
+ }
+ String[] hostComponents = host.split("\\.");
+ if (hostComponents.length < 2) {
+ return false;
+ }
+
+ int googleComponent = hostComponents.length - 2;
+ String component = hostComponents[googleComponent];
+ if (!"google".equals(component)) {
+ if (hostComponents.length < 3 ||
+ (!"co".equals(component) && !"com".equals(component))) {
+ return false;
+ }
+ googleComponent = hostComponents.length - 3;
+ if (!"google".equals(hostComponents[googleComponent])) {
+ return false;
+ }
+ }
+ return true;
+ }
+}