packages/apps/Browser
Revision | 8ba13bcb1ad5ab8b439fcc53d158bdafa327a2e8 (tree) |
---|---|
Time | 2011-05-18 09:58:04 |
Author | Ed Tam <etam@goog...> |
Commiter | Ed Tam |
DO NOT MERGE - Backport RLZ code to GB:
Bug: 4436761
Change-Id: I7ce0e7bead7954ed9ebfe10b66242553f14ed6f2
@@ -197,6 +197,19 @@ | ||
197 | 197 | <!-- Makes .BrowserActivity the search target for any activity in Browser --> |
198 | 198 | <meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" /> |
199 | 199 | |
200 | + <!-- Application code for RLZ tracking. RLZ assigns non-unique, non-personally identifiable | |
201 | + tracking labels to client products; these labels sometimes appear in Google search | |
202 | + queries. See http://code.google.com/p/rlz for more info. | |
203 | + | |
204 | + This value signifies to the RLZ client that this application uses RLZ tracking. --> | |
205 | + <meta-data android:name="com.google.android.partnersetup.RLZ_ACCESS_POINT" | |
206 | + android:value="@string/rlz_access_point" /> | |
207 | + <receiver android:name=".RlzReceiver"> | |
208 | + <intent-filter> | |
209 | + <action android:name="android.intent.action.RLZ_VALUES_UPDATED"/> | |
210 | + </intent-filter> | |
211 | + </receiver> | |
212 | + | |
200 | 213 | <receiver android:name=".OpenDownloadReceiver"> |
201 | 214 | <intent-filter> |
202 | 215 | <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/> |
@@ -753,4 +753,6 @@ | ||
753 | 753 | <string name="error_console_eval_text_hint" translatable="false">Evaluate JavaScript</string> |
754 | 754 | <string name="error_console_eval_button_text" translatable="false">Evaluate</string> |
755 | 755 | |
756 | + <!-- Access point for RLZ tracking. --> | |
757 | + <string name="rlz_access_point" translatable="false">Y1</string> | |
756 | 758 | </resources> |
@@ -188,6 +188,8 @@ public class BrowserActivity extends Activity | ||
188 | 188 | // Keep a settings instance handy. |
189 | 189 | mSettings = BrowserSettings.getInstance(); |
190 | 190 | |
191 | + mSettings.updateRlzValues(this); | |
192 | + | |
191 | 193 | // If this was a web search request, pass it on to the default web |
192 | 194 | // search provider and finish this activity. |
193 | 195 | if (handleWebSearchIntent(getIntent())) { |
@@ -633,6 +635,17 @@ public class BrowserActivity extends Activity | ||
633 | 635 | headers.put(key, pairs.getString(key)); |
634 | 636 | } |
635 | 637 | } |
638 | + | |
639 | + // AppId will be set to the Browser for Search Bar initiated searches | |
640 | + final String appId = intent.getStringExtra(Browser.EXTRA_APPLICATION_ID); | |
641 | + if (getPackageName().equals(appId)) { | |
642 | + String rlz = mSettings.getRlzValue(); | |
643 | + Uri uri = Uri.parse(url); | |
644 | + if (!rlz.isEmpty() && needsRlz(uri)) { | |
645 | + Uri rlzUri = addRlzParameter(uri, rlz); | |
646 | + url = rlzUri.toString(); | |
647 | + } | |
648 | + } | |
636 | 649 | } |
637 | 650 | } else if (Intent.ACTION_SEARCH.equals(action) |
638 | 651 | || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action) |
@@ -4003,4 +4016,20 @@ public class BrowserActivity extends Activity | ||
4003 | 4016 | }; |
4004 | 4017 | |
4005 | 4018 | /* package */ static final UrlData EMPTY_URL_DATA = new UrlData(null); |
4019 | + | |
4020 | + private static boolean needsRlz(Uri uri) { | |
4021 | + if ((uri.getQueryParameter("rlz") == null) && | |
4022 | + (uri.getQueryParameter("q") != null) && | |
4023 | + UrlUtils.isGoogleUri(uri)) { | |
4024 | + return true; | |
4025 | + } | |
4026 | + return false; | |
4027 | + } | |
4028 | + | |
4029 | + private static Uri addRlzParameter(Uri uri, String rlz) { | |
4030 | + if (rlz.isEmpty()) { | |
4031 | + return uri; | |
4032 | + } | |
4033 | + return uri.buildUpon().appendQueryParameter("rlz", rlz).build(); | |
4034 | + } | |
4006 | 4035 | } |
@@ -23,14 +23,21 @@ import com.android.browser.search.SearchEngines; | ||
23 | 23 | import android.app.ActivityManager; |
24 | 24 | import android.content.ComponentName; |
25 | 25 | import android.content.ContentResolver; |
26 | +import android.content.ContentUris; | |
27 | +import android.content.ContentValues; | |
26 | 28 | import android.content.Context; |
27 | 29 | import android.content.pm.ActivityInfo; |
30 | +import android.content.pm.PackageManager; | |
28 | 31 | import android.content.SharedPreferences; |
29 | 32 | import android.content.SharedPreferences.Editor; |
30 | 33 | import android.database.ContentObserver; |
34 | +import android.database.Cursor; | |
35 | +import android.net.Uri; | |
36 | +import android.os.AsyncTask; | |
31 | 37 | import android.os.Handler; |
32 | 38 | import android.preference.PreferenceActivity; |
33 | 39 | import android.preference.PreferenceScreen; |
40 | +import android.provider.Browser.BookmarkColumns; | |
34 | 41 | import android.provider.Settings; |
35 | 42 | import android.util.Log; |
36 | 43 | import android.webkit.CookieManager; |
@@ -166,6 +173,11 @@ class BrowserSettings extends Observable { | ||
166 | 173 | // a ListView |
167 | 174 | public final static int MAX_TEXTVIEW_LEN = 80; |
168 | 175 | |
176 | + public static final String RLZ_PROVIDER = "com.google.android.partnersetup.rlzappprovider"; | |
177 | + public static final Uri RLZ_PROVIDER_URI = Uri.parse("content://" + RLZ_PROVIDER + "/"); | |
178 | + | |
179 | + private String mRlzValue = ""; | |
180 | + | |
169 | 181 | private TabControl mTabControl; |
170 | 182 | |
171 | 183 | // Single instance of the BrowserSettings for use in the Browser app. |
@@ -653,4 +665,115 @@ class BrowserSettings extends Observable { | ||
653 | 665 | geolocationEnabled = true; |
654 | 666 | workersEnabled = true; // only affects V8. JSC does not have a similar setting |
655 | 667 | } |
668 | + | |
669 | + /*package*/ String getRlzValue() { | |
670 | + return mRlzValue; | |
671 | + } | |
672 | + | |
673 | + /*package*/ void updateRlzValues(Context context) { | |
674 | + // Use AsyncTask because this queries both RlzProvider and Bookmarks URIs | |
675 | + new RlzUpdateTask(context).execute(); | |
676 | + } | |
677 | + | |
678 | + private class RlzUpdateTask extends AsyncTask<Void, Void, Void> { | |
679 | + private final Context context; | |
680 | + | |
681 | + public RlzUpdateTask(Context context) { | |
682 | + this.context = context; | |
683 | + } | |
684 | + | |
685 | + @Override | |
686 | + protected Void doInBackground(Void...unused) { | |
687 | + String rlz = retrieveRlzValue(context); | |
688 | + if (!rlz.isEmpty()) { | |
689 | + mRlzValue = rlz; | |
690 | + updateHomePageRlzParameter(context); | |
691 | + updateBookmarksRlzParameter(context); | |
692 | + } | |
693 | + return null; | |
694 | + } | |
695 | + } | |
696 | + | |
697 | + // Update RLZ value if present in Home page | |
698 | + private void updateHomePageRlzParameter(Context context) { | |
699 | + Uri uri = Uri.parse(homeUrl); | |
700 | + if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) { | |
701 | + String newHomeUrl = updateRlzParameter(homeUrl); | |
702 | + if (!homeUrl.equals(newHomeUrl)) { | |
703 | + setHomePage(context, newHomeUrl); | |
704 | + } | |
705 | + } | |
706 | + } | |
707 | + | |
708 | + // Update RLZ value if present in bookmarks | |
709 | + private void updateBookmarksRlzParameter(Context context) { | |
710 | + Cursor cur = null; | |
711 | + try { | |
712 | + cur = context.getContentResolver().query(Browser.BOOKMARKS_URI, | |
713 | + new String[] { BookmarkColumns._ID, BookmarkColumns.URL }, | |
714 | + "url LIKE '%rlz=%'", null, null); | |
715 | + if ((cur == null) || (cur.getCount() == 0)) { | |
716 | + return; | |
717 | + } | |
718 | + for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { | |
719 | + long id = cur.getLong(0); | |
720 | + String url = cur.getString(1); | |
721 | + if ((url == null) || url.isEmpty()) { | |
722 | + continue; | |
723 | + } | |
724 | + | |
725 | + Uri uri = Uri.parse(url); | |
726 | + if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) { | |
727 | + String newUrl = updateRlzParameter(url); | |
728 | + if (!url.equals(newUrl)) { | |
729 | + ContentValues values = new ContentValues(); | |
730 | + values.put(BookmarkColumns.URL, newUrl); | |
731 | + Uri bookmarkUri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI, id); | |
732 | + context.getContentResolver().update(bookmarkUri, values, null, null); | |
733 | + } | |
734 | + } | |
735 | + } | |
736 | + } finally { | |
737 | + if (cur != null) { | |
738 | + cur.close(); | |
739 | + } | |
740 | + } | |
741 | + } | |
742 | + | |
743 | + private String updateRlzParameter(String url) { | |
744 | + Uri uri = Uri.parse(url); | |
745 | + String oldRlz = uri.getQueryParameter("rlz"); | |
746 | + if (oldRlz != null) { | |
747 | + return url.replace("rlz=" + oldRlz, "rlz=" + mRlzValue); | |
748 | + } | |
749 | + return url; | |
750 | + } | |
751 | + | |
752 | + // Retrieve the RLZ value from the Rlz Provider | |
753 | + private static String retrieveRlzValue(Context context) { | |
754 | + String rlz = ""; | |
755 | + PackageManager pm = context.getPackageManager(); | |
756 | + if (pm.resolveContentProvider(RLZ_PROVIDER, 0) == null) { | |
757 | + return rlz; | |
758 | + } | |
759 | + | |
760 | + String ap = context.getResources().getString(R.string.rlz_access_point); | |
761 | + if (ap.isEmpty()) { | |
762 | + return rlz; | |
763 | + } | |
764 | + | |
765 | + Uri rlzUri = Uri.withAppendedPath(RLZ_PROVIDER_URI, ap); | |
766 | + Cursor cur = null; | |
767 | + try { | |
768 | + cur = context.getContentResolver().query(rlzUri, null, null, null, null); | |
769 | + if (cur != null && cur.moveToFirst() && !cur.isNull(0)) { | |
770 | + rlz = cur.getString(0); | |
771 | + } | |
772 | + } finally { | |
773 | + if (cur != null) { | |
774 | + cur.close(); | |
775 | + } | |
776 | + } | |
777 | + return rlz; | |
778 | + } | |
656 | 779 | } |
@@ -0,0 +1,38 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2011 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +package com.android.browser; | |
18 | + | |
19 | +import android.content.BroadcastReceiver; | |
20 | +import android.content.Context; | |
21 | +import android.content.Intent; | |
22 | + | |
23 | +/** | |
24 | + * This {@link BroadcastReceiver} handles RLZ broadcast notifications. | |
25 | + */ | |
26 | +public class RlzReceiver extends BroadcastReceiver { | |
27 | + public static final String RLZ_VALUES_UPDATED_ACTION = | |
28 | + "android.intent.action.RLZ_VALUES_UPDATED"; | |
29 | + | |
30 | + @Override | |
31 | + public void onReceive(Context context, Intent intent) { | |
32 | + String action = intent.getAction(); | |
33 | + if (RLZ_VALUES_UPDATED_ACTION.equals(action)) { | |
34 | + BrowserSettings settings = BrowserSettings.getInstance(); | |
35 | + settings.updateRlzValues(context); | |
36 | + } | |
37 | + } | |
38 | +} |
@@ -0,0 +1,55 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2010 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +package com.android.browser; | |
18 | + | |
19 | +import android.net.Uri; | |
20 | + | |
21 | +/** | |
22 | + * Utility methods for Url manipulation | |
23 | + */ | |
24 | +public class UrlUtils { | |
25 | + // Determine if this URI appears to be a Google property | |
26 | + /* package */ static boolean isGoogleUri(Uri uri) { | |
27 | + String scheme = uri.getScheme(); | |
28 | + if (!"http".equals(scheme) && !"https".equals(scheme)) { | |
29 | + return false; | |
30 | + } | |
31 | + | |
32 | + String host = uri.getHost(); | |
33 | + if (host == null) { | |
34 | + return false; | |
35 | + } | |
36 | + String[] hostComponents = host.split("\\."); | |
37 | + if (hostComponents.length < 2) { | |
38 | + return false; | |
39 | + } | |
40 | + | |
41 | + int googleComponent = hostComponents.length - 2; | |
42 | + String component = hostComponents[googleComponent]; | |
43 | + if (!"google".equals(component)) { | |
44 | + if (hostComponents.length < 3 || | |
45 | + (!"co".equals(component) && !"com".equals(component))) { | |
46 | + return false; | |
47 | + } | |
48 | + googleComponent = hostComponents.length - 3; | |
49 | + if (!"google".equals(hostComponents[googleComponent])) { | |
50 | + return false; | |
51 | + } | |
52 | + } | |
53 | + return true; | |
54 | + } | |
55 | +} |