mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package org.mozilla.gecko.distribution;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* A distribution ready callback that will store the distribution ID to profile-specific shared preferences.
|
||||
*/
|
||||
public class DistributionStoreCallback implements Distribution.ReadyCallback {
|
||||
private static final String LOGTAG = "Gecko" + DistributionStoreCallback.class.getSimpleName();
|
||||
|
||||
public static final String PREF_DISTRIBUTION_ID = "distribution.id";
|
||||
|
||||
private final WeakReference<Context> contextReference;
|
||||
private final String profileName;
|
||||
|
||||
public DistributionStoreCallback(final Context context, final String profileName) {
|
||||
this.contextReference = new WeakReference<>(context);
|
||||
this.profileName = profileName;
|
||||
}
|
||||
|
||||
public void distributionNotFound() { /* nothing to do here */ }
|
||||
|
||||
@Override
|
||||
public void distributionFound(final Distribution distribution) {
|
||||
storeDistribution(distribution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distributionArrivedLate(final Distribution distribution) {
|
||||
storeDistribution(distribution);
|
||||
}
|
||||
|
||||
private void storeDistribution(final Distribution distribution) {
|
||||
final Context context = contextReference.get();
|
||||
if (context == null) {
|
||||
Log.w(LOGTAG, "Context is no longer alive, could retrieve shared prefs to store distribution");
|
||||
return;
|
||||
}
|
||||
|
||||
// While the distribution preferences are per install and not per profile, it's okay to use the
|
||||
// profile-specific prefs because:
|
||||
// 1) We don't really support mulitple profiles for end-users
|
||||
// 2) The TelemetryUploadService already accesses profile-specific shared prefs so this keeps things simple.
|
||||
final SharedPreferences sharedPrefs = GeckoSharedPrefs.forProfileName(context, profileName);
|
||||
final Distribution.DistributionDescriptor desc = distribution.getDescriptor();
|
||||
if (desc != null) {
|
||||
sharedPrefs.edit().putString(PREF_DISTRIBUTION_ID, desc.id).apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,322 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.distribution;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A proxy for the partner bookmarks provider. Bookmark and folder ids of the partner bookmarks providers
|
||||
* will be transformed so that they do not overlap with the ids from the local database.
|
||||
*
|
||||
* Bookmarks in folder:
|
||||
* content://{PACKAGE_ID}.partnerbookmarks/bookmarks/{folderId}
|
||||
* Icon of bookmark:
|
||||
* content://{PACKAGE_ID}.partnerbookmarks/icons/{bookmarkId}
|
||||
*/
|
||||
public class PartnerBookmarksProviderProxy extends ContentProvider {
|
||||
/**
|
||||
* The contract between the partner bookmarks provider and applications. Contains the definition
|
||||
* for the supported URIs and columns.
|
||||
*/
|
||||
public static class PartnerContract {
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://com.android.partnerbookmarks/bookmarks");
|
||||
|
||||
public static final int TYPE_BOOKMARK = 1;
|
||||
public static final int TYPE_FOLDER = 2;
|
||||
|
||||
public static final int PARENT_ROOT_ID = 0;
|
||||
|
||||
public static final String ID = "_id";
|
||||
public static final String TYPE = "type";
|
||||
public static final String URL = "url";
|
||||
public static final String TITLE = "title";
|
||||
public static final String FAVICON = "favicon";
|
||||
public static final String TOUCHICON = "touchicon";
|
||||
public static final String PARENT = "parent";
|
||||
}
|
||||
|
||||
private static final String AUTHORITY_PREFIX = ".partnerbookmarks";
|
||||
|
||||
private static final int URI_MATCH_BOOKMARKS = 1000;
|
||||
private static final int URI_MATCH_ICON = 1001;
|
||||
private static final int URI_MATCH_BOOKMARK = 1002;
|
||||
|
||||
private static final String PREF_DELETED_PARTNER_BOOKMARKS = "distribution.partner.bookmark.deleted";
|
||||
|
||||
/**
|
||||
* Cursor wrapper for filtering empty folders.
|
||||
*/
|
||||
private static class FilteredCursor extends CursorWrapper {
|
||||
private HashSet<Integer> emptyFolderPositions;
|
||||
private int count;
|
||||
|
||||
public FilteredCursor(PartnerBookmarksProviderProxy proxy, Cursor cursor) {
|
||||
super(cursor);
|
||||
|
||||
emptyFolderPositions = new HashSet<>();
|
||||
count = cursor.getCount();
|
||||
|
||||
for (int i = 0; i < cursor.getCount(); i++) {
|
||||
cursor.moveToPosition(i);
|
||||
|
||||
final long id = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Bookmarks._ID));
|
||||
final int type = cursor.getInt(cursor.getColumnIndexOrThrow(BrowserContract.Bookmarks.TYPE));
|
||||
|
||||
if (type == BrowserContract.Bookmarks.TYPE_FOLDER && proxy.isFolderEmpty(id)) {
|
||||
// We do not support deleting folders. So at least hide partner folders that are
|
||||
// empty because all bookmarks inside it are deleted/hidden.
|
||||
// Note that this will still show folders with empty folders in them. But multi-level
|
||||
// partner bookmarks are very unlikely.
|
||||
|
||||
count--;
|
||||
emptyFolderPositions.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToPosition(int position) {
|
||||
final Cursor cursor = getWrappedCursor();
|
||||
final int actualCount = cursor.getCount();
|
||||
|
||||
// Find the next position pointing to a bookmark or a non-empty folder
|
||||
while (position < actualCount && emptyFolderPositions.contains(position)) {
|
||||
position++;
|
||||
}
|
||||
|
||||
return position < actualCount && cursor.moveToPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getAuthority(Context context) {
|
||||
return context.getPackageName() + AUTHORITY_PREFIX;
|
||||
}
|
||||
|
||||
public static Uri getUriForBookmarks(Context context, long folderId) {
|
||||
return new Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(getAuthority(context))
|
||||
.appendPath("bookmarks")
|
||||
.appendPath(String.valueOf(folderId))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getUriForIcon(Context context, long bookmarkId) {
|
||||
return new Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(getAuthority(context))
|
||||
.appendPath("icons")
|
||||
.appendPath(String.valueOf(bookmarkId))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getUriForBookmark(Context context, long bookmarkId) {
|
||||
return new Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(getAuthority(context))
|
||||
.appendPath("bookmark")
|
||||
.appendPath(String.valueOf(bookmarkId))
|
||||
.build();
|
||||
}
|
||||
|
||||
private final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
String authority = getAuthority(assertAndGetContext());
|
||||
|
||||
uriMatcher.addURI(authority, "bookmarks/*", URI_MATCH_BOOKMARKS);
|
||||
uriMatcher.addURI(authority, "icons/*", URI_MATCH_ICON);
|
||||
uriMatcher.addURI(authority, "bookmark/*", URI_MATCH_BOOKMARK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
final Context context = assertAndGetContext();
|
||||
final int match = uriMatcher.match(uri);
|
||||
|
||||
final ContentResolver contentResolver = context.getContentResolver();
|
||||
|
||||
switch (match) {
|
||||
case URI_MATCH_BOOKMARKS:
|
||||
final long bookmarkId = ContentUris.parseId(uri);
|
||||
if (bookmarkId == -1) {
|
||||
throw new IllegalArgumentException("Bookmark id is not a number");
|
||||
}
|
||||
final Cursor cursor = getBookmarksInFolder(contentResolver, bookmarkId);
|
||||
cursor.setNotificationUri(context.getContentResolver(), uri);
|
||||
return new FilteredCursor(this, cursor);
|
||||
|
||||
case URI_MATCH_ICON:
|
||||
return getIcon(contentResolver, ContentUris.parseId(uri));
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI " + uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||
final int match = uriMatcher.match(uri);
|
||||
|
||||
switch (match) {
|
||||
case URI_MATCH_BOOKMARK:
|
||||
rememberRemovedBookmark(ContentUris.parseId(uri));
|
||||
notifyBookmarkChange();
|
||||
return 1;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI " + uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyBookmarkChange() {
|
||||
final Context context = assertAndGetContext();
|
||||
|
||||
context.getContentResolver().notifyChange(
|
||||
new Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(getAuthority(context))
|
||||
.appendPath("bookmarks")
|
||||
.build(),
|
||||
null);
|
||||
}
|
||||
|
||||
private synchronized void rememberRemovedBookmark(long bookmarkId) {
|
||||
Set<String> deletedIds = getRemovedBookmarkIds();
|
||||
|
||||
deletedIds.add(String.valueOf(bookmarkId));
|
||||
|
||||
GeckoSharedPrefs.forProfile(assertAndGetContext())
|
||||
.edit()
|
||||
.putStringSet(PREF_DELETED_PARTNER_BOOKMARKS, deletedIds)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private synchronized Set<String> getRemovedBookmarkIds() {
|
||||
SharedPreferences preferences = GeckoSharedPrefs.forProfile(assertAndGetContext());
|
||||
return preferences.getStringSet(PREF_DELETED_PARTNER_BOOKMARKS, new HashSet<String>());
|
||||
}
|
||||
|
||||
private Cursor getBookmarksInFolder(ContentResolver contentResolver, long folderId) {
|
||||
// Use root folder id or transform negative id into actual (positive) folder id.
|
||||
final long actualFolderId = folderId == BrowserContract.Bookmarks.FIXED_ROOT_ID
|
||||
? PartnerContract.PARENT_ROOT_ID
|
||||
: BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START - folderId;
|
||||
|
||||
final String removedBookmarkIds = TextUtils.join(",", getRemovedBookmarkIds());
|
||||
|
||||
return contentResolver.query(
|
||||
PartnerContract.CONTENT_URI,
|
||||
new String[] {
|
||||
// Transform ids into negative values starting with FAKE_PARTNER_BOOKMARKS_START.
|
||||
"(" + BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START + " - " + PartnerContract.ID + ") as " + BrowserContract.Bookmarks._ID,
|
||||
"(" + BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START + " - " + PartnerContract.ID + ") as " + BrowserContract.Combined.BOOKMARK_ID,
|
||||
PartnerContract.TITLE + " as " + BrowserContract.Bookmarks.TITLE,
|
||||
PartnerContract.URL + " as " + BrowserContract.Bookmarks.URL,
|
||||
// Transform parent ids to negative ids as well
|
||||
"(" + BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START + " - " + PartnerContract.PARENT + ") as " + BrowserContract.Bookmarks.PARENT,
|
||||
// Convert types (we use 0-1 and the partner provider 1-2)
|
||||
"(2 - " + PartnerContract.TYPE + ") as " + BrowserContract.Bookmarks.TYPE,
|
||||
// Use the ID of the entry as GUID
|
||||
PartnerContract.ID + " as " + BrowserContract.Bookmarks.GUID
|
||||
},
|
||||
PartnerContract.PARENT + " = ?"
|
||||
// We only want to read bookmarks or folders from the content provider
|
||||
+ " AND " + BrowserContract.Bookmarks.TYPE + " IN (?,?)"
|
||||
// Only select entries with non empty title
|
||||
+ " AND " + BrowserContract.Bookmarks.TITLE + " <> ''"
|
||||
// Filter all "deleted" ids
|
||||
+ " AND " + BrowserContract.Combined.BOOKMARK_ID + " NOT IN (" + removedBookmarkIds + ")",
|
||||
new String[] {
|
||||
String.valueOf(actualFolderId),
|
||||
String.valueOf(PartnerContract.TYPE_BOOKMARK),
|
||||
String.valueOf(PartnerContract.TYPE_FOLDER)
|
||||
},
|
||||
// Same order we use in our content provider (without position)
|
||||
BrowserContract.Bookmarks.TYPE + " ASC, " + BrowserContract.Bookmarks._ID + " ASC");
|
||||
}
|
||||
|
||||
private boolean isFolderEmpty(long folderId) {
|
||||
final Context context = assertAndGetContext();
|
||||
final Cursor cursor = getBookmarksInFolder(context.getContentResolver(), folderId);
|
||||
|
||||
if (cursor == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return cursor.getCount() == 0;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private Cursor getIcon(ContentResolver contentResolver, long bookmarkId) {
|
||||
final long actualId = BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START - bookmarkId;
|
||||
|
||||
return contentResolver.query(
|
||||
PartnerContract.CONTENT_URI,
|
||||
new String[] {
|
||||
PartnerContract.TOUCHICON,
|
||||
PartnerContract.FAVICON
|
||||
},
|
||||
PartnerContract.ID + " = ?",
|
||||
new String[] {
|
||||
String.valueOf(actualId)
|
||||
},
|
||||
null);
|
||||
}
|
||||
|
||||
private Context assertAndGetContext() {
|
||||
final Context context = super.getContext();
|
||||
|
||||
if (context == null) {
|
||||
throw new AssertionError("Context is null");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.distribution;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* Client for accessing data from Android's "partner browser customizations" content provider.
|
||||
*/
|
||||
public class PartnerBrowserCustomizationsClient {
|
||||
private static final Uri CONTENT_URI = Uri.parse("content://com.android.partnerbrowsercustomizations");
|
||||
|
||||
private static final Uri HOMEPAGE_URI = CONTENT_URI.buildUpon().path("homepage").build();
|
||||
|
||||
private static final String COLUMN_HOMEPAGE = "homepage";
|
||||
|
||||
/**
|
||||
* Returns the partner homepage or null if it could not be read from the content provider.
|
||||
*/
|
||||
public static String getHomepage(Context context) {
|
||||
Cursor cursor = context.getContentResolver().query(
|
||||
HOMEPAGE_URI, new String[] { COLUMN_HOMEPAGE }, null, null, null);
|
||||
|
||||
if (cursor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!cursor.moveToFirst()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_HOMEPAGE));
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.distribution;
|
||||
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Encapsulates access to values encoded in the "referrer" extra of an install intent.
|
||||
*
|
||||
* This object is immutable.
|
||||
*
|
||||
* Example input:
|
||||
*
|
||||
* "utm_source=campsource&utm_medium=campmed&utm_term=term%2Bhere&utm_content=content&utm_campaign=name"
|
||||
*/
|
||||
@RobocopTarget
|
||||
public class ReferrerDescriptor {
|
||||
public final String source;
|
||||
public final String medium;
|
||||
public final String term;
|
||||
public final String content;
|
||||
public final String campaign;
|
||||
|
||||
public ReferrerDescriptor(String referrer) {
|
||||
if (referrer == null) {
|
||||
source = null;
|
||||
medium = null;
|
||||
term = null;
|
||||
content = null;
|
||||
campaign = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
referrer = URLDecoder.decode(referrer, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// UTF-8 is always supported
|
||||
}
|
||||
|
||||
final Uri u = new Uri.Builder()
|
||||
.scheme("http")
|
||||
.authority("local")
|
||||
.path("/")
|
||||
.encodedQuery(referrer).build();
|
||||
|
||||
source = u.getQueryParameter("utm_source");
|
||||
medium = u.getQueryParameter("utm_medium");
|
||||
term = u.getQueryParameter("utm_term");
|
||||
content = u.getQueryParameter("utm_content");
|
||||
campaign = u.getQueryParameter("utm_campaign");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{s: " + source + ", m: " + medium + ", t: " + term + ", c: " + content + ", c: " + campaign + "}";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.distribution;
|
||||
|
||||
import org.mozilla.gecko.AdjustConstants;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class ReferrerReceiver extends BroadcastReceiver {
|
||||
private static final String LOGTAG = "GeckoReferrerReceiver";
|
||||
|
||||
private static final String ACTION_INSTALL_REFERRER = "com.android.vending.INSTALL_REFERRER";
|
||||
|
||||
// Sent when we're done.
|
||||
@RobocopTarget
|
||||
public static final String ACTION_REFERRER_RECEIVED = "org.mozilla.fennec.REFERRER_RECEIVED";
|
||||
|
||||
/**
|
||||
* If the install intent has this source, it is a Mozilla specific or over
|
||||
* the air distribution referral. We'll track the campaign ID using
|
||||
* Mozilla's metrics systems.
|
||||
*
|
||||
* If the install intent has a source different than this one, it is a
|
||||
* referral from an advertising network. We may track these campaigns using
|
||||
* third-party tracking and metrics systems.
|
||||
*/
|
||||
private static final String MOZILLA_UTM_SOURCE = "mozilla";
|
||||
|
||||
/**
|
||||
* If the install intent has this campaign, we'll load the specified distribution.
|
||||
*/
|
||||
private static final String DISTRIBUTION_UTM_CAMPAIGN = "distribution";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.v(LOGTAG, "Received intent " + intent);
|
||||
if (!ACTION_INSTALL_REFERRER.equals(intent.getAction())) {
|
||||
// This should never happen.
|
||||
return;
|
||||
}
|
||||
|
||||
// Track the referrer object for distribution handling.
|
||||
ReferrerDescriptor referrer = new ReferrerDescriptor(intent.getStringExtra("referrer"));
|
||||
|
||||
if (!TextUtils.equals(referrer.source, MOZILLA_UTM_SOURCE)) {
|
||||
// Allow the Adjust handler to process the intent.
|
||||
try {
|
||||
AdjustConstants.getAdjustHelper().onReceive(context, intent);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Got exception in Adjust's onReceive; ignoring referrer intent.", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextUtils.equals(referrer.campaign, DISTRIBUTION_UTM_CAMPAIGN)) {
|
||||
Distribution.onReceivedReferrer(context, referrer);
|
||||
// We want Adjust information for OTA distributions as well
|
||||
try {
|
||||
AdjustConstants.getAdjustHelper().onReceive(context, intent);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Got exception in Adjust's onReceive for distribution.", e);
|
||||
}
|
||||
} else {
|
||||
Log.d(LOGTAG, "Not downloading distribution: non-matching campaign.");
|
||||
// If this is a Mozilla campaign, pass the campaign along to Gecko.
|
||||
// It'll pretend to be a "playstore" distribution for BLP purposes.
|
||||
propagateMozillaCampaign(referrer);
|
||||
}
|
||||
|
||||
// Broadcast a secondary, local intent to allow test code to respond.
|
||||
final Intent receivedIntent = new Intent(ACTION_REFERRER_RECEIVED);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(receivedIntent);
|
||||
}
|
||||
|
||||
|
||||
private void propagateMozillaCampaign(ReferrerDescriptor referrer) {
|
||||
if (referrer.campaign == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final JSONObject data = new JSONObject();
|
||||
data.put("id", "playstore");
|
||||
data.put("version", referrer.campaign);
|
||||
String payload = data.toString();
|
||||
|
||||
// Try to make sure the prefs are written as a group.
|
||||
GeckoAppShell.notifyObservers("Campaign:Set", payload);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error propagating campaign identifier.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue