mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1321418 - Use GekcoBundle events in GeckoApp/BrowserApp; r=snorp r=sebastian r=gbrown
Bug 1321418 - 1. Use GekcoBundle events in GeckoApp; r=snorp r=sebastian Switch GeckoApp to using GeckoBundle events everywhere. UI or Gecko events are used if the event requires the UI or Gecko thread, respectively, and background events are used for all other events. There are changes to some other Java classes, such as SnackbarBuilder and GeckoAccessibility, due to the switch to GeckoBundle. For "Snackbar:Show", we need the global EventDispatcher because the event can be sent to both GeckoApp and GeckoPreferences. Howveer, we only want one listener registered at the same time, so we register and unregister in GeckoApp's and GeckoPreferences's onPause and onResume methods. Bug 1321418 - 2. Use appropriate JS EventDispatcher to send GeckoApp events; r=snorp r=sebastian Change JS code that sends events to GeckoApp to use either the global EventDispatcher or the per-window EventDispatcher. "Session:StatePurged" is not used so it's removed. "Gecko:Ready" in geckoview.js is not necessary because it's only used for GeckoApp, so it's removed from geckoview.js. Bug 1321418 - 3. Use GeckoBundle events in BrowserApp; r=snorp r=sebastian Switch BrowserApp to using GeckoBundle events, in a similar vein as GeckoApp. UI or Gecko events are used if the event handlers required UI or Gecko thread, respectively, and background events are used for all other events. Some other Java classes also have to be modified as a result of switching to GeckoBundle. Bug 1321418 - 4. Use global EventDispatcher to send BrowserApp events; r=snorp r=sebastian Change JS code that sends events to BrowserApp to use the global EventDispatcher instead of "Messaging". Bug 1321418 - 5. Update usages of events in tests; r=gbrown Update cases where we use or wait for events in tests.
This commit is contained in:
parent
87a621d48b
commit
e9532b9a3f
@ -33,8 +33,7 @@ this.AccessFu = { // jshint ignore:line
|
||||
Utils.init(aWindow);
|
||||
|
||||
try {
|
||||
Services.androidBridge.handleGeckoMessage(
|
||||
{ type: 'Accessibility:Ready' });
|
||||
Services.androidBridge.dispatch('Accessibility:Ready');
|
||||
Services.obs.addObserver(this, 'Accessibility:Settings', false);
|
||||
} catch (x) {
|
||||
// Not on Android
|
||||
@ -602,7 +601,6 @@ var Output = {
|
||||
}
|
||||
|
||||
for (let androidEvent of aDetails) {
|
||||
androidEvent.type = 'Accessibility:Event';
|
||||
if (androidEvent.bounds) {
|
||||
androidEvent.bounds = AccessFu.adjustContentBounds(
|
||||
androidEvent.bounds, aBrowser);
|
||||
@ -622,7 +620,9 @@ var Output = {
|
||||
androidEvent.brailleOutput);
|
||||
break;
|
||||
}
|
||||
this.androidBridge.handleGeckoMessage(androidEvent);
|
||||
let win = Utils.win;
|
||||
let view = win && win.QueryInterface(Ci.nsIAndroidView);
|
||||
view.dispatch('Accessibility:Event', androidEvent);
|
||||
}
|
||||
},
|
||||
|
||||
@ -818,8 +818,9 @@ var Input = {
|
||||
|
||||
if (Utils.MozBuildApp == 'mobile/android') {
|
||||
// Return focus to native Android browser chrome.
|
||||
Services.androidBridge.handleGeckoMessage(
|
||||
{ type: 'ToggleChrome:Focus' });
|
||||
let win = Utils.win;
|
||||
let view = win && win.QueryInterface(Ci.nsIAndroidView);
|
||||
view.dispatch('ToggleChrome:Focus');
|
||||
}
|
||||
break;
|
||||
case aEvent.DOM_VK_RETURN:
|
||||
|
@ -103,12 +103,9 @@ import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.IntentUtils;
|
||||
import org.mozilla.gecko.util.MenuUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
@ -202,8 +199,7 @@ public class BrowserApp extends GeckoApp
|
||||
OnUrlOpenInBackgroundListener,
|
||||
AnchoredPopup.OnVisibilityChangeListener,
|
||||
ActionModeCompat.Presenter,
|
||||
LayoutInflater.Factory,
|
||||
BundleEventListener {
|
||||
LayoutInflater.Factory {
|
||||
private static final String LOGTAG = "GeckoBrowserApp";
|
||||
|
||||
private static final int TABS_ANIMATION_DURATION = 450;
|
||||
@ -726,32 +722,36 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
mDoorhangerOverlay = findViewById(R.id.doorhanger_overlay);
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
|
||||
"Gecko:DelayedStartup",
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Search:Keyword",
|
||||
"Favicon:CacheLoad",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this,
|
||||
"Menu:Open",
|
||||
"Menu:Update",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Tab:Added",
|
||||
"Video:Play");
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
|
||||
"Video:Play",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Download:AndroidDownloadManager",
|
||||
"Settings:Show",
|
||||
"Updater:Launch",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerBackgroundThreadListener(this,
|
||||
"Experiments:GetActive",
|
||||
"Experiments:SetOverride",
|
||||
"Experiments:ClearOverride",
|
||||
"Favicon:CacheLoad",
|
||||
"Feedback:MaybeLater",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"Sanitize:ClearHistory",
|
||||
"Sanitize:ClearSyncedTabs",
|
||||
"Settings:Show",
|
||||
"Telemetry:Gather",
|
||||
"Updater:Launch",
|
||||
"Website:Metadata");
|
||||
"Download:AndroidDownloadManager",
|
||||
"Website:Metadata",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().registerUiThreadListener(this, "Prompt:ShowTop");
|
||||
|
||||
@ -1430,32 +1430,36 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
mSearchEngineManager.unregisterListeners();
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
|
||||
"Gecko:DelayedStartup",
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Search:Keyword",
|
||||
"Favicon:CacheLoad",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this,
|
||||
"Menu:Open",
|
||||
"Menu:Update",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Tab:Added",
|
||||
"Video:Play");
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
|
||||
"Video:Play",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Download:AndroidDownloadManager",
|
||||
"Settings:Show",
|
||||
"Updater:Launch",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterBackgroundThreadListener(this,
|
||||
"Experiments:GetActive",
|
||||
"Experiments:SetOverride",
|
||||
"Experiments:ClearOverride",
|
||||
"Favicon:CacheLoad",
|
||||
"Feedback:MaybeLater",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"Sanitize:ClearHistory",
|
||||
"Sanitize:ClearSyncedTabs",
|
||||
"Settings:Show",
|
||||
"Telemetry:Gather",
|
||||
"Updater:Launch",
|
||||
"Website:Metadata");
|
||||
"Download:AndroidDownloadManager",
|
||||
"Website:Metadata",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
|
||||
|
||||
@ -1548,25 +1552,6 @@ public class BrowserApp extends GeckoApp
|
||||
alphaAnimator.start();
|
||||
}
|
||||
|
||||
private void handleClearHistory(final boolean clearSearchHistory) {
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
db.clearHistory(getContentResolver(), clearSearchHistory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleClearSyncedTabs() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setToolbarMargin(int margin) {
|
||||
((RelativeLayout.LayoutParams) mGeckoLayout.getLayoutParams()).topMargin = margin;
|
||||
mGeckoLayout.requestLayout();
|
||||
@ -1663,29 +1648,21 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
@Override
|
||||
void toggleChrome(final boolean aShow) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (aShow) {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mBrowserChrome.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (aShow) {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mBrowserChrome.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
super.toggleChrome(aShow);
|
||||
}
|
||||
|
||||
@Override
|
||||
void focusChrome() {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
mActionBarFlipper.requestFocusFromTouch();
|
||||
}
|
||||
});
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
mActionBarFlipper.requestFocusFromTouch();
|
||||
|
||||
super.focusChrome();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1707,6 +1684,124 @@ public class BrowserApp extends GeckoApp
|
||||
public void handleMessage(final String event, final GeckoBundle message,
|
||||
final EventCallback callback) {
|
||||
switch (event) {
|
||||
case "Gecko:Ready":
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Gecko:DelayedStartup");
|
||||
|
||||
// Handle this message in GeckoApp, but also enable the Settings
|
||||
// menuitem, which is specific to BrowserApp.
|
||||
super.handleMessage(event, message, callback);
|
||||
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.settings).setEnabled(true);
|
||||
menu.findItem(R.id.help).setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Display notification for Mozilla data reporting, if data should be collected.
|
||||
if (AppConstants.MOZ_DATA_REPORTING &&
|
||||
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
|
||||
}
|
||||
break;
|
||||
|
||||
case "Gecko:DelayedStartup":
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Gecko:DelayedStartup");
|
||||
|
||||
// Force tabs panel inflation once the initial pageload is finished.
|
||||
ensureTabsPanelExists();
|
||||
|
||||
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
|
||||
mZoomedView = (ZoomedView) stub.inflate();
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
// Check if the fragment is already added. This should never be true
|
||||
// here, but this is a nice safety check. If casting is disabled,
|
||||
// these classes aren't built. We use reflection to initialize them.
|
||||
final Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
final String tag = "";
|
||||
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
|
||||
Log.i(LOGTAG, "Found tag " + tag);
|
||||
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (frag == null) {
|
||||
final Method getInstance = mediaManagerClass.getMethod(
|
||||
"getInstance", (Class[]) null);
|
||||
final Fragment mpm = (Fragment) getInstance.invoke(null);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.disallowAddToBackStack().add(mpm, tag).commit();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED &&
|
||||
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
// Start (this acts as ping if started already) the stumbler lib; if
|
||||
// the stumbler has queued data it will upload it. Stumbler operates
|
||||
// on its own thread, and startup impact is further minimized by
|
||||
// delaying work (such as upload) a few seconds. Avoid any potential
|
||||
// startup CPU/thread contention by delaying the pref broadcast.
|
||||
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
|
||||
// TODO: Better scheduling of sync action (Bug 1257492)
|
||||
DownloadContentService.startSync(this);
|
||||
DownloadContentService.startVerification(this);
|
||||
}
|
||||
|
||||
FeedService.setup(this);
|
||||
break;
|
||||
|
||||
case "Menu:Open":
|
||||
if (mBrowserToolbar.isEditing()) {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
openOptionsMenu();
|
||||
break;
|
||||
|
||||
case "Menu:Update":
|
||||
updateAddonMenuItem(message.getInt("id"), message.getBundle("options"));
|
||||
break;
|
||||
|
||||
case "Menu:Add":
|
||||
final MenuItemInfo info = new MenuItemInfo();
|
||||
info.label = message.getString("name");
|
||||
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
info.checked = message.getBoolean("checked", false);
|
||||
info.enabled = message.getBoolean("enabled", true);
|
||||
info.visible = message.getBoolean("visible", true);
|
||||
info.checkable = message.getBoolean("checkable", false);
|
||||
final int parent = message.getInt("parent", 0);
|
||||
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
|
||||
addAddonMenuItem(info);
|
||||
break;
|
||||
|
||||
case "Menu:Remove":
|
||||
removeAddonMenuItem(message.getInt("id") + ADDON_MENU_OFFSET);
|
||||
break;
|
||||
|
||||
case "LightweightTheme:Update":
|
||||
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
|
||||
break;
|
||||
|
||||
case "Search:Keyword":
|
||||
storeSearchQuery(message.getString("query"));
|
||||
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
|
||||
TelemetryContract.Method.ACTIONBAR);
|
||||
break;
|
||||
|
||||
case "Prompt:ShowTop":
|
||||
// Bring this activity to front so the prompt is visible..
|
||||
Intent bringToFrontIntent = new Intent();
|
||||
@ -1715,21 +1810,32 @@ public class BrowserApp extends GeckoApp
|
||||
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
startActivity(bringToFrontIntent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
final EventCallback callback) {
|
||||
switch (event) {
|
||||
case "Tab:Added":
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
// Set the target tab to null so it does not get selected (on editing
|
||||
// mode exit) in lieu of the tab that we're going to open and select.
|
||||
mTargetTabForEditingMode = null;
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
break;
|
||||
|
||||
case "Video:Play":
|
||||
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
|
||||
mVideoPlayer.start(Uri.parse(message.getString("uri")));
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW,
|
||||
TelemetryContract.Method.CONTENT, "playhls");
|
||||
}
|
||||
break;
|
||||
|
||||
case "CharEncoding:Data":
|
||||
final NativeJSObject[] charsets = message.getObjectArray("charsets");
|
||||
final GeckoBundle[] charsets = message.getBundleArray("charsets");
|
||||
final int selected = message.getInt("selected");
|
||||
|
||||
final String[] titleArray = new String[charsets.length];
|
||||
final String[] codeArray = new String[charsets.length];
|
||||
for (int i = 0; i < charsets.length; i++) {
|
||||
final NativeJSObject charset = charsets[i];
|
||||
final GeckoBundle charset = charsets[i];
|
||||
titleArray[i] = charset.getString("title");
|
||||
codeArray[i] = charset.getString("code");
|
||||
}
|
||||
@ -1750,26 +1856,15 @@ public class BrowserApp extends GeckoApp
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialogBuilder.show();
|
||||
}
|
||||
});
|
||||
dialogBuilder.show();
|
||||
break;
|
||||
|
||||
case "CharEncoding:State":
|
||||
final boolean visible = message.getString("visible").equals("true");
|
||||
final boolean visible = "true".equals(message.getString("visible"));
|
||||
GeckoPreferences.setCharEncodingState(visible);
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.char_encoding).setVisible(visible);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (mMenu != null) {
|
||||
mMenu.findItem(R.id.char_encoding).setVisible(visible);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Experiments:GetActive":
|
||||
@ -1779,7 +1874,8 @@ public class BrowserApp extends GeckoApp
|
||||
break;
|
||||
|
||||
case "Experiments:SetOverride":
|
||||
Experiments.setOverride(getContext(), message.getString("name"), message.getBoolean("isEnabled"));
|
||||
Experiments.setOverride(getContext(), message.getString("name"),
|
||||
message.getBoolean("isEnabled"));
|
||||
break;
|
||||
|
||||
case "Experiments:ClearOverride":
|
||||
@ -1792,52 +1888,25 @@ public class BrowserApp extends GeckoApp
|
||||
break;
|
||||
|
||||
case "Feedback:MaybeLater":
|
||||
resetFeedbackLaunchCount();
|
||||
break;
|
||||
|
||||
case "Menu:Add":
|
||||
final MenuItemInfo info = new MenuItemInfo();
|
||||
info.label = message.getString("name");
|
||||
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
info.checked = message.optBoolean("checked", false);
|
||||
info.enabled = message.optBoolean("enabled", true);
|
||||
info.visible = message.optBoolean("visible", true);
|
||||
info.checkable = message.optBoolean("checkable", false);
|
||||
final int parent = message.optInt("parent", 0);
|
||||
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
|
||||
final MenuItemInfo menuItemInfo = info;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addAddonMenuItem(menuItemInfo);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Menu:Remove":
|
||||
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeAddonMenuItem(id);
|
||||
}
|
||||
});
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
|
||||
break;
|
||||
|
||||
case "Sanitize:ClearHistory":
|
||||
handleClearHistory(message.optBoolean("clearSearchHistory", false));
|
||||
callback.sendSuccess(true);
|
||||
BrowserDB.from(getProfile()).clearHistory(
|
||||
getContentResolver(), message.getBoolean("clearSearchHistory", false));
|
||||
callback.sendSuccess(null);
|
||||
break;
|
||||
|
||||
case "Sanitize:ClearSyncedTabs":
|
||||
handleClearSyncedTabs();
|
||||
callback.sendSuccess(true);
|
||||
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
|
||||
callback.sendSuccess(null);
|
||||
break;
|
||||
|
||||
case "Settings:Show":
|
||||
final String resource =
|
||||
message.optString(GeckoPreferences.INTENT_EXTRA_RESOURCES, null);
|
||||
final Intent settingsIntent = new Intent(this, GeckoPreferences.class);
|
||||
final String resource = message.getString(GeckoPreferences.INTENT_EXTRA_RESOURCES);
|
||||
|
||||
GeckoPreferences.setResourceToOpen(settingsIntent, resource);
|
||||
startActivityForResult(settingsIntent, ACTIVITY_REQUEST_PREFERENCES);
|
||||
|
||||
@ -1851,30 +1920,58 @@ public class BrowserApp extends GeckoApp
|
||||
case "Telemetry:Gather":
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
final ContentResolver cr = getContentResolver();
|
||||
|
||||
Telemetry.addToHistogram("PLACES_PAGES_COUNT", db.getCount(cr, "history"));
|
||||
Telemetry.addToHistogram("FENNEC_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks"));
|
||||
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT", (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
|
||||
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE", (TextUtils.isEmpty(getHomepage()) ? 0 : 1));
|
||||
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT",
|
||||
(isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
|
||||
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE",
|
||||
(TextUtils.isEmpty(getHomepage()) ? 0 : 1));
|
||||
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
|
||||
final boolean hasCustomHomepanels =
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) || prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) ||
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
|
||||
|
||||
Telemetry.addToHistogram("FENNEC_HOMEPANELS_CUSTOM", hasCustomHomepanels ? 1 : 0);
|
||||
|
||||
Telemetry.addToHistogram("FENNEC_READER_VIEW_CACHE_SIZE",
|
||||
SavedReaderViewHelper.getSavedReaderViewHelper(getContext()).getDiskSpacedUsedKB());
|
||||
SavedReaderViewHelper.getSavedReaderViewHelper(getContext())
|
||||
.getDiskSpacedUsedKB());
|
||||
|
||||
if (Versions.feature16Plus) {
|
||||
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT", (isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
|
||||
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT",
|
||||
(isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
|
||||
}
|
||||
break;
|
||||
|
||||
case "Updater:Launch":
|
||||
handleUpdaterLaunch();
|
||||
/**
|
||||
* Launch UI that lets the user update Firefox.
|
||||
*
|
||||
* This depends on the current channel: Release and Beta both direct to
|
||||
* the Google Play Store. If updating is enabled, Aurora, Nightly, and
|
||||
* custom builds open about:, which provides an update interface.
|
||||
*
|
||||
* If updating is not enabled, this simply logs an error.
|
||||
*/
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_UPDATER) {
|
||||
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
|
||||
break;
|
||||
}
|
||||
|
||||
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
|
||||
break;
|
||||
|
||||
case "Download:AndroidDownloadManager":
|
||||
// Downloading via Android's download manager
|
||||
|
||||
final String uri = message.getString("uri");
|
||||
final String filename = message.getString("filename");
|
||||
final String mimeType = message.getString("mimeType");
|
||||
@ -1883,54 +1980,49 @@ public class BrowserApp extends GeckoApp
|
||||
request.setMimeType(mimeType);
|
||||
|
||||
try {
|
||||
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, filename);
|
||||
request.setDestinationInExternalFilesDir(
|
||||
this, Environment.DIRECTORY_DOWNLOADS, filename);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(LOGTAG, "Cannot create download directory");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setNotificationVisibility(
|
||||
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.addRequestHeader("User-Agent", HardwareUtils.isTablet() ?
|
||||
AppConstants.USER_AGENT_FENNEC_TABLET :
|
||||
AppConstants.USER_AGENT_FENNEC_MOBILE);
|
||||
|
||||
try {
|
||||
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
DownloadManager manager = (DownloadManager)
|
||||
getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.enqueue(request);
|
||||
|
||||
Log.d(LOGTAG, "Enqueued download (Download Manager)");
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(LOGTAG, "Download failed: " + e);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Website:Metadata":
|
||||
final NativeJSObject metadata = message.getObject("metadata");
|
||||
final String location = message.getString("location");
|
||||
final boolean hasImage = message.getBoolean("hasImage");
|
||||
final String metadata = message.getString("metadata");
|
||||
|
||||
final boolean hasImage = !TextUtils.isEmpty(metadata.optString("image_url", null));
|
||||
final String metadataJSON = metadata.toString();
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ContentProviderClient contentProviderClient = getContentResolver()
|
||||
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
|
||||
if (contentProviderClient == null) {
|
||||
Log.w(LOGTAG, "Failed to obtain content provider client for: " + BrowserContract.PageMetadata.CONTENT_URI);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
GlobalPageMetadata.getInstance().add(
|
||||
BrowserDB.from(getProfile()),
|
||||
contentProviderClient,
|
||||
location, hasImage, metadataJSON);
|
||||
} finally {
|
||||
contentProviderClient.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
final ContentProviderClient contentProviderClient = getContentResolver()
|
||||
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
|
||||
if (contentProviderClient == null) {
|
||||
Log.w(LOGTAG, "Failed to obtain content provider client for: " +
|
||||
BrowserContract.PageMetadata.CONTENT_URI);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
GlobalPageMetadata.getInstance().add(
|
||||
BrowserDB.from(getProfile()),
|
||||
contentProviderClient,
|
||||
location, hasImage, metadata);
|
||||
} finally {
|
||||
contentProviderClient.release();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -1994,164 +2086,6 @@ public class BrowserApp extends GeckoApp
|
||||
return (TextUtils.equals(packageName, getPackageName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
switch (event) {
|
||||
case "Menu:Open":
|
||||
if (mBrowserToolbar.isEditing()) {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
|
||||
openOptionsMenu();
|
||||
break;
|
||||
|
||||
case "Menu:Update":
|
||||
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
final JSONObject options = message.getJSONObject("options");
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAddonMenuItem(id, options);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Gecko:DelayedStartup":
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Force tabs panel inflation once the initial
|
||||
// pageload is finished.
|
||||
ensureTabsPanelExists();
|
||||
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
|
||||
mZoomedView = (ZoomedView) stub.inflate();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
// Check if the fragment is already added. This should never be true here, but this is
|
||||
// a nice safety check.
|
||||
// If casting is disabled, these classes aren't built. We use reflection to initialize them.
|
||||
final Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
final String tag = "";
|
||||
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
|
||||
Log.i(LOGTAG, "Found tag " + tag);
|
||||
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (frag == null) {
|
||||
final Method getInstance = mediaManagerClass.getMethod("getInstance", (Class[]) null);
|
||||
final Fragment mpm = (Fragment) getInstance.invoke(null);
|
||||
getSupportFragmentManager().beginTransaction().disallowAddToBackStack().add(mpm, tag).commit();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
// Start (this acts as ping if started already) the stumbler lib; if the stumbler has queued data it will upload it.
|
||||
// Stumbler operates on its own thread, and startup impact is further minimized by delaying work (such as upload) a few seconds.
|
||||
// Avoid any potential startup CPU/thread contention by delaying the pref broadcast.
|
||||
final long oneSecondInMillis = 1000;
|
||||
ThreadUtils.getBackgroundHandler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
|
||||
}
|
||||
}, oneSecondInMillis);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
|
||||
// TODO: Better scheduling of sync action (Bug 1257492)
|
||||
DownloadContentService.startSync(this);
|
||||
|
||||
DownloadContentService.startVerification(this);
|
||||
}
|
||||
|
||||
FeedService.setup(this);
|
||||
|
||||
super.handleMessage(event, message);
|
||||
break;
|
||||
|
||||
case "Gecko:Ready":
|
||||
// Handle this message in GeckoApp, but also enable the Settings
|
||||
// menuitem, which is specific to BrowserApp.
|
||||
super.handleMessage(event, message);
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.settings).setEnabled(true);
|
||||
menu.findItem(R.id.help).setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Display notification for Mozilla data reporting, if data should be collected.
|
||||
if (AppConstants.MOZ_DATA_REPORTING && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
|
||||
}
|
||||
break;
|
||||
|
||||
case "Search:Keyword":
|
||||
storeSearchQuery(message.getString("query"));
|
||||
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
|
||||
TelemetryContract.Method.ACTIONBAR);
|
||||
break;
|
||||
|
||||
case "LightweightTheme:Update":
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Video:Play":
|
||||
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
|
||||
final String uri = message.getString("uri");
|
||||
final String uuid = message.getString("uuid");
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mVideoPlayer.start(Uri.parse(uri));
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.CONTENT, "playhls");
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "Tab:Added":
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Set the target tab to null so it does not get selected (on editing
|
||||
// mode exit) in lieu of the tab that we're going to open and select.
|
||||
mTargetTabForEditingMode = null;
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(event, message);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab() {
|
||||
Tabs.getInstance().addTab();
|
||||
@ -3248,16 +3182,16 @@ public class BrowserApp extends GeckoApp
|
||||
mMenu.removeItem(id);
|
||||
}
|
||||
|
||||
private void updateAddonMenuItem(int id, JSONObject options) {
|
||||
private void updateAddonMenuItem(int id, final GeckoBundle options) {
|
||||
// Set attribute for the menu item in cache, if available
|
||||
if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
|
||||
for (MenuItemInfo item : mAddonMenuItemsCache) {
|
||||
if (item.id == id) {
|
||||
item.label = options.optString("name", item.label);
|
||||
item.checkable = options.optBoolean("checkable", item.checkable);
|
||||
item.checked = options.optBoolean("checked", item.checked);
|
||||
item.enabled = options.optBoolean("enabled", item.enabled);
|
||||
item.visible = options.optBoolean("visible", item.visible);
|
||||
item.label = options.getString("name", item.label);
|
||||
item.checkable = options.getBoolean("checkable", item.checkable);
|
||||
item.checked = options.getBoolean("checked", item.checked);
|
||||
item.enabled = options.getBoolean("enabled", item.enabled);
|
||||
item.visible = options.getBoolean("visible", item.visible);
|
||||
item.added = (mMenu != null);
|
||||
break;
|
||||
}
|
||||
@ -3270,11 +3204,11 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
final MenuItem menuItem = mMenu.findItem(id);
|
||||
if (menuItem != null) {
|
||||
menuItem.setTitle(options.optString("name", menuItem.getTitle().toString()));
|
||||
menuItem.setCheckable(options.optBoolean("checkable", menuItem.isCheckable()));
|
||||
menuItem.setChecked(options.optBoolean("checked", menuItem.isChecked()));
|
||||
menuItem.setEnabled(options.optBoolean("enabled", menuItem.isEnabled()));
|
||||
menuItem.setVisible(options.optBoolean("visible", menuItem.isVisible()));
|
||||
menuItem.setTitle(options.getString("name", menuItem.getTitle().toString()));
|
||||
menuItem.setCheckable(options.getBoolean("checkable", menuItem.isCheckable()));
|
||||
menuItem.setChecked(options.getBoolean("checked", menuItem.isChecked()));
|
||||
menuItem.setEnabled(options.getBoolean("enabled", menuItem.isEnabled()));
|
||||
menuItem.setVisible(options.getBoolean("visible", menuItem.isVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4029,11 +3963,6 @@ public class BrowserApp extends GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
private void resetFeedbackLaunchCount() {
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
|
||||
}
|
||||
|
||||
// HomePager.OnUrlOpenListener
|
||||
@Override
|
||||
public void onUrlOpen(String url, EnumSet<OnUrlOpenListener.Flags> flags) {
|
||||
@ -4147,34 +4076,6 @@ public class BrowserApp extends GeckoApp
|
||||
return mReadingListHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch UI that lets the user update Firefox.
|
||||
*
|
||||
* This depends on the current channel: Release and Beta both direct to the
|
||||
* Google Play Store. If updating is enabled, Aurora, Nightly, and custom
|
||||
* builds open about:, which provides an update interface.
|
||||
*
|
||||
* If updating is not enabled, this simply logs an error.
|
||||
*
|
||||
* @return true if update UI was launched.
|
||||
*/
|
||||
protected boolean handleUpdaterLaunch() {
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_UPDATER) {
|
||||
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Implementing ActionModeCompat.Presenter */
|
||||
@Override
|
||||
public void startActionModeCompat(final ActionModeCompat.Callback callback) {
|
||||
|
@ -39,12 +39,12 @@ import org.mozilla.gecko.text.TextSelection;
|
||||
import org.mozilla.gecko.updater.UpdateServiceHelper;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.ActivityUtils;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.FileUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.GeckoRequest;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
@ -130,12 +130,11 @@ import java.util.concurrent.TimeUnit;
|
||||
public abstract class GeckoApp
|
||||
extends GeckoActivity
|
||||
implements
|
||||
BundleEventListener,
|
||||
ContextGetter,
|
||||
GeckoAppShell.GeckoInterface,
|
||||
GeckoEventListener,
|
||||
GeckoMenu.Callback,
|
||||
GeckoMenu.MenuPresenter,
|
||||
NativeEventListener,
|
||||
Tabs.OnTabsChangedListener,
|
||||
ViewTreeObserver.OnGlobalLayoutListener {
|
||||
|
||||
@ -616,36 +615,52 @@ public abstract class GeckoApp
|
||||
public boolean areTabsShown() { return false; }
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
public void handleMessage(final String event, final GeckoBundle message,
|
||||
final EventCallback callback) {
|
||||
if ("Accessibility:Ready".equals(event)) {
|
||||
if (event.equals("Gecko:Ready")) {
|
||||
mGeckoReadyStartupTimer.stop();
|
||||
geckoConnected();
|
||||
|
||||
// This method is already running on the background thread, so we
|
||||
// know that mHealthRecorder will exist. That doesn't stop us being
|
||||
// paranoid.
|
||||
// This method is cheap, so don't spawn a new runnable.
|
||||
final HealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.recordGeckoStartupTime(mGeckoReadyStartupTimer.getElapsed());
|
||||
}
|
||||
|
||||
GeckoApplication.get().onDelayedStartup();
|
||||
|
||||
} else if (event.equals("Gecko:Exited")) {
|
||||
// Gecko thread exited first; let GeckoApp die too.
|
||||
doShutdown();
|
||||
|
||||
} else if ("Accessibility:Ready".equals(event)) {
|
||||
GeckoAccessibility.updateAccessibilitySettings(this);
|
||||
|
||||
} else if ("Accessibility:Event".equals(event)) {
|
||||
GeckoAccessibility.sendAccessibilityEvent(message);
|
||||
|
||||
} else if ("Bookmark:Insert".equals(event)) {
|
||||
final String url = message.getString("url");
|
||||
final String title = message.getString("title");
|
||||
final Context context = this;
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
final boolean bookmarkAdded = db.addBookmark(
|
||||
getContentResolver(), message.getString("title"), message.getString("url"));
|
||||
final int resId = bookmarkAdded ? R.string.bookmark_added
|
||||
: R.string.bookmark_already_added;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean bookmarkAdded = db.addBookmark(getContentResolver(), title, url);
|
||||
final int resId = bookmarkAdded ? R.string.bookmark_added : R.string.bookmark_already_added;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SnackbarBuilder.builder(GeckoApp.this)
|
||||
.message(resId)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
}
|
||||
});
|
||||
SnackbarBuilder.builder(GeckoApp.this)
|
||||
.message(resId)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
}
|
||||
});
|
||||
|
||||
} else if ("Contact:Add".equals(event)) {
|
||||
final String email = message.optString("email", null);
|
||||
final String phone = message.optString("phone", null);
|
||||
final String email = message.getString("email", null);
|
||||
final String phone = message.getString("phone", null);
|
||||
if (email != null) {
|
||||
Uri contactUri = Uri.parse(email);
|
||||
Intent i = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT, contactUri);
|
||||
@ -685,51 +700,12 @@ public abstract class GeckoApp
|
||||
setLocale(message.getString("locale"));
|
||||
|
||||
} else if ("Permissions:Data".equals(event)) {
|
||||
final NativeJSObject[] permissions = message.getObjectArray("permissions");
|
||||
final GeckoBundle[] permissions = message.getBundleArray("permissions");
|
||||
showSiteSettingsDialog(permissions);
|
||||
|
||||
} else if ("PrivateBrowsing:Data".equals(event)) {
|
||||
mPrivateBrowsingSession = message.optString("session", null);
|
||||
mPrivateBrowsingSession = message.getString("session", null);
|
||||
|
||||
} else if ("Session:StatePurged".equals(event)) {
|
||||
onStatePurged();
|
||||
|
||||
} else if ("Share:Text".equals(event)) {
|
||||
final String text = message.getString("text");
|
||||
final Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
String title = "";
|
||||
if (tab != null) {
|
||||
title = tab.getDisplayTitle();
|
||||
}
|
||||
IntentHelper.openUriExternal(text, "text/plain", "", "", Intent.ACTION_SEND, title, false);
|
||||
|
||||
// Context: Sharing via chrome list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST, "text");
|
||||
|
||||
} else if ("Snackbar:Show".equals(event)) {
|
||||
SnackbarBuilder.builder(this)
|
||||
.fromEvent(message)
|
||||
.callback(callback)
|
||||
.buildAndShow();
|
||||
|
||||
} else if ("SystemUI:Visibility".equals(event)) {
|
||||
setSystemUiVisible(message.getBoolean("visible"));
|
||||
|
||||
} else if ("ToggleChrome:Focus".equals(event)) {
|
||||
focusChrome();
|
||||
|
||||
} else if ("ToggleChrome:Hide".equals(event)) {
|
||||
toggleChrome(false);
|
||||
|
||||
} else if ("ToggleChrome:Show".equals(event)) {
|
||||
toggleChrome(true);
|
||||
|
||||
} else if ("Update:Check".equals(event)) {
|
||||
UpdateServiceHelper.checkForUpdate(this);
|
||||
} else if ("Update:Download".equals(event)) {
|
||||
UpdateServiceHelper.downloadUpdate(this);
|
||||
} else if ("Update:Install".equals(event)) {
|
||||
UpdateServiceHelper.applyUpdate(this);
|
||||
} else if ("RuntimePermissions:Prompt".equals(event)) {
|
||||
String[] permissions = message.getStringArray("permissions");
|
||||
if (callback == null || permissions == null) {
|
||||
@ -750,54 +726,64 @@ public abstract class GeckoApp
|
||||
callback.sendSuccess(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
if (event.equals("Gecko:Ready")) {
|
||||
mGeckoReadyStartupTimer.stop();
|
||||
geckoConnected();
|
||||
|
||||
// This method is already running on the background thread, so we
|
||||
// know that mHealthRecorder will exist. That doesn't stop us being
|
||||
// paranoid.
|
||||
// This method is cheap, so don't spawn a new runnable.
|
||||
final HealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.recordGeckoStartupTime(mGeckoReadyStartupTimer.getElapsed());
|
||||
}
|
||||
|
||||
GeckoApplication.get().onDelayedStartup();
|
||||
|
||||
} else if (event.equals("Gecko:Exited")) {
|
||||
// Gecko thread exited first; let GeckoApp die too.
|
||||
doShutdown();
|
||||
return;
|
||||
|
||||
} else if (event.equals("Accessibility:Event")) {
|
||||
GeckoAccessibility.sendAccessibilityEvent(message);
|
||||
} else if ("Share:Text".equals(event)) {
|
||||
final String text = message.getString("text");
|
||||
final Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
String title = "";
|
||||
if (tab != null) {
|
||||
title = tab.getDisplayTitle();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
IntentHelper.openUriExternal(text, "text/plain", "", "", Intent.ACTION_SEND, title, false);
|
||||
|
||||
// Context: Sharing via chrome list (no explicit session is active)
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST, "text");
|
||||
|
||||
} else if ("Snackbar:Show".equals(event)) {
|
||||
SnackbarBuilder.builder(this)
|
||||
.fromEvent(message)
|
||||
.callback(callback)
|
||||
.buildAndShow();
|
||||
|
||||
} else if ("SystemUI:Visibility".equals(event)) {
|
||||
if (message.getBoolean("visible", true)) {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
} else {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
|
||||
} else if ("ToggleChrome:Focus".equals(event)) {
|
||||
focusChrome();
|
||||
|
||||
} else if ("ToggleChrome:Hide".equals(event)) {
|
||||
toggleChrome(false);
|
||||
|
||||
} else if ("ToggleChrome:Show".equals(event)) {
|
||||
toggleChrome(true);
|
||||
|
||||
} else if ("Update:Check".equals(event)) {
|
||||
UpdateServiceHelper.checkForUpdate(this);
|
||||
|
||||
} else if ("Update:Download".equals(event)) {
|
||||
UpdateServiceHelper.downloadUpdate(this);
|
||||
|
||||
} else if ("Update:Install".equals(event)) {
|
||||
UpdateServiceHelper.applyUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
void onStatePurged() { }
|
||||
|
||||
/**
|
||||
* @param permissions
|
||||
* Array of JSON objects to represent site permissions.
|
||||
* Example: { type: "offline-app", setting: "Store Offline Data", value: "Allow" }
|
||||
*/
|
||||
private void showSiteSettingsDialog(final NativeJSObject[] permissions) {
|
||||
private void showSiteSettingsDialog(final GeckoBundle[] permissions) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.site_settings_title);
|
||||
|
||||
final ArrayList<HashMap<String, String>> itemList =
|
||||
new ArrayList<HashMap<String, String>>();
|
||||
for (final NativeJSObject permObj : permissions) {
|
||||
for (final GeckoBundle permObj : permissions) {
|
||||
final HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("setting", permObj.getString("setting"));
|
||||
map.put("value", permObj.getString("value"));
|
||||
@ -840,36 +826,29 @@ public abstract class GeckoApp
|
||||
}
|
||||
});
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
|
||||
final ListView listView = dialog.getListView();
|
||||
if (listView != null) {
|
||||
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
}
|
||||
|
||||
final Button clearButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
clearButton.setEnabled(false);
|
||||
|
||||
dialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void run() {
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
|
||||
final ListView listView = dialog.getListView();
|
||||
if (listView != null) {
|
||||
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
if (listView.getCheckedItemCount() == 0) {
|
||||
clearButton.setEnabled(false);
|
||||
} else {
|
||||
clearButton.setEnabled(true);
|
||||
}
|
||||
|
||||
final Button clearButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
clearButton.setEnabled(false);
|
||||
|
||||
dialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
if (listView.getCheckedItemCount() == 0) {
|
||||
clearButton.setEnabled(false);
|
||||
} else {
|
||||
clearButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* package */ void addFullScreenPluginView(View view) {
|
||||
if (mFullScreenPluginView != null) {
|
||||
Log.w(LOGTAG, "Already have a fullscreen plugin view");
|
||||
@ -958,6 +937,35 @@ public abstract class GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
private void showSetImageResult(final boolean success, final int message, final String path) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!success) {
|
||||
SnackbarBuilder.builder(GeckoApp.this)
|
||||
.message(message)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
intent.setData(Uri.parse(path));
|
||||
|
||||
// Removes the image from storage once the chooser activity ends.
|
||||
Intent chooser = Intent.createChooser(intent, getString(message));
|
||||
ActivityResultHandler handler = new ActivityResultHandler() {
|
||||
@Override
|
||||
public void onActivityResult (int resultCode, Intent data) {
|
||||
getContentResolver().delete(intent.getData(), null, null);
|
||||
}
|
||||
};
|
||||
ActivityHandlerHelper.startIntentForActivity(GeckoApp.this, chooser, handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// This method starts downloading an image synchronously and displays the Chooser activity to set the image as wallpaper.
|
||||
private void setImageAs(final String aSrc) {
|
||||
boolean isDataURI = aSrc.startsWith("data:");
|
||||
@ -990,38 +998,17 @@ public abstract class GeckoApp
|
||||
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
|
||||
if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) {
|
||||
SnackbarBuilder.builder(this)
|
||||
.message(R.string.set_image_path_fail)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
showSetImageResult(/* success */ false, R.string.set_image_path_fail, null);
|
||||
return;
|
||||
}
|
||||
String path = Media.insertImage(getContentResolver(), image, null, null);
|
||||
if (path == null) {
|
||||
SnackbarBuilder.builder(this)
|
||||
.message(R.string.set_image_path_fail)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
showSetImageResult(/* success */ false, R.string.set_image_path_fail, null);
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
intent.setData(Uri.parse(path));
|
||||
|
||||
// Removes the image from storage once the chooser activity ends.
|
||||
Intent chooser = Intent.createChooser(intent, getString(R.string.set_image_chooser_title));
|
||||
ActivityResultHandler handler = new ActivityResultHandler() {
|
||||
@Override
|
||||
public void onActivityResult (int resultCode, Intent data) {
|
||||
getContentResolver().delete(intent.getData(), null, null);
|
||||
}
|
||||
};
|
||||
ActivityHandlerHelper.startIntentForActivity(this, chooser, handler);
|
||||
showSetImageResult(/* success */ true, R.string.set_image_chooser_title, path);
|
||||
} else {
|
||||
SnackbarBuilder.builder(this)
|
||||
.message(R.string.set_image_fail)
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
showSetImageResult(/* success */ false, R.string.set_image_fail, null);
|
||||
}
|
||||
} catch (OutOfMemoryError ome) {
|
||||
Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);
|
||||
@ -1193,15 +1180,12 @@ public abstract class GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
// GeckoThread has to register for "Gecko:Ready" first, so GeckoApp registers
|
||||
// for events after initializing GeckoThread but before launching it.
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
|
||||
// To prevent races, register startup events before launching the Gecko thread.
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Accessibility:Ready",
|
||||
"Gecko:Exited",
|
||||
"Gecko:Ready",
|
||||
"Gecko:Exited");
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
|
||||
"Accessibility:Ready");
|
||||
null);
|
||||
|
||||
GeckoThread.launch();
|
||||
|
||||
@ -1233,30 +1217,33 @@ public abstract class GeckoApp
|
||||
mMainLayout = (RelativeLayout) findViewById(R.id.main_layout);
|
||||
mLayerView = (GeckoView) findViewById(R.id.layer_view);
|
||||
|
||||
getAppEventDispatcher().registerGeckoThreadListener((GeckoEventListener)this,
|
||||
"Accessibility:Event");
|
||||
getAppEventDispatcher().registerGeckoThreadListener(this,
|
||||
"Accessibility:Event",
|
||||
"Locale:Set",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().registerGeckoThreadListener((NativeEventListener)this,
|
||||
getAppEventDispatcher().registerBackgroundThreadListener(this,
|
||||
"Bookmark:Insert",
|
||||
"Image:SetAs",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().registerUiThreadListener(this,
|
||||
"Contact:Add",
|
||||
"DevToolsAuth:Scan",
|
||||
"DOMFullScreen:Start",
|
||||
"DOMFullScreen:Stop",
|
||||
"Image:SetAs",
|
||||
"Locale:Set",
|
||||
"Permissions:Data",
|
||||
"PrivateBrowsing:Data",
|
||||
"RuntimePermissions:Prompt",
|
||||
"Session:StatePurged",
|
||||
"Share:Text",
|
||||
"Snackbar:Show",
|
||||
"SystemUI:Visibility",
|
||||
"ToggleChrome:Focus",
|
||||
"ToggleChrome:Hide",
|
||||
"ToggleChrome:Show",
|
||||
"Update:Check",
|
||||
"Update:Download",
|
||||
"Update:Install");
|
||||
"Update:Install",
|
||||
null);
|
||||
|
||||
Tabs.getInstance().attachToContext(this, mLayerView);
|
||||
|
||||
@ -1683,9 +1670,9 @@ public abstract class GeckoApp
|
||||
public void run() {
|
||||
if (TabQueueHelper.TAB_QUEUE_ENABLED && TabQueueHelper.shouldOpenTabQueueUrls(GeckoApp.this)) {
|
||||
|
||||
getAppEventDispatcher().registerGeckoThreadListener(new NativeEventListener() {
|
||||
getAppEventDispatcher().registerGeckoThreadListener(new BundleEventListener() {
|
||||
@Override
|
||||
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
|
||||
public void handleMessage(String event, GeckoBundle message, EventCallback callback) {
|
||||
if ("Tabs:TabsOpened".equals(event)) {
|
||||
getAppEventDispatcher().unregisterGeckoThreadListener(this, "Tabs:TabsOpened");
|
||||
openTabsRunnable.run();
|
||||
@ -2083,6 +2070,9 @@ public abstract class GeckoApp
|
||||
// After an onPause, the activity is back in the foreground.
|
||||
// Undo whatever we did in onPause.
|
||||
super.onResume();
|
||||
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Snackbar:Show");
|
||||
|
||||
if (mIsAbortingAppLaunch) {
|
||||
return;
|
||||
}
|
||||
@ -2164,6 +2154,8 @@ public abstract class GeckoApp
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Snackbar:Show");
|
||||
|
||||
if (mIsAbortingAppLaunch) {
|
||||
super.onPause();
|
||||
return;
|
||||
@ -2247,37 +2239,39 @@ public abstract class GeckoApp
|
||||
return;
|
||||
}
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener)this,
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Accessibility:Ready",
|
||||
"Gecko:Exited",
|
||||
"Gecko:Ready",
|
||||
"Gecko:Exited");
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener)this,
|
||||
"Accessibility:Ready");
|
||||
getAppEventDispatcher().unregisterGeckoThreadListener(this,
|
||||
"Accessibility:Event",
|
||||
"Locale:Set",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().unregisterGeckoThreadListener((GeckoEventListener)this,
|
||||
"Accessibility:Event");
|
||||
|
||||
getAppEventDispatcher().unregisterGeckoThreadListener((NativeEventListener)this,
|
||||
getAppEventDispatcher().unregisterBackgroundThreadListener(this,
|
||||
"Bookmark:Insert",
|
||||
"Image:SetAs",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().unregisterUiThreadListener(this,
|
||||
"Contact:Add",
|
||||
"DevToolsAuth:Scan",
|
||||
"DOMFullScreen:Start",
|
||||
"DOMFullScreen:Stop",
|
||||
"Image:SetAs",
|
||||
"Locale:Set",
|
||||
"Permissions:Data",
|
||||
"PrivateBrowsing:Data",
|
||||
"RuntimePermissions:Prompt",
|
||||
"Session:StatePurged",
|
||||
"Share:Text",
|
||||
"Snackbar:Show",
|
||||
"SystemUI:Visibility",
|
||||
"ToggleChrome:Focus",
|
||||
"ToggleChrome:Hide",
|
||||
"ToggleChrome:Show",
|
||||
"Update:Check",
|
||||
"Update:Download",
|
||||
"Update:Install");
|
||||
"Update:Install",
|
||||
null);
|
||||
|
||||
if (mPromptService != null)
|
||||
mPromptService.destroy();
|
||||
@ -2799,19 +2793,6 @@ public abstract class GeckoApp
|
||||
onLocaleChanged(resultant);
|
||||
}
|
||||
|
||||
private void setSystemUiVisible(final boolean visible) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (visible) {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
} else {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected HealthRecorder createHealthRecorder(final Context context,
|
||||
final String profilePath,
|
||||
final EventDispatcher dispatcher,
|
||||
|
@ -6,7 +6,7 @@
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
@ -173,11 +173,11 @@ public class SnackbarBuilder {
|
||||
/**
|
||||
* @param object Populate the builder with data from a Gecko Snackbar:Show event.
|
||||
*/
|
||||
public SnackbarBuilder fromEvent(final NativeJSObject object) {
|
||||
public SnackbarBuilder fromEvent(final GeckoBundle object) {
|
||||
message = object.getString("message");
|
||||
duration = object.getInt("duration");
|
||||
|
||||
if (object.has("backgroundColor")) {
|
||||
if (object.containsKey("backgroundColor")) {
|
||||
final String providedColor = object.getString("backgroundColor");
|
||||
try {
|
||||
backgroundColor = Color.parseColor(providedColor);
|
||||
@ -186,9 +186,9 @@ public class SnackbarBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
NativeJSObject actionObject = object.optObject("action", null);
|
||||
GeckoBundle actionObject = object.getBundle("action");
|
||||
if (actionObject != null) {
|
||||
action = actionObject.optString("label", null);
|
||||
action = actionObject.getString("label", null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.mozglue.SafeIntent;
|
||||
import org.mozilla.gecko.notifications.WhatsNewReceiver;
|
||||
import org.mozilla.gecko.reader.ReaderModeUtils;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
@ -40,7 +43,7 @@ import android.provider.Browser;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
|
||||
public class Tabs implements GeckoEventListener {
|
||||
public class Tabs implements BundleEventListener, GeckoEventListener {
|
||||
private static final String LOGTAG = "GeckoTabs";
|
||||
|
||||
// mOrder and mTabs are always of the same cardinality, and contain the same values.
|
||||
@ -104,8 +107,11 @@ public class Tabs implements GeckoEventListener {
|
||||
};
|
||||
|
||||
private Tabs() {
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this,
|
||||
"Tab:Added",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this,
|
||||
"Tab:Close",
|
||||
"Tab:Select",
|
||||
"Tab:SelectAndForeground",
|
||||
@ -473,50 +479,56 @@ public class Tabs implements GeckoEventListener {
|
||||
return Tabs.TabsInstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
@Override // BundleEventListener
|
||||
public synchronized void handleMessage(final String event, final GeckoBundle message,
|
||||
final EventCallback callback) {
|
||||
// "Tab:Added" is a special case because tab will be null if the tab was just added
|
||||
if ("Tab:Added".equals(event)) {
|
||||
int id = message.getInt("tabID");
|
||||
Tab tab = getTab(id);
|
||||
|
||||
String url = message.getString("uri");
|
||||
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
final Tab oldTab = getSelectedTab();
|
||||
if (oldTab != null) {
|
||||
oldTab.setIsEditing(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (message.getBoolean("stub")) {
|
||||
if (tab == null) {
|
||||
// Tab was already closed; abort
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tab = addTab(id, url, message.getBoolean("external"),
|
||||
message.getInt("parentId"),
|
||||
message.getString("title"),
|
||||
message.getBoolean("isPrivate"),
|
||||
message.getInt("tabIndex"));
|
||||
// If we added the tab as a stub, we should have already
|
||||
// selected it, so ignore this flag for stubbed tabs.
|
||||
if (message.getBoolean("selected"))
|
||||
selectTab(id);
|
||||
}
|
||||
|
||||
if (message.getBoolean("delayLoad"))
|
||||
tab.setState(Tab.STATE_DELAYED);
|
||||
if (message.getBoolean("desktopMode"))
|
||||
tab.setDesktopMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
// GeckoEventListener implementation
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
public synchronized void handleMessage(String event, JSONObject message) {
|
||||
Log.d(LOGTAG, "handleMessage: " + event);
|
||||
try {
|
||||
// All other events handled below should contain a tabID property
|
||||
int id = message.getInt("tabID");
|
||||
Tab tab = getTab(id);
|
||||
|
||||
// "Tab:Added" is a special case because tab will be null if the tab was just added
|
||||
if (event.equals("Tab:Added")) {
|
||||
String url = message.isNull("uri") ? null : message.getString("uri");
|
||||
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
final Tab oldTab = getSelectedTab();
|
||||
if (oldTab != null) {
|
||||
oldTab.setIsEditing(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (message.getBoolean("stub")) {
|
||||
if (tab == null) {
|
||||
// Tab was already closed; abort
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tab = addTab(id, url, message.getBoolean("external"),
|
||||
message.getInt("parentId"),
|
||||
message.getString("title"),
|
||||
message.getBoolean("isPrivate"),
|
||||
message.getInt("tabIndex"));
|
||||
// If we added the tab as a stub, we should have already
|
||||
// selected it, so ignore this flag for stubbed tabs.
|
||||
if (message.getBoolean("selected"))
|
||||
selectTab(id);
|
||||
}
|
||||
|
||||
if (message.getBoolean("delayLoad"))
|
||||
tab.setState(Tab.STATE_DELAYED);
|
||||
if (message.getBoolean("desktopMode"))
|
||||
tab.setDesktopMode(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tab was already closed; abort
|
||||
if (tab == null)
|
||||
return;
|
||||
|
@ -538,14 +538,7 @@ public class CombinedHistoryPanel extends HomeFragment implements RemoteClientsD
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "hint_private_browsing");
|
||||
try {
|
||||
final JSONObject json = new JSONObject();
|
||||
json.put("type", "Menu:Open");
|
||||
GeckoApp.getEventDispatcher().dispatchEvent(json, null);
|
||||
EventDispatcher.getInstance().dispatchEvent(json, null);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error forming JSON for Private Browsing contextual hint", e);
|
||||
}
|
||||
EventDispatcher.getInstance().dispatch("Menu:Open", null);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,9 @@ import org.mozilla.gecko.AppConstants.Versions;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.WindowUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils.AssertBehavior;
|
||||
@ -37,7 +39,7 @@ import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
public class LightweightTheme implements GeckoEventListener {
|
||||
public class LightweightTheme implements BundleEventListener {
|
||||
private static final String LOGTAG = "GeckoLightweightTheme";
|
||||
|
||||
private static final String PREFS_URL = "lightweightTheme.headerURL";
|
||||
@ -163,7 +165,7 @@ public class LightweightTheme implements GeckoEventListener {
|
||||
mListeners = new ArrayList<OnChangeListener>();
|
||||
|
||||
// unregister isn't needed as the lifetime is same as the application.
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this,
|
||||
"LightweightTheme:Update",
|
||||
"LightweightTheme:Disable");
|
||||
|
||||
@ -181,28 +183,19 @@ public class LightweightTheme implements GeckoEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
if (event.equals("LightweightTheme:Update")) {
|
||||
JSONObject lightweightTheme = message.getJSONObject("data");
|
||||
final String headerURL = lightweightTheme.getString("headerURL");
|
||||
final String color = lightweightTheme.optString("accentcolor");
|
||||
public void handleMessage(String event, GeckoBundle message, EventCallback callback) {
|
||||
if (event.equals("LightweightTheme:Update")) {
|
||||
GeckoBundle lightweightTheme = message.getBundle("data");
|
||||
final String headerURL = lightweightTheme.getString("headerURL");
|
||||
final String color = lightweightTheme.getString("accentcolor");
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new LightweightThemeRunnable(headerURL, color));
|
||||
} else if (event.equals("LightweightTheme:Disable")) {
|
||||
// Clear the saved data when a theme is disabled.
|
||||
// Called on the Gecko thread, but should be very lightweight.
|
||||
clearPrefs();
|
||||
ThreadUtils.postToBackgroundThread(new LightweightThemeRunnable(headerURL, color));
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resetLightweightTheme();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
} else if (event.equals("LightweightTheme:Disable")) {
|
||||
// Clear the saved data when a theme is disabled.
|
||||
// Called on the Gecko thread, but should be very lightweight.
|
||||
clearPrefs();
|
||||
resetLightweightTheme();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,10 @@ import org.mozilla.gecko.tabqueue.TabQueueHelper;
|
||||
import org.mozilla.gecko.tabqueue.TabQueuePrompt;
|
||||
import org.mozilla.gecko.updater.UpdateService;
|
||||
import org.mozilla.gecko.updater.UpdateServiceHelper;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.ContextUtils;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.InputOptionsUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
@ -101,12 +103,12 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeckoPreferences
|
||||
extends AppCompatPreferenceActivity
|
||||
implements
|
||||
GeckoActivityStatus,
|
||||
NativeEventListener,
|
||||
OnPreferenceChangeListener,
|
||||
OnSharedPreferenceChangeListener
|
||||
extends AppCompatPreferenceActivity
|
||||
implements BundleEventListener,
|
||||
GeckoActivityStatus,
|
||||
NativeEventListener,
|
||||
OnPreferenceChangeListener,
|
||||
OnSharedPreferenceChangeListener
|
||||
{
|
||||
private static final String LOGTAG = "GeckoPreferences";
|
||||
|
||||
@ -369,9 +371,8 @@ OnSharedPreferenceChangeListener
|
||||
// Use setResourceToOpen to specify these extras.
|
||||
Bundle intentExtras = getIntent().getExtras();
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Sanitize:Finished",
|
||||
"Snackbar:Show");
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener) this,
|
||||
"Sanitize:Finished");
|
||||
|
||||
// Add handling for long-press click.
|
||||
// This is only for Android 3.0 and below (which use the long-press-context-menu paradigm).
|
||||
@ -506,9 +507,8 @@ OnSharedPreferenceChangeListener
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Sanitize:Finished",
|
||||
"Snackbar:Show");
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
|
||||
"Sanitize:Finished");
|
||||
|
||||
if (mPrefsRequest != null) {
|
||||
PrefsHelper.removeObserver(mPrefsRequest);
|
||||
@ -518,6 +518,8 @@ OnSharedPreferenceChangeListener
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Snackbar:Show");
|
||||
|
||||
// Symmetric with onResume.
|
||||
if (isMultiPane()) {
|
||||
SharedPreferences prefs = GeckoSharedPrefs.forApp(this);
|
||||
@ -535,6 +537,8 @@ OnSharedPreferenceChangeListener
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Snackbar:Show");
|
||||
|
||||
if (getApplication() instanceof GeckoApplication) {
|
||||
((GeckoApplication) getApplication()).onActivityResume(this);
|
||||
}
|
||||
@ -607,6 +611,17 @@ OnSharedPreferenceChangeListener
|
||||
Permissions.onRequestPermissionsResult(this, permissions, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final GeckoBundle message,
|
||||
final EventCallback callback) {
|
||||
if ("Snackbar:Show".equals(event)) {
|
||||
SnackbarBuilder.builder(this)
|
||||
.fromEvent(message)
|
||||
.callback(callback)
|
||||
.buildAndShow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message, final EventCallback callback) {
|
||||
try {
|
||||
@ -620,12 +635,6 @@ OnSharedPreferenceChangeListener
|
||||
.duration(Snackbar.LENGTH_LONG)
|
||||
.buildAndShow();
|
||||
break;
|
||||
case "Snackbar:Show":
|
||||
SnackbarBuilder.builder(this)
|
||||
.fromEvent(message)
|
||||
.callback(callback)
|
||||
.buildAndShow();
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
|
@ -591,7 +591,7 @@ var ActionBarHandler = {
|
||||
},
|
||||
|
||||
action: function(element, win) {
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Share:Text",
|
||||
text: ActionBarHandler._getSelectedText(),
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ var Feedback = {
|
||||
break;
|
||||
|
||||
case "FeedbackMaybeLater":
|
||||
Messaging.sendRequest({ type: "Feedback:MaybeLater" });
|
||||
GlobalEventDispatcher.sendRequest({ type: "Feedback:MaybeLater" });
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ var PermissionsHelper = {
|
||||
// Keep track of permissions, so we know which ones to clear
|
||||
this._currentPermissions = permissions;
|
||||
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Permissions:Data",
|
||||
permissions: permissions
|
||||
});
|
||||
|
@ -126,7 +126,7 @@ var Reader = {
|
||||
}
|
||||
|
||||
case "Reader:SystemUIVisibility":
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "SystemUI:Visibility",
|
||||
visible: message.data.visible
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ var RemoteDebugger = {
|
||||
return this._receivingOOB;
|
||||
}
|
||||
|
||||
this._receivingOOB = Messaging.sendRequestForResult({
|
||||
this._receivingOOB = WindowEventDispatcher.sendRequestForResult({
|
||||
type: "DevToolsAuth:Scan"
|
||||
}).then(data => {
|
||||
return JSON.parse(data);
|
||||
|
@ -78,17 +78,20 @@ function init() {
|
||||
function checkForUpdates() {
|
||||
showCheckingMessage();
|
||||
|
||||
Services.androidBridge.handleGeckoMessage({ type: "Update:Check" });
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
window.WindowEventDispatcher.sendRequest({ type: "Update:Check" });
|
||||
}
|
||||
|
||||
function downloadUpdate() {
|
||||
Services.androidBridge.handleGeckoMessage({ type: "Update:Download" });
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
window.WindowEventDispatcher.sendRequest({ type: "Update:Download" });
|
||||
}
|
||||
|
||||
function installUpdate() {
|
||||
showCheckAction();
|
||||
|
||||
Services.androidBridge.handleGeckoMessage({ type: "Update:Install" });
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
window.WindowEventDispatcher.sendRequest({ type: "Update:Install" });
|
||||
}
|
||||
|
||||
let updateLink = document.getElementById("updateLink");
|
||||
|
@ -8,8 +8,11 @@
|
||||
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/SharedPreferences.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm");
|
||||
|
||||
// Name of Android SharedPreference controlling whether to upload
|
||||
// health reports.
|
||||
@ -119,7 +122,7 @@ var healthReportWrapper = {
|
||||
|
||||
showSettings: function () {
|
||||
console.log("AboutHealthReport: showing settings.");
|
||||
Messaging.sendRequest({
|
||||
EventDispatcher.instance.sendRequest({
|
||||
type: "Settings:Show",
|
||||
resource: "preferences_vendor",
|
||||
});
|
||||
@ -127,7 +130,7 @@ var healthReportWrapper = {
|
||||
|
||||
launchUpdater: function () {
|
||||
console.log("AboutHealthReport: launching updater.");
|
||||
Messaging.sendRequest({
|
||||
EventDispatcher.instance.sendRequest({
|
||||
type: "Updater:Launch",
|
||||
});
|
||||
},
|
||||
|
@ -5,7 +5,6 @@
|
||||
var Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://services-common/utils.js"); /*global: CommonUtils */
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
@ -19,6 +18,8 @@ XPCOMUtils.defineLazyGetter(window, "gChromeWin", () =>
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow));
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Prompt",
|
||||
"resource://gre/modules/Prompt.jsm");
|
||||
@ -416,7 +417,7 @@ var Logins = {
|
||||
|
||||
_loadFavicon: function (aImg, aHostname) {
|
||||
// Load favicon from cache.
|
||||
Messaging.sendRequestForResult({
|
||||
EventDispatcher.instance.sendRequestForResult({
|
||||
type: "Favicon:CacheLoad",
|
||||
url: aHostname,
|
||||
}).then(function(faviconUrl) {
|
||||
|
@ -390,14 +390,13 @@ var BrowserApp = {
|
||||
Services.obs.addObserver(this, "android-set-pref", false);
|
||||
Services.obs.addObserver(this, "gather-telemetry", false);
|
||||
Services.obs.addObserver(this, "keyword-search", false);
|
||||
Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
|
||||
Services.obs.addObserver(this, "Fonts:Reload", false);
|
||||
Services.obs.addObserver(this, "Vibration:Request", false);
|
||||
|
||||
Messaging.addListener(this.getHistory.bind(this), "Session:GetHistory");
|
||||
|
||||
window.addEventListener("fullscreen", function() {
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: window.fullScreen ? "ToggleChrome:Hide" : "ToggleChrome:Show"
|
||||
});
|
||||
}, false);
|
||||
@ -409,7 +408,7 @@ var BrowserApp = {
|
||||
// (per spec). This means the last event on enabling will be for the innermost
|
||||
// document, which will have fullscreenElement set correctly.
|
||||
let doc = e.target;
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: doc.fullscreenElement ? "DOMFullScreen:Start" : "DOMFullScreen:Stop",
|
||||
rootElement: doc.fullscreenElement == doc.documentElement
|
||||
});
|
||||
@ -508,7 +507,7 @@ var BrowserApp = {
|
||||
}
|
||||
|
||||
// Notify Java that Gecko has loaded.
|
||||
Messaging.sendRequest({ type: "Gecko:Ready" });
|
||||
GlobalEventDispatcher.sendRequest({ type: "Gecko:Ready" });
|
||||
|
||||
this.deck.addEventListener("DOMContentLoaded", function BrowserApp_delayedStartup() {
|
||||
BrowserApp.deck.removeEventListener("DOMContentLoaded", BrowserApp_delayedStartup, false);
|
||||
@ -517,7 +516,7 @@ var BrowserApp = {
|
||||
InitLater(() => Cu.import("resource://gre/modules/PresentationDeviceInfoManager.jsm"));
|
||||
|
||||
InitLater(() => Services.obs.notifyObservers(window, "browser-delayed-startup-finished", ""));
|
||||
InitLater(() => Messaging.sendRequest({ type: "Gecko:DelayedStartup" }));
|
||||
InitLater(() => GlobalEventDispatcher.sendRequest({ type: "Gecko:DelayedStartup" }));
|
||||
|
||||
if (!AppConstants.RELEASE_OR_BETA) {
|
||||
InitLater(() => WebcompatReporter.init());
|
||||
@ -573,7 +572,7 @@ var BrowserApp = {
|
||||
*/
|
||||
setLocale: function (locale) {
|
||||
console.log("browser.js: requesting locale set: " + locale);
|
||||
Messaging.sendRequest({ type: "Locale:Set", locale: locale });
|
||||
WindowEventDispatcher.sendRequest({ type: "Locale:Set", locale: locale });
|
||||
},
|
||||
|
||||
initContextMenu: function () {
|
||||
@ -726,7 +725,7 @@ var BrowserApp = {
|
||||
UITelemetry.addEvent("action.1", "contextmenu", null, "web_contact_email");
|
||||
|
||||
let url = NativeWindow.contextmenus._getLinkURL(aTarget);
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Contact:Add",
|
||||
email: url
|
||||
});
|
||||
@ -738,7 +737,7 @@ var BrowserApp = {
|
||||
UITelemetry.addEvent("action.1", "contextmenu", null, "web_contact_phone");
|
||||
|
||||
let url = NativeWindow.contextmenus._getLinkURL(aTarget);
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Contact:Add",
|
||||
phone: url
|
||||
});
|
||||
@ -752,7 +751,7 @@ var BrowserApp = {
|
||||
|
||||
let url = NativeWindow.contextmenus._getLinkURL(aTarget);
|
||||
let title = aTarget.textContent || aTarget.title || url;
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Bookmark:Insert",
|
||||
url: url,
|
||||
title: title
|
||||
@ -889,7 +888,7 @@ var BrowserApp = {
|
||||
UITelemetry.addEvent("action.1", "contextmenu", null, "web_background_image");
|
||||
|
||||
let src = aTarget.src;
|
||||
Messaging.sendRequest({
|
||||
WindowEventDispatcher.sendRequest({
|
||||
type: "Image:SetAs",
|
||||
url: src
|
||||
});
|
||||
@ -1756,7 +1755,7 @@ var BrowserApp = {
|
||||
let query = isPrivate ? "" : aData;
|
||||
|
||||
let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "Search:Keyword",
|
||||
identifier: engine.identifier,
|
||||
name: engine.name,
|
||||
@ -1902,12 +1901,8 @@ var BrowserApp = {
|
||||
break;
|
||||
}
|
||||
|
||||
case "sessionstore-state-purge-complete":
|
||||
Messaging.sendRequest({ type: "Session:StatePurged" });
|
||||
break;
|
||||
|
||||
case "gather-telemetry":
|
||||
Messaging.sendRequest({ type: "Telemetry:Gather" });
|
||||
GlobalEventDispatcher.sendRequest({ type: "Telemetry:Gather" });
|
||||
break;
|
||||
|
||||
case "Locale:OS":
|
||||
@ -2179,21 +2174,21 @@ var NativeWindow = {
|
||||
options.type = "Menu:Add";
|
||||
options.id = this._menuId;
|
||||
|
||||
Messaging.sendRequest(options);
|
||||
GlobalEventDispatcher.sendRequest(options);
|
||||
this._callbacks[this._menuId] = options.callback;
|
||||
this._menuId++;
|
||||
return this._menuId - 1;
|
||||
},
|
||||
|
||||
remove: function(aId) {
|
||||
Messaging.sendRequest({ type: "Menu:Remove", id: aId });
|
||||
GlobalEventDispatcher.sendRequest({ type: "Menu:Remove", id: aId });
|
||||
},
|
||||
|
||||
update: function(aId, aOptions) {
|
||||
if (!aOptions)
|
||||
return;
|
||||
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "Menu:Update",
|
||||
id: aId,
|
||||
options: aOptions
|
||||
@ -3504,7 +3499,7 @@ Tab.prototype = {
|
||||
isPrivate: isPrivate,
|
||||
stub: stub
|
||||
};
|
||||
Messaging.sendRequest(message);
|
||||
GlobalEventDispatcher.sendRequest(message);
|
||||
}
|
||||
|
||||
let flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL |
|
||||
@ -4535,7 +4530,7 @@ var BrowserEventHandler = {
|
||||
case 'OpenMediaWithExternalApp': {
|
||||
let mediaSrc = aEvent.target.currentSrc || aEvent.target.src;
|
||||
let uuid = uuidgen.generateUUID().toString();
|
||||
Services.androidBridge.handleGeckoMessage({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "Video:Play",
|
||||
uri: mediaSrc,
|
||||
uuid: uuid
|
||||
@ -5632,7 +5627,7 @@ var CharacterEncoding = {
|
||||
showCharEncoding = Services.prefs.getComplexValue("browser.menu.showCharacterEncoding", Ci.nsIPrefLocalizedString).data;
|
||||
} catch (e) { /* Optional */ }
|
||||
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "CharEncoding:State",
|
||||
visible: showCharEncoding
|
||||
});
|
||||
@ -5666,7 +5661,7 @@ var CharacterEncoding = {
|
||||
}
|
||||
}
|
||||
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "CharEncoding:Data",
|
||||
charsets: this._charsets,
|
||||
selected: selected
|
||||
@ -6334,7 +6329,7 @@ var Experiments = {
|
||||
OFFLINE_CACHE: "offline-cache",
|
||||
|
||||
init() {
|
||||
Messaging.sendRequestForResult({
|
||||
GlobalEventDispatcher.sendRequestForResult({
|
||||
type: "Experiments:GetActive"
|
||||
}).then(experiments => {
|
||||
let names = JSON.parse(experiments);
|
||||
@ -6361,7 +6356,7 @@ var Experiments = {
|
||||
},
|
||||
|
||||
setOverride(name, isEnabled) {
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "Experiments:SetOverride",
|
||||
name: name,
|
||||
isEnabled: isEnabled
|
||||
@ -6369,7 +6364,7 @@ var Experiments = {
|
||||
},
|
||||
|
||||
clearOverride(name) {
|
||||
Messaging.sendRequest({
|
||||
GlobalEventDispatcher.sendRequest({
|
||||
type: "Experiments:ClearOverride",
|
||||
name: name
|
||||
});
|
||||
|
@ -14,9 +14,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Log",
|
||||
"resource://gre/modules/AndroidLog.jsm", "AndroidLog");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Messaging",
|
||||
"resource://gre/modules/Messaging.jsm", "Messaging");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm", "Services");
|
||||
|
||||
@ -26,7 +23,4 @@ function dump(msg) {
|
||||
|
||||
function startup() {
|
||||
dump("zerdatime " + Date.now() + " - geckoivew chrome startup finished.");
|
||||
|
||||
// Notify Java that Gecko has loaded.
|
||||
Messaging.sendRequest({ type: "Gecko:Ready" });
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -239,7 +239,7 @@ HelperAppLauncherDialog.prototype = {
|
||||
mimeType = ContentAreaUtils.getMIMETypeForURI(aLauncher.source) || "";
|
||||
}
|
||||
|
||||
Messaging.sendRequest({
|
||||
EventDispatcher.instance.sendRequest({
|
||||
'type': 'Download:AndroidDownloadManager',
|
||||
'uri': aLauncher.source.spec,
|
||||
'mimeType': mimeType,
|
||||
|
@ -311,7 +311,8 @@ SessionStore.prototype = {
|
||||
this._openTabs(data);
|
||||
|
||||
if (data.shouldNotifyTabsOpenedToJava) {
|
||||
Messaging.sendRequest({
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
window.WindowEventDispatcher.sendRequest({
|
||||
type: "Tabs:TabsOpened"
|
||||
});
|
||||
}
|
||||
@ -979,7 +980,8 @@ SessionStore.prototype = {
|
||||
|
||||
// If we have private data, send it to Java; otherwise, send null to
|
||||
// indicate that there is no private data
|
||||
Messaging.sendRequest({
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
window.WindowEventDispatcher.sendRequest({
|
||||
type: "PrivateBrowsing:Data",
|
||||
session: (privateData.windows.length > 0 && privateData.windows[0].tabs.length > 0) ? JSON.stringify(privateData) : null
|
||||
});
|
||||
|
@ -106,6 +106,9 @@ public final class EventDispatcher extends JNIObject {
|
||||
try {
|
||||
synchronized (listenersMap) {
|
||||
for (final String event : events) {
|
||||
if (event == null) {
|
||||
continue;
|
||||
}
|
||||
List<T> listeners = listenersMap.get(event);
|
||||
if (listeners == null) {
|
||||
// Java doesn't let us put Class<? extends List<T>> as the type for listType.
|
||||
@ -156,6 +159,9 @@ public final class EventDispatcher extends JNIObject {
|
||||
final String[] events) {
|
||||
synchronized (listenersMap) {
|
||||
for (final String event : events) {
|
||||
if (event == null) {
|
||||
continue;
|
||||
}
|
||||
List<T> listeners = listenersMap.get(event);
|
||||
if ((listeners == null ||
|
||||
!listeners.remove(listener)) && !AppConstants.RELEASE_OR_BETA) {
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.AppConstants.Versions;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UIAsyncTask;
|
||||
|
||||
@ -34,7 +34,7 @@ public class GeckoAccessibility {
|
||||
|
||||
private static boolean sEnabled;
|
||||
// Used to store the JSON message and populate the event later in the code path.
|
||||
private static JSONObject sHoverEnter;
|
||||
private static GeckoBundle sHoverEnter;
|
||||
private static AccessibilityNodeInfo sVirtualCursorNode;
|
||||
private static int sCurrentNode;
|
||||
|
||||
@ -76,32 +76,32 @@ public class GeckoAccessibility {
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private static void populateEventFromJSON (AccessibilityEvent event, JSONObject message) {
|
||||
final JSONArray textArray = message.optJSONArray("text");
|
||||
private static void populateEventFromJSON (AccessibilityEvent event, GeckoBundle message) {
|
||||
final String[] textArray = message.getStringArray("text");
|
||||
if (textArray != null) {
|
||||
for (int i = 0; i < textArray.length(); i++)
|
||||
event.getText().add(textArray.optString(i));
|
||||
for (int i = 0; i < textArray.length; i++)
|
||||
event.getText().add(textArray[i]);
|
||||
}
|
||||
|
||||
event.setContentDescription(message.optString("description"));
|
||||
event.setEnabled(message.optBoolean("enabled", true));
|
||||
event.setChecked(message.optBoolean("checked"));
|
||||
event.setPassword(message.optBoolean("password"));
|
||||
event.setAddedCount(message.optInt("addedCount", -1));
|
||||
event.setRemovedCount(message.optInt("removedCount", -1));
|
||||
event.setFromIndex(message.optInt("fromIndex", -1));
|
||||
event.setItemCount(message.optInt("itemCount", -1));
|
||||
event.setCurrentItemIndex(message.optInt("currentItemIndex", -1));
|
||||
event.setBeforeText(message.optString("beforeText"));
|
||||
event.setToIndex(message.optInt("toIndex", -1));
|
||||
event.setScrollable(message.optBoolean("scrollable"));
|
||||
event.setScrollX(message.optInt("scrollX", -1));
|
||||
event.setScrollY(message.optInt("scrollY", -1));
|
||||
event.setMaxScrollX(message.optInt("maxScrollX", -1));
|
||||
event.setMaxScrollY(message.optInt("maxScrollY", -1));
|
||||
event.setContentDescription(message.getString("description"));
|
||||
event.setEnabled(message.getBoolean("enabled", true));
|
||||
event.setChecked(message.getBoolean("checked"));
|
||||
event.setPassword(message.getBoolean("password"));
|
||||
event.setAddedCount(message.getInt("addedCount", -1));
|
||||
event.setRemovedCount(message.getInt("removedCount", -1));
|
||||
event.setFromIndex(message.getInt("fromIndex", -1));
|
||||
event.setItemCount(message.getInt("itemCount", -1));
|
||||
event.setCurrentItemIndex(message.getInt("currentItemIndex", -1));
|
||||
event.setBeforeText(message.getString("beforeText"));
|
||||
event.setToIndex(message.getInt("toIndex", -1));
|
||||
event.setScrollable(message.getBoolean("scrollable"));
|
||||
event.setScrollX(message.getInt("scrollX", -1));
|
||||
event.setScrollY(message.getInt("scrollY", -1));
|
||||
event.setMaxScrollX(message.getInt("maxScrollX", -1));
|
||||
event.setMaxScrollY(message.getInt("maxScrollY", -1));
|
||||
}
|
||||
|
||||
private static void sendDirectAccessibilityEvent(int eventType, JSONObject message) {
|
||||
private static void sendDirectAccessibilityEvent(int eventType, GeckoBundle message) {
|
||||
final Context context = GeckoAppShell.getApplicationContext();
|
||||
final AccessibilityEvent accEvent = AccessibilityEvent.obtain(eventType);
|
||||
accEvent.setClassName(GeckoAccessibility.class.getName());
|
||||
@ -120,11 +120,11 @@ public class GeckoAccessibility {
|
||||
return sEnabled;
|
||||
}
|
||||
|
||||
public static void sendAccessibilityEvent (final JSONObject message) {
|
||||
public static void sendAccessibilityEvent(final GeckoBundle message) {
|
||||
if (!sEnabled)
|
||||
return;
|
||||
|
||||
final int eventType = message.optInt("eventType", -1);
|
||||
final int eventType = message.getInt("eventType", -1);
|
||||
if (eventType < 0) {
|
||||
Log.e(LOGTAG, "No accessibility event type provided");
|
||||
return;
|
||||
@ -133,11 +133,11 @@ public class GeckoAccessibility {
|
||||
sendAccessibilityEvent(message, eventType);
|
||||
}
|
||||
|
||||
public static void sendAccessibilityEvent (final JSONObject message, final int eventType) {
|
||||
public static void sendAccessibilityEvent(final GeckoBundle message, final int eventType) {
|
||||
if (!sEnabled)
|
||||
return;
|
||||
|
||||
final String exitView = message.optString("exitView");
|
||||
final String exitView = message.getString("exitView");
|
||||
if (exitView.equals("moveNext")) {
|
||||
sCurrentNode = VIRTUAL_ENTRY_POINT_AFTER;
|
||||
} else if (exitView.equals("movePrevious")) {
|
||||
@ -162,29 +162,30 @@ public class GeckoAccessibility {
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
if (sVirtualCursorNode == null)
|
||||
if (sVirtualCursorNode == null) {
|
||||
sVirtualCursorNode = AccessibilityNodeInfo.obtain(view, VIRTUAL_CURSOR_POSITION);
|
||||
sVirtualCursorNode.setEnabled(message.optBoolean("enabled", true));
|
||||
sVirtualCursorNode.setClickable(message.optBoolean("clickable"));
|
||||
sVirtualCursorNode.setCheckable(message.optBoolean("checkable"));
|
||||
sVirtualCursorNode.setChecked(message.optBoolean("checked"));
|
||||
sVirtualCursorNode.setPassword(message.optBoolean("password"));
|
||||
}
|
||||
sVirtualCursorNode.setEnabled(message.getBoolean("enabled", true));
|
||||
sVirtualCursorNode.setClickable(message.getBoolean("clickable"));
|
||||
sVirtualCursorNode.setCheckable(message.getBoolean("checkable"));
|
||||
sVirtualCursorNode.setChecked(message.getBoolean("checked"));
|
||||
sVirtualCursorNode.setPassword(message.getBoolean("password"));
|
||||
|
||||
final JSONArray textArray = message.optJSONArray("text");
|
||||
final String[] textArray = message.getStringArray("text");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (textArray != null && textArray.length() > 0) {
|
||||
sb.append(textArray.optString(0));
|
||||
for (int i = 1; i < textArray.length(); i++) {
|
||||
sb.append(" ").append(textArray.optString(i));
|
||||
if (textArray != null && textArray.length > 0) {
|
||||
sb.append(textArray[0]);
|
||||
for (int i = 1; i < textArray.length; i++) {
|
||||
sb.append(" ").append(textArray[i]);
|
||||
}
|
||||
sVirtualCursorNode.setText(sb.toString());
|
||||
}
|
||||
sVirtualCursorNode.setContentDescription(message.optString("description"));
|
||||
sVirtualCursorNode.setContentDescription(message.getString("description"));
|
||||
|
||||
JSONObject bounds = message.optJSONObject("bounds");
|
||||
final GeckoBundle bounds = message.getBundle("bounds");
|
||||
if (bounds != null) {
|
||||
Rect relativeBounds = new Rect(bounds.optInt("left"), bounds.optInt("top"),
|
||||
bounds.optInt("right"), bounds.optInt("bottom"));
|
||||
Rect relativeBounds = new Rect(bounds.getInt("left"), bounds.getInt("top"),
|
||||
bounds.getInt("right"), bounds.getInt("bottom"));
|
||||
sVirtualCursorNode.setBoundsInParent(relativeBounds);
|
||||
int[] locationOnScreen = new int[2];
|
||||
view.getLocationOnScreen(locationOnScreen);
|
||||
@ -193,10 +194,10 @@ public class GeckoAccessibility {
|
||||
sVirtualCursorNode.setBoundsInScreen(screenBounds);
|
||||
}
|
||||
|
||||
final JSONObject braille = message.optJSONObject("brailleOutput");
|
||||
final GeckoBundle braille = message.getBundle("brailleOutput");
|
||||
if (braille != null) {
|
||||
sendBrailleText(view, braille.optString("text"),
|
||||
braille.optInt("selectionStart"), braille.optInt("selectionEnd"));
|
||||
sendBrailleText(view, braille.getString("text"),
|
||||
braille.getInt("selectionStart"), braille.getInt("selectionEnd"));
|
||||
}
|
||||
|
||||
if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER) {
|
||||
|
@ -551,13 +551,7 @@ public class GeckoThread extends Thread {
|
||||
// And... we're done.
|
||||
setState(State.EXITED);
|
||||
|
||||
try {
|
||||
final JSONObject msg = new JSONObject();
|
||||
msg.put("type", "Gecko:Exited");
|
||||
EventDispatcher.getInstance().dispatchEvent(msg, null);
|
||||
} catch (final JSONException e) {
|
||||
Log.e(LOGTAG, "unable to dispatch event", e);
|
||||
}
|
||||
EventDispatcher.getInstance().dispatch("Gecko:Exited", null);
|
||||
|
||||
// Remove pumpMessageLoop() idle handler
|
||||
Looper.myQueue().removeIdleHandler(idleHandler);
|
||||
|
@ -8,6 +8,10 @@ var Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm");
|
||||
|
||||
function LightweightThemeConsumer(aDocument) {
|
||||
this._doc = aDocument;
|
||||
@ -39,6 +43,6 @@ LightweightThemeConsumer.prototype = {
|
||||
|
||||
let msg = active ? { type: "LightweightTheme:Update", data: aData } :
|
||||
{ type: "LightweightTheme:Disable" };
|
||||
Services.androidBridge.handleGeckoMessage(msg);
|
||||
EventDispatcher.instance.sendRequest(msg);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["RuntimePermissions"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
|
||||
@ -36,6 +37,7 @@ var RuntimePermissions = {
|
||||
permissions: permissions
|
||||
};
|
||||
|
||||
return Messaging.sendRequestForResult(msg);
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
return window.WindowEventDispatcher.sendRequestForResult(msg);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -13,7 +13,6 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
Cu.import("resource://gre/modules/FormHistory.jsm");
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Downloads.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
@ -21,6 +20,8 @@ Cu.import("resource://gre/modules/Accounts.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration",
|
||||
"resource://gre/modules/DownloadIntegration.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm");
|
||||
|
||||
function dump(a) {
|
||||
Services.console.logStringMessage(a);
|
||||
@ -144,7 +145,7 @@ Sanitizer.prototype = {
|
||||
history: {
|
||||
clear: function ()
|
||||
{
|
||||
return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory" })
|
||||
return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:ClearHistory" })
|
||||
.catch(e => Cu.reportError("Java-side history clearing failed: " + e))
|
||||
.then(function() {
|
||||
try {
|
||||
@ -170,7 +171,7 @@ Sanitizer.prototype = {
|
||||
searchHistory: {
|
||||
clear: function ()
|
||||
{
|
||||
return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory", clearSearchHistory: true })
|
||||
return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:ClearHistory", clearSearchHistory: true })
|
||||
.catch(e => Cu.reportError("Java-side search history clearing failed: " + e))
|
||||
},
|
||||
|
||||
@ -283,7 +284,7 @@ Sanitizer.prototype = {
|
||||
syncedTabs: {
|
||||
clear: function ()
|
||||
{
|
||||
return Messaging.sendRequestForResult({ type: "Sanitize:ClearSyncedTabs" })
|
||||
return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:ClearSyncedTabs" })
|
||||
.catch(e => Cu.reportError("Java-side synced tabs clearing failed: " + e));
|
||||
},
|
||||
|
||||
|
@ -10,7 +10,7 @@ this.EXPORTED_SYMBOLS = ["Snackbars"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
|
||||
const LENGTH_INDEFINITE = -2;
|
||||
const LENGTH_LONG = 0;
|
||||
@ -45,9 +45,9 @@ var Snackbars = {
|
||||
msg.action.label = aOptions.action.label;
|
||||
}
|
||||
|
||||
Messaging.sendRequestForResult(msg).then(result => aOptions.action.callback());
|
||||
EventDispatcher.instance.sendRequestForResult(msg).then(result => aOptions.action.callback());
|
||||
} else {
|
||||
Messaging.sendRequest(msg);
|
||||
EventDispatcher.instance.sendRequest(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -69,4 +69,4 @@ function migrateToastIfNeeded(aDuration, aOptions) {
|
||||
};
|
||||
}
|
||||
return [duration, options];
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ this.EXPORTED_SYMBOLS = ["WebsiteMetadata"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
|
||||
|
||||
var WebsiteMetadata = {
|
||||
@ -32,10 +32,11 @@ var WebsiteMetadata = {
|
||||
let msg = {
|
||||
type: 'Website:Metadata',
|
||||
location: doc.location.href,
|
||||
metadata: metadata,
|
||||
hasImage: metadata.image_url && metadata.image_url !== "",
|
||||
metadata: JSON.stringify(metadata),
|
||||
};
|
||||
|
||||
Messaging.sendRequest(msg);
|
||||
EventDispatcher.instance.sendRequest(msg);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -68,7 +68,8 @@ abstract class BaseTest extends BaseRobocopTest {
|
||||
|
||||
protected void blockForDelayedStartup() {
|
||||
try {
|
||||
Actions.EventExpecter delayedStartupExpector = mActions.expectGeckoEvent("Gecko:DelayedStartup");
|
||||
Actions.EventExpecter delayedStartupExpector =
|
||||
mActions.expectGlobalEvent(Actions.EventType.UI, "Gecko:DelayedStartup");
|
||||
delayedStartupExpector.blockForEvent(GECKO_READY_WAIT_MS, true);
|
||||
delayedStartupExpector.unregisterListener();
|
||||
} catch (Exception e) {
|
||||
@ -78,7 +79,8 @@ abstract class BaseTest extends BaseRobocopTest {
|
||||
|
||||
protected void blockForGeckoReady() {
|
||||
try {
|
||||
Actions.EventExpecter geckoReadyExpector = mActions.expectGeckoEvent("Gecko:Ready");
|
||||
Actions.EventExpecter geckoReadyExpector =
|
||||
mActions.expectGlobalEvent(Actions.EventType.GECKO, "Gecko:Ready");
|
||||
if (!GeckoThread.isRunning()) {
|
||||
geckoReadyExpector.blockForEvent(GECKO_READY_WAIT_MS, true);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ abstract class ContentContextMenuTest extends PixelTest {
|
||||
if (!mSolo.searchText(contextMenuOption)) {
|
||||
openWebContentContextMenu(contextMenuOption); // Open the context menu if it is not already
|
||||
}
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
mSolo.clickOnText(contextMenuOption);
|
||||
tabEventExpecter.blockForEvent();
|
||||
tabEventExpecter.unregisterListener();
|
||||
|
@ -26,7 +26,7 @@ public final class GeckoHelper {
|
||||
}
|
||||
|
||||
public static void blockForReady() {
|
||||
blockForEvent("Gecko:Ready");
|
||||
blockForEvent(Actions.EventType.GECKO, "Gecko:Ready");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,11 +34,11 @@ public final class GeckoHelper {
|
||||
* first page load.
|
||||
*/
|
||||
public static void blockForDelayedStartup() {
|
||||
blockForEvent("Gecko:DelayedStartup");
|
||||
blockForEvent(Actions.EventType.UI, "Gecko:DelayedStartup");
|
||||
}
|
||||
|
||||
private static void blockForEvent(final String eventName) {
|
||||
final EventExpecter eventExpecter = sActions.expectGeckoEvent(eventName);
|
||||
private static void blockForEvent(final Actions.EventType type, final String eventName) {
|
||||
final EventExpecter eventExpecter = sActions.expectGlobalEvent(type, eventName);
|
||||
|
||||
if (!GeckoThread.isRunning()) {
|
||||
eventExpecter.blockForEvent();
|
||||
|
@ -29,7 +29,7 @@ public class testAboutPage extends PixelTest {
|
||||
verifyUrlInContentDescription(url);
|
||||
|
||||
// Set up listeners to catch the page load we're about to do.
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
|
||||
|
||||
selectSettingsItem(mStringHelper.MOZILLA_SECTION_LABEL, mStringHelper.ABOUT_LABEL);
|
||||
|
@ -29,7 +29,7 @@ public class testAddonManager extends PixelTest {
|
||||
selectMenuItem(mStringHelper.ADDONS_LABEL);
|
||||
|
||||
// Set up listeners to catch the page load we're about to do
|
||||
tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
|
||||
|
||||
// Wait for the new tab and page to load
|
||||
@ -50,7 +50,7 @@ public class testAddonManager extends PixelTest {
|
||||
verifyUrlBarTitle(aboutAddonsURL);
|
||||
|
||||
// Setup wait for tab to spawn and load
|
||||
tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
|
||||
|
||||
// Open a new tab
|
||||
|
@ -4,17 +4,16 @@
|
||||
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.Actions;
|
||||
import org.mozilla.gecko.Element;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
public class testBookmarksPanel extends AboutHomeTest {
|
||||
public void testBookmarksPanel() {
|
||||
final String BOOKMARK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
|
||||
JSONObject data = null;
|
||||
GeckoBundle data = null;
|
||||
|
||||
// Make sure our default bookmarks are loaded.
|
||||
// Technically this will race with the check below.
|
||||
@ -40,43 +39,27 @@ public class testBookmarksPanel extends AboutHomeTest {
|
||||
// Test that "Open in New Tab" works
|
||||
final Element tabCount = mDriver.findElement(getActivity(), R.id.tabs_counter);
|
||||
final int tabCountInt = Integer.parseInt(tabCount.getText());
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
mSolo.clickOnText(mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]);
|
||||
try {
|
||||
data = new JSONObject(tabEventExpecter.blockForEventData());
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "exception getting event data", e.toString());
|
||||
}
|
||||
|
||||
data = tabEventExpecter.blockForBundle();
|
||||
tabEventExpecter.unregisterListener();
|
||||
mAsserter.ok(mSolo.searchText(mStringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed");
|
||||
// extra check here on the Tab:Added message to be sure the right tab opened
|
||||
int tabID = 0;
|
||||
try {
|
||||
mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri");
|
||||
tabID = data.getInt("tabID");
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "exception accessing event data", e.toString());
|
||||
}
|
||||
mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri");
|
||||
// close tab so about:firefox can be selected again
|
||||
closeTab(tabID);
|
||||
closeTab(data.getInt("tabID"));
|
||||
|
||||
// Test that "Open in Private Tab" works
|
||||
openBookmarkContextMenu(mStringHelper.DEFAULT_BOOKMARKS_URLS[0]);
|
||||
tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
mSolo.clickOnText(mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[1]);
|
||||
try {
|
||||
data = new JSONObject(tabEventExpecter.blockForEventData());
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "exception getting event data", e.toString());
|
||||
}
|
||||
|
||||
data = tabEventExpecter.blockForBundle();
|
||||
tabEventExpecter.unregisterListener();
|
||||
mAsserter.ok(mSolo.searchText(mStringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed");
|
||||
// extra check here on the Tab:Added message to be sure the right tab opened, again
|
||||
try {
|
||||
mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri");
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "exception accessing event data", e.toString());
|
||||
}
|
||||
mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri");
|
||||
|
||||
// Test that "Edit" works
|
||||
String[] editedBookmarkValues = new String[] { "New bookmark title", "www.NewBookmark.url", "newBookmarkKeyword" };
|
||||
|
@ -7,10 +7,8 @@ package org.mozilla.gecko.tests;
|
||||
import android.widget.CheckBox;
|
||||
import android.view.View;
|
||||
import com.robotium.solo.Condition;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.Actions;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
/* This test will test if doorhangers are displayed and dismissed
|
||||
The test will test:
|
||||
@ -133,7 +131,7 @@ public class testDoorHanger extends BaseTest {
|
||||
mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), true, "Popup blocker is displayed");
|
||||
|
||||
// Wait for the popup to be shown.
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
Actions.EventExpecter tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
|
||||
waitForCheckBox();
|
||||
mSolo.clickOnCheckBox(0);
|
||||
@ -141,18 +139,14 @@ public class testDoorHanger extends BaseTest {
|
||||
waitForTextDismissed(mStringHelper.POPUP_MESSAGE);
|
||||
mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), false, "Popup blocker is hidden when popup allowed");
|
||||
|
||||
try {
|
||||
final JSONObject data = new JSONObject(tabEventExpecter.blockForEventData());
|
||||
final GeckoBundle data = tabEventExpecter.blockForBundle();
|
||||
|
||||
// Check to make sure the popup window was opened.
|
||||
mAsserter.is("data:text/plain;charset=utf-8,a", data.getString("uri"), "Checking popup URL");
|
||||
// Check to make sure the popup window was opened.
|
||||
mAsserter.is("data:text/plain;charset=utf-8,a", data.getString("uri"), "Checking popup URL");
|
||||
|
||||
// Close the popup window.
|
||||
closeTab(data.getInt("tabID"));
|
||||
// Close the popup window.
|
||||
closeTab(data.getInt("tabID"));
|
||||
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "exception getting event data", e.toString());
|
||||
}
|
||||
tabEventExpecter.unregisterListener();
|
||||
|
||||
// Load page with popup
|
||||
|
@ -6,10 +6,9 @@ package org.mozilla.gecko.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.Actions;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
/**
|
||||
* The test loads a new private tab and loads a page with a big link on it
|
||||
@ -27,7 +26,7 @@ public class testPrivateBrowsing extends ContentContextMenuTest {
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
Actions.EventExpecter tabExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
Actions.EventExpecter tabExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
Actions.EventExpecter contentExpecter = mActions.expectGeckoEvent("Content:PageShow");
|
||||
tabs.loadUrl(bigLinkUrl, Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_PRIVATE);
|
||||
tabExpecter.blockForEvent();
|
||||
@ -46,18 +45,19 @@ public class testPrivateBrowsing extends ContentContextMenuTest {
|
||||
mAsserter.ok(!mSolo.searchText(mStringHelper.CONTEXT_MENU_ITEMS_IN_NORMAL_TAB[0]), "Checking that 'Open Link in New Tab' is not displayed in the context menu", "'Open Link in New Tab' is not displayed in the context menu");
|
||||
|
||||
// Open the link in a new private tab and check that it is private
|
||||
tabExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
tabExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
contentExpecter = mActions.expectGeckoEvent("Content:PageShow");
|
||||
mSolo.clickOnText(mStringHelper.CONTEXT_MENU_ITEMS_IN_PRIVATE_TAB[0]);
|
||||
String eventData = tabExpecter.blockForEventData();
|
||||
|
||||
final GeckoBundle eventData = tabExpecter.blockForBundle();
|
||||
tabExpecter.unregisterListener();
|
||||
contentExpecter.blockForEvent();
|
||||
contentExpecter.unregisterListener();
|
||||
mAsserter.ok(isTabPrivate(eventData), "Checking if the new tab opened from the context menu was a private tab", "The tab was a private tab");
|
||||
mAsserter.ok(eventData.getBoolean("isPrivate"), "Checking if the new tab opened from the context menu was a private tab", "The tab was a private tab");
|
||||
verifyTabCount(2);
|
||||
|
||||
// Open a normal tab to check later that it was registered in the Firefox Browser History
|
||||
tabExpecter = mActions.expectGeckoEvent("Tab:Added");
|
||||
tabExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
|
||||
contentExpecter = mActions.expectGeckoEvent("Content:PageShow");
|
||||
tabs.loadUrl(blank2Url, Tabs.LOADURL_NEW_TAB);
|
||||
tabExpecter.blockForEvent();
|
||||
@ -76,14 +76,4 @@ public class testPrivateBrowsing extends ContentContextMenuTest {
|
||||
mAsserter.ok(!firefoxHistory.contains(blank1Url), "Check that the link opened in the private tab from the context menu was not saved", blank1Url + " was not added to history");
|
||||
mAsserter.ok(firefoxHistory.contains(blank2Url), "Check that the link opened in the normal tab was saved", blank2Url + " was added to history");
|
||||
}
|
||||
|
||||
private boolean isTabPrivate(String eventData) {
|
||||
try {
|
||||
JSONObject data = new JSONObject(eventData);
|
||||
return data.getBoolean("isPrivate");
|
||||
} catch (JSONException e) {
|
||||
mAsserter.ok(false, "Error parsing the event data", e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,14 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail;
|
||||
|
||||
public class testRuntimePermissionsAPI extends JavascriptTest implements NativeEventListener {
|
||||
public class testRuntimePermissionsAPI extends JavascriptTest implements BundleEventListener {
|
||||
public testRuntimePermissionsAPI() {
|
||||
super("testRuntimePermissionsAPI.js");
|
||||
}
|
||||
@ -20,18 +21,18 @@ public class testRuntimePermissionsAPI extends JavascriptTest implements NativeE
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this, "RuntimePermissions:Prompt");
|
||||
GeckoApp.getEventDispatcher().registerUiThreadListener(this, "RuntimePermissions:Prompt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this, "RuntimePermissions:Prompt");
|
||||
GeckoApp.getEventDispatcher().unregisterUiThreadListener(this, "RuntimePermissions:Prompt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
|
||||
public void handleMessage(String event, GeckoBundle message, EventCallback callback) {
|
||||
mAsserter.is(event, "RuntimePermissions:Prompt", "Received RuntimePermissions:Prompt event");
|
||||
|
||||
try {
|
||||
|
@ -7,11 +7,11 @@ package org.mozilla.gecko.tests;
|
||||
import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail;
|
||||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
public class testSnackbarAPI extends JavascriptTest implements NativeEventListener {
|
||||
public class testSnackbarAPI extends JavascriptTest implements BundleEventListener {
|
||||
// Snackbar.LENGTH_INDEFINITE: To avoid tests depending on the android design support library
|
||||
private static final int SNACKBAR_LENGTH_INDEFINITE = -2;
|
||||
|
||||
@ -20,14 +20,19 @@ public class testSnackbarAPI extends JavascriptTest implements NativeEventListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
|
||||
public void handleMessage(String event, GeckoBundle message, EventCallback callback) {
|
||||
if ("Robocop:WaitOnUI".equals(event)) {
|
||||
callback.sendSuccess(null);
|
||||
return;
|
||||
}
|
||||
|
||||
mAsserter.is(event, "Snackbar:Show", "Received Snackbar:Show event");
|
||||
|
||||
try {
|
||||
mAsserter.is(message.getString("message"), "This is a Snackbar", "Snackbar message");
|
||||
mAsserter.is(message.getInt("duration"), SNACKBAR_LENGTH_INDEFINITE, "Snackbar duration");
|
||||
|
||||
NativeJSObject action = message.getObject("action");
|
||||
GeckoBundle action = message.getBundle("action");
|
||||
|
||||
mAsserter.is(action.getString("label"), "Click me", "Snackbar action label");
|
||||
|
||||
@ -40,13 +45,15 @@ public class testSnackbarAPI extends JavascriptTest implements NativeEventListen
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this, "Snackbar:Show");
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Snackbar:Show");
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Robocop:WaitOnUI");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this, "Snackbar:Show");
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Snackbar:Show");
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Robocop:WaitOnUI");
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
|
||||
add_task(function* test_snackbar_api() {
|
||||
Snackbars.show("This is a Snackbar", Snackbars.LENGTH_INDEFINITE, {
|
||||
@ -16,6 +17,10 @@ add_task(function* test_snackbar_api() {
|
||||
callback: function () {}
|
||||
}
|
||||
});
|
||||
|
||||
yield EventDispatcher.instance.sendRequestForResult({
|
||||
type: "Robocop:WaitOnUI"
|
||||
});
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
|
@ -234,7 +234,7 @@ var Settings = {
|
||||
el.addEventListener("click", function() {
|
||||
if (AppConstants.platform == "android") {
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Messaging.sendRequest({
|
||||
EventDispatcher.instance.sendRequest({
|
||||
type: "Settings:Show",
|
||||
resource: "preferences_privacy",
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user