Skip to content

Commit 3b0c750

Browse files
committed
Merge branch 'pr-323'
2 parents ce511e8 + f300cb0 commit 3b0c750

File tree

30 files changed

+981
-38
lines changed

30 files changed

+981
-38
lines changed

src/build/config/android/config.gni

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,10 @@ if (is_android || is_chromeos) {
225225

226226
# Forced Android versionCode
227227

228-
android_override_version_code = "100"
228+
android_override_version_code = "102"
229229

230230
# Forced Android versionName
231-
android_override_version_name = "0.82"
231+
android_override_version_name = "0.84"
232232

233233
# The path to the keystore to use for signing builds.
234234
android_keystore_path = default_android_keystore_path

src/chrome/android/chrome_java_sources.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ chrome_java_sources = [
1313
"java/src/org/chromium/chrome/browser/AppIndexingUtil.java",
1414
"java/src/org/chromium/chrome/browser/ApplicationLifetime.java",
1515
"java/src/org/chromium/chrome/browser/BackupSigninProcessor.java",
16+
"java/src/org/chromium/chrome/browser/BrandingManager.java",
1617
"java/src/org/chromium/chrome/browser/BrowserRestartActivity.java",
1718
"java/src/org/chromium/chrome/browser/WootzDialogFragment.java",
1819
"java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java",

src/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoViewModel.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_TYPE;
99

1010
import android.content.Context;
11+
import android.content.SharedPreferences;
1112

1213
import androidx.appcompat.content.res.AppCompatResources;
1314

15+
import org.chromium.base.ContextUtils;
1416
import org.chromium.base.metrics.RecordHistogram;
1517
import org.chromium.chrome.tab_ui.R;
1618
import org.chromium.ui.modelutil.PropertyModel;
@@ -29,7 +31,17 @@ public static PropertyModel create(
2931
Context context,
3032
MessageCardView.DismissActionProvider uiDismissActionProvider,
3133
IncognitoReauthPromoMessageService.IncognitoReauthMessageData data) {
34+
35+
// Get dynamic app name for branding
36+
String appName = ContextUtils.getAppSharedPreferences().getString("app_name", "Browser");
37+
boolean hasCustomBranding = !appName.equals("Browser");
38+
39+
// Get title text and make it dynamic
3240
String titleText = context.getString(R.string.incognito_reauth_promo_title);
41+
if (hasCustomBranding && titleText.contains("WootzApp")) {
42+
titleText = titleText.replace("WootzApp", appName);
43+
}
44+
3345
String descriptionText = context.getString(R.string.incognito_reauth_promo_description);
3446
String actionText = context.getString(R.string.incognito_reauth_lock_action_text);
3547
String dismissActionText = context.getString(R.string.no_thanks);

src/chrome/android/java/res/xml/developer_preferences.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ found in the LICENSE file.
1717
android:layout_height="wrap_content"
1818
android:enabled="false"
1919
android:key="beta_stable_hint"
20-
android:title="Hint: You can also enable Developer options on Beta/Stable channels by tapping the Chrome version in "Settings > About WootzApp" multiple times."
20+
android:title="Hint: You can also enable Developer options on Beta/Stable channels by tapping the version in "Settings > About" multiple times."
2121
app:allowDividerAbove="false"
2222
app:allowDividerBelow="false" />
2323
</PreferenceScreen>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.chromium.chrome.browser;
2+
3+
import androidx.annotation.NonNull;
4+
import androidx.annotation.Nullable;
5+
6+
import org.json.JSONObject;
7+
8+
public class BrandingConfig {
9+
private String utmSource;
10+
private String appName;
11+
private String iconUrl;
12+
private String packageName;
13+
private String primaryColor;
14+
private String accentColor;
15+
16+
public BrandingConfig() {}
17+
18+
public static BrandingConfig fromJson(JSONObject json) {
19+
BrandingConfig config = new BrandingConfig();
20+
config.utmSource = json.optString("utmSource", "");
21+
config.appName = json.optString("appName", "");
22+
config.iconUrl = json.optString("iconUrl", "");
23+
config.packageName = json.optString("packageName", "");
24+
config.primaryColor = json.optString("primaryColor", "");
25+
config.accentColor = json.optString("accentColor", "");
26+
return config;
27+
}
28+
29+
public JSONObject toJson() {
30+
JSONObject json = new JSONObject();
31+
try {
32+
json.put("utmSource", utmSource);
33+
json.put("appName", appName);
34+
json.put("iconUrl", iconUrl);
35+
json.put("packageName", packageName);
36+
json.put("primaryColor", primaryColor);
37+
json.put("accentColor", accentColor);
38+
} catch (Exception e) {
39+
// Handle JSON exception
40+
}
41+
return json;
42+
}
43+
44+
// Getters and setters
45+
@NonNull
46+
public String getUtmSource() { return utmSource; }
47+
public void setUtmSource(String utmSource) { this.utmSource = utmSource; }
48+
49+
@NonNull
50+
public String getAppName() { return appName; }
51+
public void setAppName(String appName) { this.appName = appName; }
52+
53+
@Nullable
54+
public String getIconUrl() { return iconUrl; }
55+
public void setIconUrl(String iconUrl) { this.iconUrl = iconUrl; }
56+
57+
@NonNull
58+
public String getPackageName() { return packageName; }
59+
public void setPackageName(String packageName) { this.packageName = packageName; }
60+
61+
@Nullable
62+
public String getPrimaryColor() { return primaryColor; }
63+
public void setPrimaryColor(String primaryColor) { this.primaryColor = primaryColor; }
64+
65+
@Nullable
66+
public String getAccentColor() { return accentColor; }
67+
public void setAccentColor(String accentColor) { this.accentColor = accentColor; }
68+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// BrandingManager.java
2+
package org.chromium.chrome.browser;
3+
4+
import android.content.SharedPreferences;
5+
import android.text.TextUtils;
6+
import android.util.Log;
7+
import android.widget.ImageView;
8+
import android.widget.TextView;
9+
10+
import androidx.annotation.NonNull;
11+
import androidx.annotation.Nullable;
12+
13+
import org.chromium.base.ContextUtils;
14+
import org.chromium.base.task.AsyncTask;
15+
import org.chromium.chrome.R;
16+
import org.json.JSONArray;
17+
import org.json.JSONObject;
18+
19+
import java.io.InputStream;
20+
import java.net.HttpURLConnection;
21+
import java.net.URL;
22+
import java.util.Scanner;
23+
24+
public class BrandingManager {
25+
private static final String TAG = "BrandingManager";
26+
27+
// GitHub URL - using your actual repository
28+
private static final String GITHUB_URL = "https://raw.githubusercontent.com/1311-hack1/rebrand/main/branding.json";
29+
30+
// Simple keys
31+
private static final String KEY_APP_NAME = "app_name";
32+
private static final String KEY_UTM = "utm_source";
33+
private static final String KEY_ICON_URL = "icon_url";
34+
35+
/**
36+
* One simple method - fetch from GitHub and save.
37+
* Call this when you get a UTM source.
38+
*/
39+
public static void fetchAndSave(String utmSource) {
40+
Log.e(TAG, "fetchAndSave: " + utmSource);
41+
if (TextUtils.isEmpty(utmSource)) return;
42+
43+
new AsyncTask<Void>() {
44+
@Override
45+
protected Void doInBackground() {
46+
Log.e(TAG, "doInBackground: " + utmSource);
47+
try {
48+
// Get JSON from GitHub
49+
URL url = new URL(GITHUB_URL);
50+
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
51+
InputStream input = conn.getInputStream();
52+
Scanner scanner = new Scanner(input).useDelimiter("\\A");
53+
String json = scanner.hasNext() ? scanner.next() : "";
54+
conn.disconnect();
55+
Log.e(TAG, "json: " + json);
56+
// Parse and find matching UTM
57+
JSONArray brands = new JSONObject(json).getJSONArray("brands");
58+
for (int i = 0; i < brands.length(); i++) {
59+
JSONObject brand = brands.getJSONObject(i);
60+
if (utmSource.equals(brand.optString("utmSource"))) {
61+
// Save to preferences
62+
String appName = brand.optString("appName", "Browser");
63+
String iconUrl = brand.optString("iconUrl", "");
64+
ContextUtils.getAppSharedPreferences().edit()
65+
.putString(KEY_APP_NAME, appName)
66+
.putString(KEY_UTM, utmSource)
67+
.putString(KEY_ICON_URL, iconUrl)
68+
.apply();
69+
Log.e(TAG, "Saved: " + appName);
70+
Log.e(TAG, "Saved: " + utmSource);
71+
Log.e(TAG, "Saved icon URL: " + iconUrl);
72+
break;
73+
}
74+
}
75+
} catch (Exception e) {
76+
Log.e(TAG, "Error fetching branding", e);
77+
}
78+
return null;
79+
}
80+
81+
@Override
82+
protected void onPostExecute(Void result) {
83+
// This method is required but we don't need to do anything here
84+
// since we're not updating UI from this task
85+
}
86+
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
87+
}
88+
89+
/**
90+
* Get current app name.
91+
*/
92+
@NonNull
93+
public static String getAppName() {
94+
return ContextUtils.getAppSharedPreferences().getString(KEY_APP_NAME, "Browser");
95+
}
96+
97+
/**
98+
* Set app name in TextView.
99+
*/
100+
public static void setTitle(@Nullable TextView textView) {
101+
if (textView != null) textView.setText(getAppName());
102+
}
103+
104+
/**
105+
* Set settings title in TextView.
106+
*/
107+
public static void setSettingsTitle(@Nullable TextView textView) {
108+
if (textView != null) textView.setText(getAppName() + " Settings");
109+
}
110+
111+
/**
112+
* Set incognito title in TextView.
113+
*/
114+
public static void setIncognitoTitle(@Nullable TextView textView) {
115+
if (textView != null) textView.setText(getAppName() + " Incognito");
116+
}
117+
118+
/**
119+
* Set default icon in ImageView.
120+
*/
121+
public static void setIcon(@Nullable ImageView imageView) {
122+
if (imageView != null) imageView.setImageResource(R.drawable.ic_chrome);
123+
}
124+
}

src/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@
282282
import java.util.concurrent.atomic.AtomicBoolean;
283283
import java.util.function.DoubleConsumer;
284284
import java.util.Iterator;
285+
import org.chromium.chrome.browser.BrandingManager;
285286

286287
/**
287288
* This is the main activity for ChromeMobile when not running in document mode. All the tabs are
@@ -4115,14 +4116,33 @@ private void maybeShowTabSwitcher(Intent intent) {
41154116
}
41164117

41174118
String extUtmSource = "";
4119+
String campaign = "";
41184120
private void handleBranchDeepLinkParams(JSONObject firstReferringParams) {
41194121
try {
41204122
android.content.SharedPreferences prefs = getSharedPreferences("branch_data", MODE_PRIVATE);
4123+
41214124
extUtmSource = firstReferringParams.optString("~channel", "");
4125+
4126+
campaign = firstReferringParams.optString("~campaign", "");
4127+
4128+
Log.e(TAG, "Anuj: campaign: " + campaign);
4129+
// if campaign is not empty, then use it as utm_source
4130+
if(!campaign.isEmpty() && extUtmSource.equals("wootzapp_ext")) {
4131+
String temp="";
4132+
temp=extUtmSource;
4133+
extUtmSource = campaign;
4134+
campaign = temp;
4135+
Log.e(TAG, "Anuj: utm source contains wootzapp_ext");
4136+
}
4137+
41224138
boolean isFirstRun = prefs.getBoolean("is_first_run", true);
41234139
if (isFirstRun) {
41244140
Log.e(TAG, "Processing branch link with utm_source: " + extUtmSource);
41254141
if (!TextUtils.isEmpty(extUtmSource)) {
4142+
BrandingManager.fetchAndSave(extUtmSource);
4143+
IntentHandler.storeCampaign(campaign);
4144+
IntentHandler.processStoredCampaignIfNeeded();
4145+
41264146
IntentHandler.ext_utm_source = extUtmSource;
41274147
IntentHandler.switchIconBasedOnUtm(extUtmSource);
41284148
IntentHandler.storeUtmSource(extUtmSource);

src/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,7 @@ public static boolean hasAnyIncognitoExtra(@Nullable Bundle extras) {
15341534
interface Natives {
15351535
boolean isCorsSafelistedHeader(String name, String value);
15361536
void storeUtmSource(String utmSource);
1537+
void storeCampaign(String campaign);
15371538
}
15381539

15391540
/**
@@ -1549,14 +1550,21 @@ public static void onIntentReceived(Intent intent) {
15491550
Log.d("IntentHandler", "intent.getData() != null");
15501551
Uri uri = intent.getData();
15511552
String utmSource = uri.getQueryParameter("utm_source");
1553+
String campaign = uri.getQueryParameter("campaign");
15521554
ext_utm_source = utmSource;
15531555
Log.d("IntentHandler", "utmSource: " + utmSource);
1556+
Log.d("IntentHandler", "campaign: " + campaign);
15541557
if (utmSource != null) {
15551558
Log.d("IntentHandler", "utmSource != null");
15561559
switchIconBasedOnUtm(utmSource);
15571560
// Store UTM source in shared preferences
15581561
storeUtmSource(utmSource);
15591562
}
1563+
if (campaign != null) {
1564+
Log.d("IntentHandler", "campaign != null");
1565+
// Store campaign in shared preferences
1566+
storeCampaign(campaign);
1567+
}
15601568
}
15611569
}
15621570

@@ -1628,6 +1636,49 @@ public static void storeUtmSource(String utmSource) {
16281636
}
16291637
}
16301638

1639+
/**
1640+
* Stores the campaign in shared preferences for later use.
1641+
* @param campaign The campaign to store
1642+
*/
1643+
public static void storeCampaign(String campaign) {
1644+
if (campaign != null && !campaign.isEmpty()) {
1645+
try {
1646+
SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
1647+
SharedPreferences.Editor editor = prefs.edit();
1648+
editor.putString("last_campaign", campaign);
1649+
editor.putBoolean("campaign_needs_jni_processing", true);
1650+
editor.apply();
1651+
Log.d("IntentHandler", "Stored campaign: " + campaign + " in SharedPreferences");
1652+
} catch (Exception e) {
1653+
Log.e("IntentHandler", "Error storing campaign", e);
1654+
}
1655+
}
1656+
}
1657+
1658+
/**
1659+
* Processes the stored campaign if needed.
1660+
*/
1661+
public static void processStoredCampaignIfNeeded() {
1662+
try {
1663+
SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
1664+
boolean needsProcessing = prefs.getBoolean("campaign_needs_jni_processing", false);
1665+
1666+
if (needsProcessing && LibraryLoader.getInstance().isInitialized()) {
1667+
String campaign = prefs.getString("last_campaign", "");
1668+
if (!campaign.isEmpty()) {
1669+
// Call JNI to send to native
1670+
IntentHandlerJni.get().storeCampaign(campaign);
1671+
Log.d("IntentHandler", "Processed stored campaign via JNI: " + campaign);
1672+
1673+
// Mark as processed
1674+
prefs.edit().putBoolean("campaign_needs_jni_processing", false).apply();
1675+
}
1676+
}
1677+
} catch (Exception e) {
1678+
Log.e("IntentHandler", "Error processing stored campaign", e);
1679+
}
1680+
}
1681+
16311682
/**
16321683
* Gets the last stored UTM source from SharedPreferences.
16331684
* @return The last UTM source or empty string if none exists

0 commit comments

Comments
 (0)