This commit is contained in:
Wes Kocher 2013-12-10 15:58:54 -08:00
Родитель 2b769f4918 f1c64af7fe
Коммит 0df0709ec5
6 изменённых файлов: 194 добавлений и 18 удалений

Просмотреть файл

@ -79,6 +79,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "OS",
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
"resource:///modules/BrowserUITelemetry.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -476,6 +479,7 @@ BrowserGlue.prototype = {
webrtcUI.init();
AboutHome.init();
SessionStore.init();
BrowserUITelemetry.init();
if (Services.prefs.getBoolPref("browser.tabs.remote"))
ContentClick.init();

Просмотреть файл

@ -0,0 +1,161 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
"use strict";
this.EXPORTED_SYMBOLS = ["BrowserUITelemetry"];
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
"resource://gre/modules/UITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
const ALL_BUILTIN_ITEMS = [
"fullscreen-button",
"switch-to-metro-button",
];
this.BrowserUITelemetry = {
init: function() {
UITelemetry.addSimpleMeasureFunction("toolbars",
this.getToolbarMeasures.bind(this));
Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
},
observe: function(aSubject, aTopic, aData) {
if (aTopic == "browser-delayed-startup-finished") {
this._registerWindow(aSubject);
}
},
/**
* For the _countableEvents object, constructs a chain of
* Javascript Objects with the keys in aKeys, with the final
* key getting the value in aEndWith. If the final key already
* exists in the final object, its value is not set. In either
* case, a reference to the second last object in the chain is
* returned.
*
* Example - suppose I want to store:
* _countableEvents: {
* a: {
* b: {
* c: 0
* }
* }
* }
*
* And then increment the "c" value by 1, you could call this
* function like this:
*
* let example = this._ensureObjectChain([a, b, c], 0);
* example["c"]++;
*
* Subsequent repetitions of these last two lines would
* simply result in the c value being incremented again
* and again.
*
* @param aKeys the Array of keys to chain Objects together with.
* @param aEndWith the value to assign to the last key.
* @returns a reference to the second last object in the chain -
* so in our example, that'd be "b".
*/
_ensureObjectChain: function(aKeys, aEndWith) {
let current = this._countableEvents;
let parent = null;
for (let [i, key] of Iterator(aKeys)) {
if (!(key in current)) {
if (i == aKeys.length - 1) {
current[key] = aEndWith;
} else {
current[key] = {};
}
}
parent = current;
current = current[key];
}
return parent;
},
_countableEvents: {},
_countMouseUpEvent: function(aCategory, aAction, aMouseUpEvent) {
const BUTTONS = ["left", "middle", "right"];
let buttonKey = BUTTONS[aMouseUpEvent.button];
if (buttonKey) {
let countObject =
this._ensureObjectChain([aCategory, aAction, buttonKey], 0);
countObject[buttonKey]++;
}
},
_registerWindow: function(aWindow) {
aWindow.addEventListener("unload", this);
let document = aWindow.document;
for (let areaID of CustomizableUI.areas) {
let areaNode = document.getElementById(areaID);
(areaNode.customizationTarget || areaNode).addEventListener("mouseup", this);
}
},
_unregisterWindow: function(aWindow) {
aWindow.removeEventListener("unload", this);
let document = aWindow.document;
for (let areaID of CustomizableUI.areas) {
let areaNode = document.getElementById(areaID);
(areaNode.customizationTarget || areaNode).removeEventListener("mouseup", this);
}
},
handleEvent: function(aEvent) {
switch(aEvent.type) {
case "unload":
this._unregisterWindow(aEvent.currentTarget);
break;
case "mouseup":
this._handleMouseUp(aEvent);
break;
}
},
_handleMouseUp: function(aEvent) {
let item = aEvent.originalTarget;
// Perhaps we're seeing one of the default toolbar items
// being clicked.
if (ALL_BUILTIN_ITEMS.indexOf(item.id) != -1) {
// Base case - we clicked directly on one of our built-in items,
// and we can go ahead and register that click.
this._countMouseUpEvent("click-builtin-item", item.id, aEvent);
}
},
getToolbarMeasures: function() {
// Grab the most recent non-popup, non-private browser window for us to
// analyze the toolbars in...
let win = RecentWindow.getMostRecentBrowserWindow({
private: false,
allowPopups: false
});
// If there are no such windows, we're out of luck. :(
if (!win) {
return {};
}
let document = win.document;
let result = {};
result.countableEvents = this._countableEvents;
return result;
},
};

Просмотреть файл

@ -8,6 +8,7 @@ TEST_DIRS += ['test']
EXTRA_JS_MODULES += [
'BrowserNewTabPreloader.jsm',
'BrowserUITelemetry.jsm',
'CharsetMenu.jsm',
'ContentClick.jsm',
'NetworkPrioritizer.jsm',

Просмотреть файл

@ -49,6 +49,12 @@
<item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>
<item name="homeListViewStyle">@style/Widget.HomeListView</item>
<item name="menuItemActionModeStyle">@style/GeckoActionBar.Button</item>
<item name="android:actionModeStyle">@style/GeckoActionBar</item>
<item name="android:actionButtonStyle">@style/GeckoActionBar.Button</item>
<item name="android:actionModeCutDrawable">@drawable/cut</item>
<item name="android:actionModeCopyDrawable">@drawable/copy</item>
<item name="android:actionModePasteDrawable">@drawable/paste</item>
<item name="android:actionModeSelectAllDrawable">@drawable/select_all</item>
</style>
</resources>

Просмотреть файл

@ -15,7 +15,7 @@ import java.util.concurrent.SynchronousQueue;
public final class Clipboard {
private static Context mContext;
private final static String LOG_TAG = "Clipboard";
private final static String LOGTAG = "GeckoClipboard";
private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
private Clipboard() {
@ -23,7 +23,7 @@ public final class Clipboard {
public static void init(Context c) {
if (mContext != null) {
Log.w(LOG_TAG, "Clipboard.init() called twice!");
Log.w(LOGTAG, "Clipboard.init() called twice!");
return;
}
mContext = c;
@ -62,7 +62,7 @@ public final class Clipboard {
@SuppressWarnings("deprecation")
public void run() {
if (Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = getClipboardManager11(mContext);
android.content.ClipboardManager cm = getClipboardManager(mContext);
ClipData clip = ClipData.newPlainText("Text", text);
try {
cm.setPrimaryClip(clip);
@ -72,7 +72,7 @@ public final class Clipboard {
// Fortunately, the text is still successfully copied to the clipboard.
}
} else {
android.text.ClipboardManager cm = getClipboardManager(mContext);
android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
cm.setText(text);
}
}
@ -86,8 +86,13 @@ public final class Clipboard {
*/
@WrapElementForJNI
public static boolean hasText() {
String text = getText();
return text != null;
if (Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = getClipboardManager(mContext);
return cm.hasPrimaryClip();
}
android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
return cm.hasText();
}
/**
@ -98,13 +103,13 @@ public final class Clipboard {
setText(null);
}
private static android.content.ClipboardManager getClipboardManager11(Context context) {
private static android.content.ClipboardManager getClipboardManager(Context context) {
// In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
// which is a subclass of android.text.ClipboardManager.
return (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
}
private static android.text.ClipboardManager getClipboardManager(Context context) {
private static android.text.ClipboardManager getDeprecatedClipboardManager(Context context) {
return (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
}
@ -114,7 +119,7 @@ public final class Clipboard {
@SuppressWarnings("deprecation")
private static String getClipboardTextImpl() {
if (Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = getClipboardManager11(mContext);
android.content.ClipboardManager cm = getClipboardManager(mContext);
if (cm.hasPrimaryClip()) {
ClipData clip = cm.getPrimaryClip();
if (clip != null) {
@ -123,7 +128,7 @@ public final class Clipboard {
}
}
} else {
android.text.ClipboardManager cm = getClipboardManager(mContext);
android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
if (cm.hasText()) {
return cm.getText().toString();
}

Просмотреть файл

@ -315,11 +315,14 @@ var SelectionHandler = {
label: this._getValue(action, "label", ""),
icon: this._getValue(action, "icon", "drawable://ic_status_logo"),
showAsAction: this._getValue(action, "showAsAction", true),
order: this._getValue(action, "order", 0)
};
actions.push(a);
}
}
actions.sort((a, b) => b.order - a.order);
sendMessageToJava({
type: type,
handles: handles,
@ -340,6 +343,7 @@ var SelectionHandler = {
SelectionHandler.selectAll(aElement);
},
selector: ClipboardHelper.selectAllContext,
order: 1,
},
CUT: {
@ -356,6 +360,7 @@ var SelectionHandler = {
// copySelection closes the selection. Show a caret where we just cut the text.
SelectionHandler.attachCaret(aElement);
},
order: 1,
selector: ClipboardHelper.cutContext,
},
@ -366,6 +371,7 @@ var SelectionHandler = {
action: function() {
SelectionHandler.copySelection();
},
order: 1,
selector: ClipboardHelper.getCopyContext(false)
},
@ -378,6 +384,7 @@ var SelectionHandler = {
SelectionHandler._positionHandles();
SelectionHandler._updateMenu();
},
order: 1,
selector: ClipboardHelper.pasteContext,
},
@ -388,10 +395,6 @@ var SelectionHandler = {
action: function() {
SelectionHandler.shareSelection();
},
showAsAction: function(aElement) {
return !((aElement instanceof HTMLInputElement && aElement.mozIsTextField(false)) ||
(aElement instanceof HTMLTextAreaElement));
},
selector: ClipboardHelper.shareContext,
},
@ -401,10 +404,6 @@ var SelectionHandler = {
},
id: "search_action",
icon: "drawable://ic_url_bar_search",
showAsAction: function(aElement) {
return !((aElement instanceof HTMLInputElement && aElement.mozIsTextField(false)) ||
(aElement instanceof HTMLTextAreaElement));
},
action: function() {
SelectionHandler.searchSelection();
SelectionHandler._closeSelection();