Bug 879555 - Add ShowSettings message to Android about:healthreport wrapper. r=rnewman
authorNick Alexander <nalexander@mozilla.com>
Fri, 21 Jun 2013 14:00:40 -0700
changeset 147631 d5da469d2c49830901de202306efcb6c48c02543
parent 147630 c4980d2512385bad101eec87dcadbe55726c4267
child 147632 0b51d02bebd03ce080660823850f6d6ef071de8a
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman
bugs879555
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 879555 - Add ShowSettings message to Android about:healthreport wrapper. r=rnewman
mobile/android/base/BrowserApp.java
mobile/android/base/DataReportingNotification.java
mobile/android/base/GeckoPreferences.java
mobile/android/chrome/content/aboutHealthReport.js
mobile/android/modules/JNI.jsm
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -438,16 +438,17 @@ abstract public class BrowserApp extends
         mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
 
         registerEventListener("CharEncoding:Data");
         registerEventListener("CharEncoding:State");
         registerEventListener("Feedback:LastUrl");
         registerEventListener("Feedback:OpenPlayStore");
         registerEventListener("Feedback:MaybeLater");
         registerEventListener("Telemetry:Gather");
+        registerEventListener("Settings:Show");
 
         Distribution.init(this, getPackageResourcePath());
         JavaAddonManager.getInstance().init(getApplicationContext());
         mSharedPreferencesHelper = new SharedPreferencesHelper(getApplicationContext());
         mOrderedBroadcastHelper = new OrderedBroadcastHelper(getApplicationContext());
         mBrowserHealthReporter = new BrowserHealthReporter();
 
         if (AppConstants.MOZ_ANDROID_BEAM && Build.VERSION.SDK_INT >= 14) {
@@ -710,16 +711,17 @@ abstract public class BrowserApp extends
         }
 
         unregisterEventListener("CharEncoding:Data");
         unregisterEventListener("CharEncoding:State");
         unregisterEventListener("Feedback:LastUrl");
         unregisterEventListener("Feedback:OpenPlayStore");
         unregisterEventListener("Feedback:MaybeLater");
         unregisterEventListener("Telemetry:Gather");
+        unregisterEventListener("Settings:Show");
 
         if (AppConstants.MOZ_ANDROID_BEAM && Build.VERSION.SDK_INT >= 14) {
             NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
             if (nfc != null) {
                 // null this out even though the docs say it's not needed,
                 // because the source code looks like it will only do this
                 // automatically on API 14+
                 nfc.setNdefPushMessageCallback(null, this);
@@ -1078,16 +1080,25 @@ abstract public class BrowserApp extends
             } else if (event.equals("Reader:Removed")) {
                 final String url = message.getString("url");
                 handleReaderRemoved(url);
             } else if (event.equals("Reader:Share")) {
                 final String title = message.getString("title");
                 final String url = message.getString("url");
                 GeckoAppShell.openUriExternal(url, "text/plain", "", "",
                                               Intent.ACTION_SEND, title);
+            } else if (event.equals("Settings:Show")) {
+                // null strings return "null" (http://code.google.com/p/android/issues/detail?id=13830)
+                String resource = null;
+                if (!message.isNull(GeckoPreferences.INTENT_EXTRA_RESOURCES)) {
+                    resource = message.getString(GeckoPreferences.INTENT_EXTRA_RESOURCES);
+                }
+                Intent settingsIntent = new Intent(this, GeckoPreferences.class);
+                GeckoPreferences.setResourceToOpen(settingsIntent, resource);
+                startActivity(settingsIntent);
             } else {
                 super.handleMessage(event, message);
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
--- a/mobile/android/base/DataReportingNotification.java
+++ b/mobile/android/base/DataReportingNotification.java
@@ -43,26 +43,17 @@ public class DataReportingNotification {
         // Notify if user has not been notified or if policy version has changed.
         if ((!dataPrefs.contains(PREFS_POLICY_NOTIFIED_TIME)) ||
             (DATA_REPORTING_VERSION != dataPrefs.getInt(PREFS_POLICY_VERSION, -1))) {
 
             // Launch main App to launch Data choices when notification is clicked.
             Intent prefIntent = new Intent(GeckoApp.ACTION_LAUNCH_SETTINGS);
             prefIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.BROWSER_INTENT_CLASS);
 
-            // Build launch intent based on Android version.
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-                prefIntent.putExtra("resource", "preferences_datareporting");
-            } else {
-                prefIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, GeckoPreferenceFragment.class.getName());
-
-                Bundle fragmentArgs = new Bundle();
-                fragmentArgs.putString("resource", "preferences_datareporting");
-                prefIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
-            }
+            GeckoPreferences.setResourceToOpen(prefIntent, "preferences_datareporting");
             prefIntent.putExtra(ALERT_NAME_DATAREPORTING_NOTIFICATION, true);
 
             PendingIntent contentIntent = PendingIntent.getActivity(context, 0, prefIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
             // Create and send notification.
             String notificationTitle = context.getResources().getString(R.string.datareporting_notification_title);
             String notificationSummary;
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
--- a/mobile/android/base/GeckoPreferences.java
+++ b/mobile/android/base/GeckoPreferences.java
@@ -76,18 +76,18 @@ public class GeckoPreferences
         // For fragment-capable devices, display the default fragment if no explicit fragment to show.
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
             !getIntent().hasExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT)) {
             setupTopLevelFragmentIntent();
         }
 
         super.onCreate(savedInstanceState);
 
+        // Use setResourceToOpen to specify these extras.
         Bundle intentExtras = getIntent().getExtras();
-
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
             if (intentExtras != null && intentExtras.containsKey(INTENT_EXTRA_RESOURCES)) {
                 String resourceName = intentExtras.getString(INTENT_EXTRA_RESOURCES);
                 int resource = getResources().getIdentifier(resourceName, "xml", getPackageName());
                 addPreferencesFromResource(resource);
             } else {
                 addPreferencesFromResource(R.xml.preferences);
             }
@@ -676,9 +676,36 @@ public class GeckoPreferences
     private void unregisterEventListener(String event) {
         GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this);
     }
 
     @Override
     public boolean isGeckoActivityOpened() {
         return false;
     }
+
+    /**
+     * Given an Intent instance, add extras to specify which settings section to
+     * open.
+     *
+     * resource should be a valid Android XML resource identifier.
+     *
+     * The mechanism to open a section differs based on Android version.
+     */
+    public static void setResourceToOpen(final Intent intent, final String resource) {
+        if (intent == null) {
+            throw new IllegalArgumentException("intent must not be null");
+        }
+        if (resource == null) {
+            return;
+        }
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
+            intent.putExtra("resource", resource);
+        } else {
+            intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, GeckoPreferenceFragment.class.getName());
+
+            Bundle fragmentArgs = new Bundle();
+            fragmentArgs.putString("resource", resource);
+            intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
+        }
+    }
 }
--- a/mobile/android/chrome/content/aboutHealthReport.js
+++ b/mobile/android/chrome/content/aboutHealthReport.js
@@ -111,30 +111,41 @@ let healthReportWrapper = {
       type: type,
       content: content,
     };
 
     let iframe = document.getElementById("remote-report");
     iframe.contentWindow.postMessage(data, reportUrl);
   },
 
+  showSettings: function () {
+    console.log("AboutHealthReport: showing settings.");
+    sendMessageToJava({
+      type: "Settings:Show",
+      resource: "preferences_datareporting",
+    });
+  },
+
   handleRemoteCommand: function (evt) {
     switch (evt.detail.command) {
       case "DisableDataSubmission":
         this.onOptOut();
         break;
       case "EnableDataSubmission":
         this.onOptIn();
         break;
       case "RequestCurrentPrefs":
         this.updatePrefState();
         break;
       case "RequestCurrentPayload":
         this.refreshPayload();
         break;
+      case "ShowSettings":
+        this.showSettings();
+        break;
       default:
         Cu.reportError("Unexpected remote command received: " + evt.detail.command +
                        ". Ignoring command.");
         break;
     }
   },
 
   initRemotePage: function () {
--- a/mobile/android/modules/JNI.jsm
+++ b/mobile/android/modules/JNI.jsm
@@ -119,17 +119,17 @@ JNI.prototype = {
                                                    ctypes.void_t,
                                                    this.types.jclass,
                                                    this.types.jmethodID,
                                                    this.types.jvalue.ptr);
   },
 
   callStaticVoidMethod: function(aClass, aMethod) {
     let args = Array.prototype.slice.apply(arguments, [2]);
-    this._callStaticVoidMethod(aClass, aMethodId.methodId, this.getArgs(aMethod, args));
+    this._callStaticVoidMethod(aClass, aMethod.methodId, this.getArgs(aMethod, args));
     if (this.exceptionCheck())
        throw("Error calling static void method");
   },
 
   get _callStaticIntMethod() {
     delete this._callStaticIntMethod;
     return this._callStaticIntMethod = this.lib.declare("jsjni_CallStaticIntMethodA",
                                                    ctypes.default_abi,