Merge m-c to inbound, a=merge

This commit is contained in:
Wes Kocher 2015-07-06 17:20:44 -07:00
commit f93edc4449
78 changed files with 1400 additions and 300 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "dc6c18c0dea7af3c40bfff86c530fd877d899dc4",
"git_revision": "2673b2501d86f0d6230ee5328e6f7ba054f938a0",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "eed37c94d1a7e2581513af12d3bedaa9342dee43",
"revision": "d5367c89aeb2c2c892bb51c808b63ccc21d5ed22",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dc6c18c0dea7af3c40bfff86c530fd877d899dc4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2673b2501d86f0d6230ee5328e6f7ba054f938a0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -43,7 +43,7 @@
<div class="graphic graphic-sync-intro"> </div>
<div class="button-row">
<button id="buttonOpenPrefs" class="button" href="#" tabindex="0">&aboutAccountsConfig.manage.label;</button>
<button id="buttonOpenPrefs" class="button" href="#" tabindex="0">&aboutAccountsConfig.syncPreferences.label;</button>
</div>
</section>
</div>

View File

@ -266,6 +266,11 @@ let gFxAccounts = {
let signedInTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
let updateWithUserData = (userData) => {
// Window might have been closed while fetching data.
if (window.closed) {
return;
}
// Reset the button to its original state.
this.panelUILabel.setAttribute("label", defaultLabel);
this.panelUIStatus.removeAttribute("tooltiptext");

View File

@ -6683,9 +6683,20 @@ var gIdentityHandler = {
this._identityPopup.hidePopup();
},
showSubView(name, anchor) {
toggleSubView(name, anchor) {
let view = document.getElementById("identity-popup-multiView");
view.showSubView(`identity-popup-${name}View`, anchor);
if (view.showingSubView) {
view.showMainView();
} else {
view.showSubView(`identity-popup-${name}View`, anchor);
}
// If an element is focused that's not the anchor, clear the focus.
// Elements of hidden views have -moz-user-focus:ignore but setting that
// per CSS selector doesn't blur a focused element in those hidden views.
if (Services.focus.focusedElement != anchor) {
Services.focus.clearFocus(window);
}
},
/**
@ -7054,11 +7065,6 @@ var gIdentityHandler = {
this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
},
onPopupShown : function(event) {
this._identityPopup.addEventListener("blur", this, true);
this._identityPopup.addEventListener("popuphidden", this);
},
onDragStart: function (event) {
if (gURLBar.getAttribute("pageproxystate") != "valid")
return;
@ -7075,26 +7081,6 @@ var gIdentityHandler = {
dt.setDragImage(gProxyFavIcon, 16, 16);
},
handleEvent: function (event) {
switch (event.type) {
case "blur":
// Focus hasn't moved yet, need to wait until after the blur event.
setTimeout(() => {
if (document.activeElement &&
document.activeElement.compareDocumentPosition(this._identityPopup) &
Node.DOCUMENT_POSITION_CONTAINS)
return;
this._identityPopup.hidePopup();
}, 0);
break;
case "popuphidden":
this._identityPopup.removeEventListener("blur", this, true);
this._identityPopup.removeEventListener("popuphidden", this);
break;
}
},
updateSitePermissions: function () {
while (this._permissionList.hasChildNodes())
this._permissionList.removeChild(this._permissionList.lastChild);

View File

@ -220,7 +220,6 @@ skip-if = toolkit != "cocoa"
[browser_bug580956.js]
[browser_bug581242.js]
[browser_bug581253.js]
skip-if = e10s # Bug 1093756 - can't bookmark the data: url in e10s somehow
[browser_bug581947.js]
[browser_bug585558.js]
[browser_bug585785.js]
@ -234,7 +233,6 @@ skip-if = e10s # Bug 653065 - Make the lightweight theme web installer ready for
[browser_bug597218.js]
[browser_bug609700.js]
[browser_bug623155.js]
skip-if = e10s && debug
[browser_bug623893.js]
[browser_bug624734.js]
[browser_bug633691.js]
@ -245,7 +243,6 @@ skip-if = buildapp == 'mulet'
[browser_bug676619.js]
skip-if = buildapp == 'mulet' || os == "mac" # mac: Intermittent failures, bug 925225
[browser_bug678392.js]
skip-if = e10s # bug 1102331 - does focus things on the content window which break in e10s mode
[browser_bug710878.js]
[browser_bug719271.js]
[browser_bug724239.js]
@ -260,7 +257,6 @@ skip-if = e10s # bug 1102331 - does focus things on the content window which bre
[browser_bug832435.js]
[browser_bug839103.js]
[browser_bug880101.js]
skip-if = e10s # Bug 1126316 - New e10s windows erroneously fire initial about:blank location through nsIWebProgressListener
[browser_bug882977.js]
[browser_bug902156.js]
[browser_bug906190.js]
@ -295,7 +291,6 @@ skip-if = e10s
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
[browser_favicon_change.js]
[browser_favicon_change_not_in_document.js]
skip-if = e10s
[browser_findbarClose.js]
[browser_fullscreen-window-open.js]
skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
@ -309,11 +304,10 @@ skip-if = e10s # Bug 863514 - no gesture support.
[browser_homeDrop.js]
skip-if = buildapp == 'mulet'
[browser_identity_UI.js]
skip-if = e10s && debug # Seeing lots of timeouts (bug 1095517)
skip-if = debug # Seeing lots of timeouts (bug 1095517)
[browser_keywordBookmarklets.js]
skip-if = e10s # Bug 1102025 - different principals for the bookmarklet only in e10s mode (unclear if test or 'real' issue)
[browser_keywordSearch.js]
skip-if = e10s # Bug 921957 - remote webprogress doesn't supply cancel method on the request object
[browser_keywordSearch_postData.js]
[browser_lastAccessedTab.js]
skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bug 969405)
@ -334,12 +328,9 @@ skip-if = buildapp == 'mulet' || e10s # Bug 1093603 - test breaks with PopupNoti
[browser_pageInfo.js]
skip-if = buildapp == 'mulet'
[browser_page_style_menu.js]
[browser_parsable_css.js]
skip-if = e10s
[browser_parsable_script.js]
skip-if = asan || (os == 'linux' && !debug && (bits == 32)) # disabled on asan because of timeouts, and bug 1172468 for the linux 32-bit pgo issue.
[browser_pinnedTabs.js]
[browser_plainTextLinks.js]
[browser_popupUI.js]
@ -377,7 +368,6 @@ skip-if = buildapp == 'mulet'
[browser_save_video_frame.js]
[browser_scope.js]
[browser_searchSuggestionUI.js]
skip-if = e10s
support-files =
searchSuggestionUI.html
searchSuggestionUI.js
@ -388,7 +378,6 @@ run-if = e10s
[browser_star_hsts.js]
[browser_subframe_favicons_not_used.js]
[browser_syncui.js]
skip-if = e10s # Bug 1137087 - browser_tabopen_reflows.js fails if this was previously run with e10s
[browser_tabDrop.js]
skip-if = buildapp == 'mulet' || e10s
[browser_tabReorder.js]
@ -407,7 +396,6 @@ skip-if = buildapp == 'mulet'
skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
# Disabled on OS X because of bug 967917
[browser_tabfocus.js]
skip-if = e10s && debug # Bug 907326
[browser_tabkeynavigation.js]
skip-if = e10s
[browser_tabopen_reflows.js]
@ -455,7 +443,7 @@ skip-if = true # Bug 1005420 - fails intermittently. also with e10s enabled: biz
[browser_visibleTabs_bookmarkAllTabs.js]
[browser_visibleTabs_contextMenu.js]
[browser_visibleTabs_tabPreview.js]
skip-if = (os == "win" && !debug) || e10s # Bug 1007418
skip-if = (os == "win" && !debug)
[browser_web_channel.js]
[browser_windowopen_reflows.js]
skip-if = buildapp == 'mulet'

View File

@ -5,9 +5,6 @@
<panel id="identity-popup"
type="arrow"
hidden="true"
noautofocus="true"
onpopupshown="if (event.target == this)
gIdentityHandler.onPopupShown(event);"
orient="vertical"
level="top">
@ -33,7 +30,7 @@
value="&identity.connectionInternal;"/>
</vbox>
<button class="identity-popup-expander"
oncommand="gIdentityHandler.showSubView('security', this)"/>
oncommand="gIdentityHandler.toggleSubView('security', this)"/>
</hbox>
<!-- Tracking Protection Section -->

View File

@ -15,7 +15,7 @@
<content>
<xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
<xul:stack anonid="viewStack" xbl:inherits="viewtype,transitioning" viewtype="main" class="panel-viewstack">
<xul:vbox anonid="mainViewContainer" class="panel-mainview"/>
<xul:vbox anonid="mainViewContainer" class="panel-mainview" xbl:inherits="viewtype"/>
<!-- Used to capture click events over the PanelUI-mainView if we're in
subview mode. That way, any click on the PanelUI-mainView causes us

View File

@ -459,7 +459,7 @@ loop.conversationViews = (function(mozL10n) {
_onEmailLinkReceived: function() {
var emailLink = this.getStoreState().emailLink;
var contactEmail = _getPreferredEmail(this.props.contact).value;
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
sharedUtils.composeCallUrlEmail(emailLink, contactEmail, null, "callfailed");
this.closeWindow();
},

View File

@ -459,7 +459,7 @@ loop.conversationViews = (function(mozL10n) {
_onEmailLinkReceived: function() {
var emailLink = this.getStoreState().emailLink;
var contactEmail = _getPreferredEmail(this.props.contact).value;
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
sharedUtils.composeCallUrlEmail(emailLink, contactEmail, null, "callfailed");
this.closeWindow();
},

View File

@ -546,7 +546,8 @@ loop.panel = (function(_, mozL10n) {
event.stopPropagation();
event.preventDefault();
this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
roomUrl: this.props.room.roomUrl
roomUrl: this.props.room.roomUrl,
from: "panel"
}));
this.setState({urlCopied: true});
},

View File

@ -546,7 +546,8 @@ loop.panel = (function(_, mozL10n) {
event.stopPropagation();
event.preventDefault();
this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
roomUrl: this.props.room.roomUrl
roomUrl: this.props.room.roomUrl,
from: "panel"
}));
this.setState({urlCopied: true});
},

View File

@ -275,7 +275,9 @@ loop.store = loop.store || {};
this._notifications.remove("create-room-error");
this._mozLoop.rooms.create(roomCreationData, function(err, createdRoom) {
var buckets = this._mozLoop.ROOM_CREATE;
if (err) {
this._mozLoop.telemetryAddValue("LOOP_ROOM_CREATE", buckets.CREATE_FAIL);
this.dispatchAction(new sharedActions.CreateRoomError({error: err}));
return;
}
@ -283,6 +285,16 @@ loop.store = loop.store || {};
this.dispatchAction(new sharedActions.CreatedRoom({
roomToken: createdRoom.roomToken
}));
this._mozLoop.telemetryAddValue("LOOP_ROOM_CREATE", buckets.CREATE_SUCCESS);
// Since creating a room with context is only possible from the panel,
// we can record that as the action here.
var URLs = roomCreationData.decryptedContext.urls;
if (URLs && URLs.length) {
buckets = this._mozLoop.ROOM_CONTEXT_ADD;
this._mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_ADD",
buckets.ADD_FROM_PANEL);
}
}.bind(this));
},
@ -325,6 +337,14 @@ loop.store = loop.store || {};
copyRoomUrl: function(actionData) {
this._mozLoop.copyString(actionData.roomUrl);
this._mozLoop.notifyUITour("Loop:RoomURLCopied");
var from = actionData.from;
var bucket = this._mozLoop.SHARING_ROOM_URL["COPY_FROM_" + from.toUpperCase()];
if (typeof bucket === "undefined") {
console.error("No URL sharing type bucket found for '" + from + "'");
return;
}
this._mozLoop.telemetryAddValue("LOOP_SHARING_ROOM_URL", bucket);
},
/**
@ -334,7 +354,7 @@ loop.store = loop.store || {};
*/
emailRoomUrl: function(actionData) {
loop.shared.utils.composeCallUrlEmail(actionData.roomUrl, null,
actionData.roomDescription);
actionData.roomDescription, actionData.from);
this._mozLoop.notifyUITour("Loop:RoomURLEmailed");
},
@ -390,9 +410,12 @@ loop.store = loop.store || {};
*/
deleteRoom: function(actionData) {
this._mozLoop.rooms.delete(actionData.roomToken, function(err) {
var buckets = this._mozLoop.ROOM_DELETE;
if (err) {
this.dispatchAction(new sharedActions.DeleteRoomError({error: err}));
this.dispatchAction(new sharedActions.DeleteRoomError({error: err}));
}
this._mozLoop.telemetryAddValue("LOOP_ROOM_DELETE", buckets[err ?
"DELETE_FAIL" : "DELETE_SUCCESS"]);
}.bind(this));
},
@ -521,6 +544,8 @@ loop.store = loop.store || {};
return;
}
var hadContextBefore = !!oldRoomURL;
this.setStoreState({error: null});
this._mozLoop.rooms.update(actionData.roomToken, roomData,
function(error, data) {
@ -528,6 +553,15 @@ loop.store = loop.store || {};
new sharedActions.UpdateRoomContextError({ error: error }) :
new sharedActions.UpdateRoomContextDone();
this.dispatchAction(action);
if (!err && !hadContextBefore) {
// Since updating the room context data is only possible from the
// conversation window, we can assume that any newly added URL was
// done from there.
var buckets = this._mozLoop.ROOM_CONTEXT_ADD;
this._mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_ADD",
buckets.ADD_FROM_CONVERSATION);
}
}.bind(this));
}.bind(this));
},

View File

@ -178,15 +178,18 @@ loop.roomViews = (function(mozL10n) {
this.props.dispatcher.dispatch(
new sharedActions.EmailRoomUrl({
roomUrl: roomData.roomUrl,
roomDescription: contextURL && contextURL.description
roomDescription: contextURL && contextURL.description,
from: "conversation"
}));
},
handleCopyButtonClick: function(event) {
event.preventDefault();
this.props.dispatcher.dispatch(
new sharedActions.CopyRoomUrl({roomUrl: this.props.roomData.roomUrl}));
this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
roomUrl: this.props.roomData.roomUrl,
from: "conversation"
}));
this.setState({copiedUrl: true});
},
@ -395,7 +398,10 @@ loop.roomViews = (function(mozL10n) {
return;
}
this.props.mozLoop.openURL(url.location);
var mozLoop = this.props.mozLoop;
mozLoop.openURL(url.location);
mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_CLICK", 1);
},
handleCheckboxChange: function(state) {

View File

@ -178,15 +178,18 @@ loop.roomViews = (function(mozL10n) {
this.props.dispatcher.dispatch(
new sharedActions.EmailRoomUrl({
roomUrl: roomData.roomUrl,
roomDescription: contextURL && contextURL.description
roomDescription: contextURL && contextURL.description,
from: "conversation"
}));
},
handleCopyButtonClick: function(event) {
event.preventDefault();
this.props.dispatcher.dispatch(
new sharedActions.CopyRoomUrl({roomUrl: this.props.roomData.roomUrl}));
this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
roomUrl: this.props.roomData.roomUrl,
from: "conversation"
}));
this.setState({copiedUrl: true});
},
@ -395,7 +398,10 @@ loop.roomViews = (function(mozL10n) {
return;
}
this.props.mozLoop.openURL(url.location);
var mozLoop = this.props.mozLoop;
mozLoop.openURL(url.location);
mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_CLICK", 1);
},
handleCheckboxChange: function(state) {

View File

@ -415,6 +415,7 @@ loop.shared.actions = (function() {
* XXX: should move to some roomActions module - refs bug 1079284
*/
CopyRoomUrl: Action.define("copyRoomUrl", {
from: String,
roomUrl: String
}),
@ -423,6 +424,7 @@ loop.shared.actions = (function() {
* XXX: should move to some roomActions module - refs bug 1079284
*/
EmailRoomUrl: Action.define("emailRoomUrl", {
from: String,
roomUrl: String
// roomDescription: String, Optional.
}),

View File

@ -439,11 +439,14 @@ loop.store = loop.store || {};
maxSize: loop.store.MAX_ROOM_CREATION_SIZE,
expiresIn: loop.store.DEFAULT_EXPIRES_IN
}, function(err, createdRoomData) {
var buckets = this.mozLoop.ROOM_CREATE;
if (err) {
this.trigger("error:emailLink");
this.mozLoop.telemetryAddValue("LOOP_ROOM_CREATE", buckets.CREATE_FAIL);
return;
}
this.setStoreState({"emailLink": createdRoomData.roomUrl});
this.mozLoop.telemetryAddValue("LOOP_ROOM_CREATE", buckets.CREATE_SUCCESS);
}.bind(this));
},

View File

@ -388,9 +388,11 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
* @param {String} callUrl The call URL.
* @param {String} [recipient] The recipient email address (optional).
* @param {String} [contextDescription] The context description (optional).
* @param {String} [from] The area from which this function is called.
*/
function composeCallUrlEmail(callUrl, recipient, contextDescription) {
if (typeof navigator.mozLoop === "undefined") {
function composeCallUrlEmail(callUrl, recipient, contextDescription, from) {
var mozLoop = navigator.mozLoop;
if (typeof mozLoop === "undefined") {
console.warn("composeCallUrlEmail isn't available for Loop standalone.");
return;
}
@ -399,7 +401,7 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
var brandShortname = mozL10n.get("brandShortname");
var clientShortname2 = mozL10n.get("clientShortname2");
var clientSuperShortname = mozL10n.get("clientSuperShortname");
var learnMoreUrl = navigator.mozLoop.getLoopPref("learnMoreUrl");
var learnMoreUrl = mozLoop.getLoopPref("learnMoreUrl");
if (contextDescription) {
subject = mozL10n.get("share_email_subject_context", {
@ -427,11 +429,18 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
});
}
navigator.mozLoop.composeEmail(
mozLoop.composeEmail(
subject,
body.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n"),
recipient
);
var bucket = mozLoop.SHARING_ROOM_URL["EMAIL_FROM_" + (from || "").toUpperCase()];
if (typeof bucket === "undefined") {
console.error("No URL sharing type bucket found for '" + from + "'");
return;
}
mozLoop.telemetryAddValue("LOOP_SHARING_ROOM_URL", bucket);
}
// We can alias `subarray` to `slice` when the latter is not available, because

View File

@ -674,6 +674,34 @@ function injectLoopAPI(targetWindow) {
}
},
SHARING_ROOM_URL: {
enumerable: true,
get: function() {
return Cu.cloneInto(SHARING_ROOM_URL, targetWindow);
}
},
ROOM_CREATE: {
enumerable: true,
get: function() {
return Cu.cloneInto(ROOM_CREATE, targetWindow);
}
},
ROOM_DELETE: {
enumerable: true,
get: function() {
return Cu.cloneInto(ROOM_DELETE, targetWindow);
}
},
ROOM_CONTEXT_ADD: {
enumerable: true,
get: function() {
return Cu.cloneInto(ROOM_CONTEXT_ADD, targetWindow);
}
},
fxAEnabled: {
enumerable: true,
get: function() {

View File

@ -42,6 +42,49 @@ const SHARING_STATE_CHANGE = {
BROWSER_DISABLED: 3
};
/**
* Values that we segment sharing a room URL action telemetry probes into.
*
* @type {{COPY_FROM_PANEL: Number, COPY_FROM_CONVERSATION: Number,
* EMAIL_FROM_CALLFAILED: Number, EMAIL_FROM_CONVERSATION: Number}}
*/
const SHARING_ROOM_URL = {
COPY_FROM_PANEL: 0,
COPY_FROM_CONVERSATION: 1,
EMAIL_FROM_CALLFAILED: 2,
EMAIL_FROM_CONVERSATION: 3
};
/**
* Values that we segment room create action telemetry probes into.
*
* @type {{CREATE_SUCCESS: Number, CREATE_FAIL: Number}}
*/
const ROOM_CREATE = {
CREATE_SUCCESS: 0,
CREATE_FAIL: 1
};
/**
* Values that we segment room delete action telemetry probes into.
*
* @type {{DELETE_SUCCESS: Number, DELETE_FAIL: Number}}
*/
const ROOM_DELETE = {
DELETE_SUCCESS: 0,
DELETE_FAIL: 1
};
/**
* Values that we segment room context action telemetry probes into.
*
* @type {{ADD_FROM_PANEL: Number, ADD_FROM_CONVERSATION: Number}}
*/
const ROOM_CONTEXT_ADD = {
ADD_FROM_PANEL: 0,
ADD_FROM_CONVERSATION: 1
};
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
const PREF_LOG_LEVEL = "loop.debug.loglevel";
@ -56,7 +99,8 @@ Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
Cu.importGlobalProperties(["URL"]);
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE",
"TWO_WAY_MEDIA_CONN_LENGTH", "SHARING_STATE_CHANGE"];
"TWO_WAY_MEDIA_CONN_LENGTH", "SHARING_STATE_CHANGE", "SHARING_ROOM_URL",
"ROOM_CREATE", "ROOM_DELETE", "ROOM_CONTEXT_ADD"];
XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
"resource:///modules/loop/MozLoopAPI.jsm");

View File

@ -52,6 +52,10 @@ describe("loop.conversationViews", function () {
};
fakeMozLoop = navigator.mozLoop = {
SHARING_ROOM_URL: {
EMAIL_FROM_CALLFAILED: 2,
EMAIL_FROM_CONVERSATION: 3
},
// Dummy function, stubbed below.
getLoopPref: function() {},
calls: {
@ -255,7 +259,7 @@ describe("loop.conversationViews", function () {
});
describe("CallFailedView", function() {
var fakeAudio;
var fakeAudio, composeCallUrlEmail;
var fakeContact = {email: [{value: "test@test.tld"}]};
@ -275,6 +279,7 @@ describe("loop.conversationViews", function () {
removeAttribute: sinon.spy()
};
sandbox.stub(window, "Audio").returns(fakeAudio);
composeCallUrlEmail = sandbox.stub(sharedUtils, "composeCallUrlEmail");
});
it("should dispatch a retryCall action when the retry button is pressed",
@ -346,13 +351,12 @@ describe("loop.conversationViews", function () {
});
it("should compose an email once the email link is received", function() {
var composeCallUrlEmail = sandbox.stub(sharedUtils, "composeCallUrlEmail");
view = mountTestComponent({contact: fakeContact});
conversationStore.setStoreState({emailLink: "http://fake.invalid/"});
sinon.assert.calledOnce(composeCallUrlEmail);
sinon.assert.calledWithExactly(composeCallUrlEmail,
"http://fake.invalid/", "test@test.tld");
"http://fake.invalid/", "test@test.tld", null, "callfailed");
});
it("should close the conversation window once the email link is received",

View File

@ -526,8 +526,10 @@ describe("loop.panel", function() {
TestUtils.Simulate.click(copyButton);
sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.CopyRoomUrl({roomUrl: roomData.roomUrl}));
sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.CopyRoomUrl({
roomUrl: roomData.roomUrl,
from: "panel"
}));
});
it("should set state.urlCopied when the click event fires", function() {

View File

@ -76,6 +76,24 @@ describe("loop.store.RoomStore", function () {
beforeEach(function() {
fakeMozLoop = {
SHARING_ROOM_URL: {
COPY_FROM_PANEL: 0,
COPY_FROM_CONVERSATION: 1,
EMAIL_FROM_PANEL: 2,
EMAIL_FROM_CONVERSATION: 3
},
ROOM_CREATE: {
CREATE_SUCCESS: 0,
CREATE_FAIL: 1
},
ROOM_DELETE: {
DELETE_SUCCESS: 0,
DELETE_FAIL: 1
},
ROOM_CONTEXT_ADD: {
ADD_FROM_PANEL: 0,
ADD_FROM_CONVERSATION: 1
},
copyString: function() {},
getLoopPref: function(pref) {
return pref;
@ -83,11 +101,13 @@ describe("loop.store.RoomStore", function () {
notifyUITour: function() {},
rooms: {
create: function() {},
delete: function() {},
getAll: function() {},
open: function() {},
rename: function() {},
on: sandbox.stub()
}
},
telemetryAddValue: sinon.stub()
};
fakeNotifications = {
set: sinon.stub(),
@ -217,14 +237,15 @@ describe("loop.store.RoomStore", function () {
var fakeNameTemplate = "Conversation {{conversationLabel}}";
var fakeLocalRoomId = "777";
var fakeOwner = "fake@invalid";
var fakeRoomCreationData = {
nameTemplate: fakeNameTemplate,
roomOwner: fakeOwner
};
var fakeRoomCreationData;
beforeEach(function() {
sandbox.stub(dispatcher, "dispatch");
store.setStoreState({pendingCreation: false, rooms: []});
fakeRoomCreationData = {
nameTemplate: fakeNameTemplate,
roomOwner: fakeOwner
};
});
it("should clear any existing room errors", function() {
@ -237,6 +258,24 @@ describe("loop.store.RoomStore", function () {
"create-room-error");
});
it("should log a telemetry event when the operation with context is successful", function() {
sandbox.stub(fakeMozLoop.rooms, "create", function(data, cb) {
cb(null, {roomToken: "fakeToken"});
});
fakeRoomCreationData.urls = [{
location: "http://invalid.com",
description: "fakeSite",
thumbnail: "fakeimage.png"
}];
store.createRoom(new sharedActions.CreateRoom(fakeRoomCreationData));
sinon.assert.calledTwice(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_CONTEXT_ADD", 0);
});
it("should request creation of a new room", function() {
sandbox.stub(fakeMozLoop.rooms, "create");
@ -314,6 +353,31 @@ describe("loop.store.RoomStore", function () {
error: err
}));
});
it("should log a telemetry event when the operation is successful", function() {
sandbox.stub(fakeMozLoop.rooms, "create", function(data, cb) {
cb(null, {roomToken: "fakeToken"});
});
store.createRoom(new sharedActions.CreateRoom(fakeRoomCreationData));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_CREATE", 0);
});
it("should log a telemetry event when the operation fails", function() {
var err = new Error("fake");
sandbox.stub(fakeMozLoop.rooms, "create", function(data, cb) {
cb(err);
});
store.createRoom(new sharedActions.CreateRoom(fakeRoomCreationData));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_CREATE", 1);
});
});
describe("#createdRoom", function() {
@ -369,17 +433,104 @@ describe("loop.store.RoomStore", function () {
});
});
describe("#deleteRoom", function() {
var fakeRoomToken = "42abc";
beforeEach(function() {
sandbox.stub(dispatcher, "dispatch");
});
it("should request deletion of a room", function() {
sandbox.stub(fakeMozLoop.rooms, "delete");
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken
}));
sinon.assert.calledWith(fakeMozLoop.rooms.delete, fakeRoomToken);
});
it("should dispatch a DeleteRoomError action if the operation fails", function() {
var err = new Error("fake");
sandbox.stub(fakeMozLoop.rooms, "delete", function(roomToken, cb) {
cb(err);
});
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken
}));
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.DeleteRoomError({
error: err
}));
});
it("should log a telemetry event when the operation is successful", function() {
sandbox.stub(fakeMozLoop.rooms, "delete", function(roomToken, cb) {
cb();
});
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken
}));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_DELETE", 0);
});
it("should log a telemetry event when the operation fails", function() {
var err = new Error("fake");
sandbox.stub(fakeMozLoop.rooms, "delete", function(roomToken, cb) {
cb(err);
});
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken
}));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_DELETE", 1);
});
});
describe("#copyRoomUrl", function() {
it("should copy the room URL", function() {
var copyString = sandbox.stub(fakeMozLoop, "copyString");
store.copyRoomUrl(new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid"
roomUrl: "http://invalid",
from: "conversation"
}));
sinon.assert.calledOnce(copyString);
sinon.assert.calledWithExactly(copyString, "http://invalid");
});
it("should send a telemetry event for copy from panel", function() {
store.copyRoomUrl(new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid",
from: "panel"
}));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_SHARING_ROOM_URL", 0);
});
it("should send a telemetry event for copy from conversation", function() {
store.copyRoomUrl(new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid",
from: "conversation"
}));
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_SHARING_ROOM_URL", 1);
});
});
describe("#emailRoomUrl", function() {
@ -387,12 +538,13 @@ describe("loop.store.RoomStore", function () {
sandbox.stub(sharedUtils, "composeCallUrlEmail");
store.emailRoomUrl(new sharedActions.EmailRoomUrl({
roomUrl: "http://invalid"
roomUrl: "http://invalid",
from: "conversation"
}));
sinon.assert.calledOnce(sharedUtils.composeCallUrlEmail);
sinon.assert.calledWith(sharedUtils.composeCallUrlEmail,
"http://invalid");
"http://invalid", null, undefined, "conversation");
});
it("should call composeUrlEmail differently with context", function() {
@ -402,12 +554,13 @@ describe("loop.store.RoomStore", function () {
var description = "Hello, is it me you're looking for?";
store.emailRoomUrl(new sharedActions.EmailRoomUrl({
roomUrl: url,
roomDescription: description
roomDescription: description,
from: "conversation"
}));
sinon.assert.calledOnce(sharedUtils.composeCallUrlEmail);
sinon.assert.calledWithExactly(sharedUtils.composeCallUrlEmail,
url, null, description);
url, null, description, "conversation");
});
});

View File

@ -29,6 +29,7 @@ describe("loop.roomViews", function () {
previews: [],
title: ""
}),
openURL: sinon.stub(),
rooms: {
get: sinon.stub().callsArgWith(1, null, {
roomToken: "fakeToken",
@ -39,7 +40,8 @@ describe("loop.roomViews", function () {
}
}),
update: sinon.stub().callsArgWith(2, null)
}
},
telemetryAddValue: sinon.stub()
};
fakeWindow = {
@ -163,7 +165,8 @@ describe("loop.roomViews", function () {
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.EmailRoomUrl({
roomUrl: "http://invalid",
roomDescription: undefined
roomDescription: undefined,
from: "conversation"
}));
});
@ -186,7 +189,8 @@ describe("loop.roomViews", function () {
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.EmailRoomUrl({
roomUrl: url,
roomDescription: description
roomDescription: description,
from: "conversation"
}));
});
@ -204,8 +208,10 @@ describe("loop.roomViews", function () {
React.addons.TestUtils.Simulate.click(copyBtn);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.CopyRoomUrl({roomUrl: "http://invalid"}));
sinon.assert.calledWith(dispatcher.dispatch, new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid",
from: "conversation"
}));
});
it("should change the text when the url has been copied", function() {
@ -932,5 +938,54 @@ describe("loop.roomViews", function () {
expect(node.querySelector(".room-context-comments").value).to.eql("");
});
});
describe("#handleContextClick", function() {
var fakeEvent;
beforeEach(function() {
fakeEvent = {
preventDefault: sinon.stub(),
stopPropagation: sinon.stub()
};
});
it("should not attempt to open a URL when none is attached", function() {
view = mountTestComponent({
roomData: {
roomToken: "fakeToken",
roomName: "fakeName"
}
});
view.handleContextClick(fakeEvent);
sinon.assert.calledOnce(fakeEvent.preventDefault);
sinon.assert.calledOnce(fakeEvent.stopPropagation);
sinon.assert.notCalled(fakeMozLoop.openURL);
sinon.assert.notCalled(fakeMozLoop.telemetryAddValue);
});
it("should open a URL", function() {
view = mountTestComponent({
roomData: {
roomToken: "fakeToken",
roomName: "fakeName",
roomContextUrls: [fakeContextURL]
}
});
view.handleContextClick(fakeEvent);
sinon.assert.calledOnce(fakeEvent.preventDefault);
sinon.assert.calledOnce(fakeEvent.stopPropagation);
sinon.assert.calledOnce(fakeMozLoop.openURL);
sinon.assert.calledWithExactly(fakeMozLoop.openURL, fakeContextURL.location);
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue,
"LOOP_ROOM_CONTEXT_CLICK", 1);
});
});
});
});

View File

@ -76,3 +76,104 @@ add_task(function* test_mozLoop_telemetryAdd_sharing_buckets() {
Assert.strictEqual(snapshot.counts[SHARING_STATES.BROWSER_ENABLED], 3, "SHARING_STATE_CHANGE.BROWSER_ENABLED");
Assert.strictEqual(snapshot.counts[SHARING_STATES.BROWSER_DISABLED], 4, "SHARING_STATE_CHANGE.BROWSER_DISABLED");
});
add_task(function* test_mozLoop_telemetryAdd_sharingURL_buckets() {
let histogramId = "LOOP_SHARING_ROOM_URL";
let histogram = Services.telemetry.getHistogramById(histogramId);
const SHARING_TYPES = gMozLoopAPI.SHARING_ROOM_URL;
histogram.clear();
for (let value of [SHARING_TYPES.COPY_FROM_PANEL,
SHARING_TYPES.COPY_FROM_CONVERSATION,
SHARING_TYPES.COPY_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION]) {
gMozLoopAPI.telemetryAddValue(histogramId, value);
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[SHARING_TYPES.COPY_FROM_PANEL], 1,
"SHARING_ROOM_URL.COPY_FROM_PANEL");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.COPY_FROM_CONVERSATION], 2,
"SHARING_ROOM_URL.COPY_FROM_CONVERSATION");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.EMAIL_FROM_CALLFAILED], 3,
"SHARING_ROOM_URL.EMAIL_FROM_CALLFAILED");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.EMAIL_FROM_CONVERSATION], 4,
"SHARING_ROOM_URL.EMAIL_FROM_CONVERSATION");
});
add_task(function* test_mozLoop_telemetryAdd_roomCreate_buckets() {
let histogramId = "LOOP_ROOM_CREATE";
let histogram = Services.telemetry.getHistogramById(histogramId);
const ACTION_TYPES = gMozLoopAPI.ROOM_CREATE;
histogram.clear();
for (let value of [ACTION_TYPES.CREATE_SUCCESS,
ACTION_TYPES.CREATE_FAIL,
ACTION_TYPES.CREATE_FAIL]) {
gMozLoopAPI.telemetryAddValue(histogramId, value);
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[ACTION_TYPES.CREATE_SUCCESS], 1,
"SHARING_ROOM_URL.CREATE_SUCCESS");
Assert.strictEqual(snapshot.counts[ACTION_TYPES.CREATE_FAIL], 2,
"SHARING_ROOM_URL.CREATE_FAIL");
});
add_task(function* test_mozLoop_telemetryAdd_roomDelete_buckets() {
let histogramId = "LOOP_ROOM_DELETE";
let histogram = Services.telemetry.getHistogramById(histogramId);
const ACTION_TYPES = gMozLoopAPI.ROOM_DELETE;
histogram.clear();
for (let value of [ACTION_TYPES.DELETE_SUCCESS,
ACTION_TYPES.DELETE_FAIL,
ACTION_TYPES.DELETE_FAIL]) {
gMozLoopAPI.telemetryAddValue(histogramId, value);
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[ACTION_TYPES.DELETE_SUCCESS], 1,
"SHARING_ROOM_URL.DELETE_SUCCESS");
Assert.strictEqual(snapshot.counts[ACTION_TYPES.DELETE_FAIL], 2,
"SHARING_ROOM_URL.DELETE_FAIL");
});
add_task(function* test_mozLoop_telemetryAdd_roomContextAdd_buckets() {
let histogramId = "LOOP_ROOM_CONTEXT_ADD";
let histogram = Services.telemetry.getHistogramById(histogramId);
const ACTION_TYPES = gMozLoopAPI.ROOM_CONTEXT_ADD;
histogram.clear();
for (let value of [ACTION_TYPES.ADD_FROM_PANEL,
ACTION_TYPES.ADD_FROM_CONVERSATION,
ACTION_TYPES.ADD_FROM_CONVERSATION]) {
gMozLoopAPI.telemetryAddValue(histogramId, value);
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[ACTION_TYPES.ADD_FROM_PANEL], 1,
"SHARING_ROOM_URL.CREATE_SUCCESS");
Assert.strictEqual(snapshot.counts[ACTION_TYPES.ADD_FROM_CONVERSATION], 2,
"SHARING_ROOM_URL.ADD_FROM_CONVERSATION");
});
add_task(function* test_mozLoop_telemetryAdd_roomContextClick() {
let histogramId = "LOOP_ROOM_CONTEXT_CLICK";
let histogram = Services.telemetry.getHistogramById(histogramId);
histogram.clear();
let snapshot;
for (let i = 1; i < 4; ++i) {
gMozLoopAPI.telemetryAddValue("LOOP_ROOM_CONTEXT_CLICK", 1);
snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[0], i);
}
});

View File

@ -39,6 +39,10 @@ describe("loop.store.ConversationStore", function () {
};
fakeMozLoop = {
ROOM_CREATE: {
CREATE_SUCCESS: 0,
CREATE_FAIL: 1
},
getLoopPref: sandbox.stub(),
addConversationContext: sandbox.stub(),
calls: {
@ -48,7 +52,8 @@ describe("loop.store.ConversationStore", function () {
},
rooms: {
create: sandbox.stub()
}
},
telemetryAddValue: sandbox.stub()
};
dispatcher = new loop.Dispatcher();
@ -1036,6 +1041,8 @@ describe("loop.store.ConversationStore", function () {
}));
expect(store.getStoreState("emailLink")).eql("http://fake.invalid/");
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue, "LOOP_ROOM_CREATE", 0);
});
it("should trigger an error:emailLink event in case of failure",
@ -1051,6 +1058,8 @@ describe("loop.store.ConversationStore", function () {
sinon.assert.calledOnce(trigger);
sinon.assert.calledWithExactly(trigger, "error:emailLink");
sinon.assert.calledOnce(fakeMozLoop.telemetryAddValue);
sinon.assert.calledWithExactly(fakeMozLoop.telemetryAddValue, "LOOP_ROOM_CREATE", 1);
});
});

View File

@ -338,7 +338,7 @@ describe("loop.shared.utils", function() {
});
describe("#composeCallUrlEmail", function() {
var composeEmail;
var composeEmail, telemetryAddValue;
beforeEach(function() {
// fake mozL10n
@ -355,9 +355,15 @@ describe("loop.shared.utils", function() {
}
});
composeEmail = sandbox.spy();
telemetryAddValue = sandbox.spy();
navigator.mozLoop = {
SHARING_ROOM_URL: {
EMAIL_FROM_CALLFAILED: 2,
EMAIL_FROM_CONVERSATION: 3
},
getLoopPref: sandbox.spy(),
composeEmail: composeEmail
composeEmail: composeEmail,
telemetryAddValue: telemetryAddValue
};
});
@ -375,6 +381,13 @@ describe("loop.shared.utils", function() {
sinon.assert.calledOnce(composeEmail);
sinon.assert.calledWith(composeEmail, "subject_context", "body_context");
});
it("should record a telemetry event when an email is composed", function() {
sharedUtils.composeCallUrlEmail("http://invalid", null,
"Hello, is me you're looking for?", "callfailed");
sinon.assert.calledOnce(telemetryAddValue, "LOOP_SHARING_ROOM_URL", 2);
});
});
describe("#btoa", function() {

View File

@ -289,6 +289,15 @@ if (typeof Mozilla == 'undefined') {
_sendEvent('toggleReaderMode');
};
Mozilla.UITour.setDefaultBrowser = function() {
_sendEvent('setDefaultBrowser');
}
Mozilla.UITour.isDefaultBrowser = function(callback) {
_sendEvent('isDefaultBrowser', {
callbackID: _waitForCallback(callback),
});
}
})();
// Make this library Require-able.

View File

@ -716,6 +716,22 @@ this.UITour = {
targetPromise.then(target => {
ReaderParent.toggleReaderMode({target: target.node});
});
break;
}
case "setDefaultBrowser": {
let shell = Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Components.interfaces.nsIShellService);
shell.setDefaultBrowser(true, false);
break;
}
case "isDefaultBrowser": {
let shell = Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Components.interfaces.nsIShellService);
let isDefault = shell.isDefaultBrowser(false);
this.sendPageCallback(messageManager, data.callbackID, { value: isDefault });
break;
}
}

View File

@ -42,3 +42,5 @@ skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
[browser_UITour_resetProfile.js]
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
[browser_UITour_defaultBrowser.js]
skip-if = e10s # Bug 1073427 - UITour.jsm not e10s friendly

View File

@ -0,0 +1,68 @@
"use strict";
let gTestTab;
let gContentAPI;
let gContentWindow;
let setDefaultBrowserCalled = false;
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://mochikit/content/tests/SimpleTest/MockObjects.js", this);
function MockShellService() {};
MockShellService.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIShellService]),
isDefaultBrowser: function(aStartupCheck, aForAllTypes) { return false; },
setDefaultBrowser: function(aClaimAllTypes, aForAllUsers) {
setDefaultBrowserCalled = true;
},
shouldCheckDefaultBrowser: false,
canSetDesktopBackground: false,
BACKGROUND_TILE : 1,
BACKGROUND_STRETCH : 2,
BACKGROUND_CENTER : 3,
BACKGROUND_FILL : 4,
BACKGROUND_FIT : 5,
setDesktopBackground: function(aElement, aPosition) {},
APPLICATION_MAIL : 0,
APPLICATION_NEWS : 1,
openApplication: function(aApplication) {},
desktopBackgroundColor: 0,
openApplicationWithURI: function(aApplication, aURI) {},
defaultFeedReader: 0,
};
let mockShellService = new MockObjectRegisterer("@mozilla.org/browser/shell-service;1",
MockShellService);
// Temporarily disabled, see note at test_setDefaultBrowser.
// mockShellService.register();
function test() {
UITourTest();
}
let tests = [
/* This test is disabled (bug 1180714) since the MockObjectRegisterer
is not actually replacing the original ShellService.
taskify(function* test_setDefaultBrowser() {
try {
gContentAPI.setDefaultBrowser();
ok(setDefaultBrowserCalled, "setDefaultBrowser called");
} finally {
mockShellService.unregister();
}
}),
*/
taskify(function* test_isDefaultBrowser(done) {
let shell = Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Components.interfaces.nsIShellService);
let isDefault = shell.isDefaultBrowser(false);
gContentAPI.isDefaultBrowser(function(data) {
is(data.value, isDefault, "gContentAPI.isDefaultBrowser should match shellService.isDefaultBrowser");
done();
});
})
];

View File

@ -1047,7 +1047,7 @@ InspectorPanel.prototype = {
if (!this.selection.isNode()) {
return;
}
this._copyLongStr(this.walker.innerHTML(this.selection.nodeFront));
this._copyLongString(this.walker.innerHTML(this.selection.nodeFront));
},
/**
@ -1057,8 +1057,21 @@ InspectorPanel.prototype = {
if (!this.selection.isNode()) {
return;
}
let node = this.selection.nodeFront;
this._copyLongStr(this.walker.outerHTML(this.selection.nodeFront));
switch (node.nodeType) {
case Ci.nsIDOMNode.ELEMENT_NODE :
this._copyLongString(this.walker.outerHTML(node));
break;
case Ci.nsIDOMNode.COMMENT_NODE :
this._getLongString(node.getNodeValue()).then(comment => {
clipboardHelper.copyString("<!--" + comment + "-->");
});
break;
case Ci.nsIDOMNode.DOCUMENT_TYPE_NODE :
clipboardHelper.copyString(node.doctypeString);
break;
}
},
/**
@ -1071,13 +1084,29 @@ InspectorPanel.prototype = {
}
},
_copyLongStr: function(promise) {
return promise.then(longstr => {
return longstr.string().then(toCopy => {
longstr.release().then(null, console.error);
clipboardHelper.copyString(toCopy);
/**
* Copy the content of a longString (via a promise resolving a LongStringActor) to the clipboard
* @param {Promise} longStringActorPromise promise expected to resolve a LongStringActor instance
* @return {Promise} promise resolving (with no argument) when the string is sent to the clipboard
*/
_copyLongString: function(longStringActorPromise) {
return this._getLongString(longStringActorPromise).then(string => {
clipboardHelper.copyString(string);
}).catch(Cu.reportError);
},
/**
* Retrieve the content of a longString (via a promise resolving a LongStringActor)
* @param {Promise} longStringActorPromise promise expected to resolve a LongStringActor instance
* @return {Promise} promise resolving with the retrieved string as argument
*/
_getLongString: function(longStringActorPromise) {
return longStringActorPromise.then(longStringActor => {
return longStringActor.string().then(string => {
longStringActor.release().catch(Cu.reportError);
return string;
});
}).then(null, console.error);
}).catch(Cu.reportError);
},
/**

View File

@ -21,6 +21,7 @@ support-files =
doc_inspector_infobar_01.html
doc_inspector_infobar_02.html
doc_inspector_menu.html
doc_inspector_outerhtml.html
doc_inspector_remove-iframe-during-load.html
doc_inspector_search.html
doc_inspector_search-reserved.html
@ -76,6 +77,7 @@ skip-if = e10s # GCLI isn't e10s compatible. See bug 1128988.
[browser_inspector_initialization.js]
[browser_inspector_inspect-object-element.js]
[browser_inspector_invalidate.js]
[browser_inspector_keyboard-shortcuts-copy-outerhtml.js]
[browser_inspector_keyboard-shortcuts.js]
[browser_inspector_menu-01-sensitivity.js]
[browser_inspector_menu-02-copy-items.js]

View File

@ -0,0 +1,58 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test copy outer HTML from the keyboard/copy event
const TEST_URL = TEST_URL_ROOT + "doc_inspector_outerhtml.html";
add_task(function *() {
let { inspector } = yield openInspectorForURL(TEST_URL);
let root = inspector.markup._elt;
info("Test copy outerHTML for COMMENT node");
let comment = getElementByType(inspector, Ci.nsIDOMNode.COMMENT_NODE);
yield setSelectionNodeFront(comment, inspector);
yield checkClipboard("<!-- Comment -->", root);
info("Test copy outerHTML for DOCTYPE node");
let doctype = getElementByType(inspector, Ci.nsIDOMNode.DOCUMENT_TYPE_NODE);
yield setSelectionNodeFront(doctype, inspector);
yield checkClipboard("<!DOCTYPE html>", root);
info("Test copy outerHTML for ELEMENT node");
yield selectAndHighlightNode("div", inspector);
yield checkClipboard("<div><p>Test copy OuterHTML</p></div>", root);
});
function* setSelectionNodeFront(node, inspector) {
let updated = inspector.once("inspector-updated");
inspector.selection.setNodeFront(node);
yield updated;
}
function* checkClipboard(expectedText, node) {
let deferred = promise.defer();
waitForClipboard(
expectedText,
() => fireCopyEvent(node),
deferred.resolve,
deferred.reject
);
try {
yield deferred.promise;
ok(true, "Clipboard successfully filled with : " + expectedText);
} catch (e) {
ok(false, "Clipboard could not be filled with the expected text : " + expectedText);
}
}
function getElementByType(inspector, type) {
for (let [node] of inspector.markup._containers) {
if (node.nodeType === type) {
return node;
}
}
}

View File

@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Inspector Copy OuterHTML Test</title>
</head>
<body>
<!-- Comment -->
<div><p>Test copy OuterHTML</p></div>
</body>
</html>

View File

@ -723,6 +723,15 @@ function wait(ms) {
return def.promise;
}
/**
* Dispatch the copy event on the given element
*/
function fireCopyEvent(element) {
let evt = element.ownerDocument.createEvent("Event");
evt.initEvent("copy", true, true);
element.dispatchEvent(evt);
}
/**
* Send an async message to the frame script (chrome -> content) and wait for a
* response message with the same name (content -> chrome).

View File

@ -6,6 +6,10 @@
-moz-control-character-visibility: visible;
}
body {
-moz-user-select: none;
}
/* Force height and width (possibly overflowing) from inline elements.
* This allows long overflows of text or input fields to still be styled with
* the container, rather than the background disappearing when scrolling */
@ -16,7 +20,6 @@
body.dragging .tag-line {
cursor: grabbing;
-moz-user-select: none;
}
#root-wrapper:after {

View File

@ -111,6 +111,9 @@ function MarkupView(aInspector, aFrame, aControllerWindow) {
this._boundKeyDown = this._onKeyDown.bind(this);
this._frame.contentWindow.addEventListener("keydown", this._boundKeyDown, false);
this._onCopy = this._onCopy.bind(this);
this._frame.contentWindow.addEventListener("copy", this._onCopy);
this._boundFocus = this._onFocus.bind(this);
this._frame.addEventListener("focus", this._boundFocus, false);
@ -507,6 +510,20 @@ MarkupView.prototype = {
return walker;
},
_onCopy: function (evt) {
// Ignore copy events from editors
if (this._isInputOrTextarea(evt.target)) {
return;
}
let selection = this._inspector.selection;
if (selection.isNode()) {
this._inspector.copyOuterHTML();
}
evt.stopPropagation();
evt.preventDefault();
},
/**
* Key handling.
*/
@ -514,8 +531,7 @@ MarkupView.prototype = {
let handled = true;
// Ignore keystrokes that originated in editors.
if (aEvent.target.tagName.toLowerCase() === "input" ||
aEvent.target.tagName.toLowerCase() === "textarea") {
if (this._isInputOrTextarea(aEvent.target)) {
return;
}
@ -614,6 +630,14 @@ MarkupView.prototype = {
}
},
/**
* Check if a node is an input or textarea
*/
_isInputOrTextarea : function (element) {
let name = element.tagName.toLowerCase();
return name === "input" || name === "textarea";
},
/**
* Delete a node from the DOM.
* This is an undoable action.
@ -1485,6 +1509,9 @@ MarkupView.prototype = {
this._boundKeyDown, false);
this._boundKeyDown = null;
this._frame.contentWindow.removeEventListener("copy", this._onCopy);
this._onCopy = null;
this._inspector.selection.off("new-node-front", this._boundOnNewSelection);
this._boundOnNewSelection = null;
@ -2314,10 +2341,7 @@ function GenericEditor(aContainer, aNode) {
this.tag.textContent = aNode.isBeforePseudoElement ? "::before" : "::after";
} else if (aNode.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE) {
this.elt.classList.add("comment");
this.tag.textContent = '<!DOCTYPE ' + aNode.name +
(aNode.publicId ? ' PUBLIC "' + aNode.publicId + '"': '') +
(aNode.systemId ? ' "' + aNode.systemId + '"' : '') +
'>';
this.tag.textContent = aNode.doctypeString;
} else {
this.tag.textContent = aNode.nodeName;
}

View File

@ -151,6 +151,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
this._onClick = this._onClick.bind(this);
this._onCopy = this._onCopy.bind(this);
this._onCopyColor = this._onCopyColor.bind(this);
this._onCopyUrl = this._onCopyUrl.bind(this);
this._onCopyImageDataUrl = this._onCopyImageDataUrl.bind(this);
this._onFilterStyles = this._onFilterStyles.bind(this);
this._onFilterKeyPress = this._onFilterKeyPress.bind(this);
@ -716,6 +717,13 @@ CssHtmlTree.prototype = {
command: this._onCopyColor
});
// Copy URL
this.menuitemCopyUrl = createMenuItem(this._contextmenu, {
label: "styleinspector.contextmenu.copyUrl",
accesskey: "styleinspector.contextmenu.copyUrl.accessKey",
command: this._onCopyUrl
});
// Copy data URI
this.menuitemCopyImageDataUrl = createMenuItem(this._contextmenu, {
label: "styleinspector.contextmenu.copyImageDataUrl",
@ -753,6 +761,7 @@ CssHtmlTree.prototype = {
this.menuitemSources.setAttribute("checked", showOrig);
this.menuitemCopyColor.hidden = !this._isColorPopup();
this.menuitemCopyUrl.hidden = !this._isImageUrlPopup();
this.menuitemCopyImageDataUrl.hidden = !this._isImageUrlPopup();
},
@ -874,6 +883,13 @@ CssHtmlTree.prototype = {
clipboardHelper.copyString(this._colorToCopy);
},
/**
* Retrieve the url for the selected image and copy it to the clipboard
*/
_onCopyUrl: function() {
clipboardHelper.copyString(this._imageUrlToCopy);
},
/**
* Retrieve the image data for the selected image url and copy it to the clipboard
*/
@ -979,6 +995,10 @@ CssHtmlTree.prototype = {
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
this.menuitemCopyColor = null;
// Destroy Copy URL menuitem
this.menuitemCopyUrl.removeEventListener("command", this._onCopyUrl);
this.menuitemCopyUrl = null;
// Destroy Copy Data URI menuitem.
this.menuitemCopyImageDataUrl.removeEventListener("command", this._onCopyImageDataUrl);
this.menuitemCopyImageDataUrl = null;
@ -1047,7 +1067,9 @@ function createMenuItem(aMenu, aAttributes)
let item = aMenu.ownerDocument.createElementNS(XUL_NS, "menuitem");
item.setAttribute("label", CssHtmlTree.l10n(aAttributes.label));
item.setAttribute("accesskey", CssHtmlTree.l10n(aAttributes.accesskey));
if (aAttributes.accesskey) {
item.setAttribute("accesskey", CssHtmlTree.l10n(aAttributes.accesskey));
}
item.addEventListener("command", aAttributes.command);
if (aAttributes.type) {

View File

@ -1158,6 +1158,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this._onSelectAll = this._onSelectAll.bind(this);
this._onCopy = this._onCopy.bind(this);
this._onCopyColor = this._onCopyColor.bind(this);
this._onCopyUrl = this._onCopyUrl.bind(this);
this._onCopyImageDataUrl = this._onCopyImageDataUrl.bind(this);
this._onCopyLocation = this._onCopyLocation.bind(this);
this._onCopyPropertyDeclaration = this._onCopyPropertyDeclaration.bind(this);
@ -1274,6 +1275,12 @@ CssRuleView.prototype = {
command: this._onCopyColor
});
this.menuitemCopyUrl = createMenuItem(this._contextmenu, {
label: "styleinspector.contextmenu.copyUrl",
accesskey: "styleinspector.contextmenu.copyUrl.accessKey",
command: this._onCopyUrl
});
this.menuitemCopyImageDataUrl = createMenuItem(this._contextmenu, {
label: "styleinspector.contextmenu.copyImageDataUrl",
accesskey: "styleinspector.contextmenu.copyImageDataUrl.accessKey",
@ -1469,6 +1476,7 @@ CssRuleView.prototype = {
this.menuitemCopy.hidden = !copy;
this.menuitemCopyColor.hidden = !this._isColorPopup();
this.menuitemCopyUrl.hidden = !this._isImageUrlPopup();
this.menuitemCopyImageDataUrl.hidden = !this._isImageUrlPopup();
this.menuitemCopyLocation.hidden = true;
@ -1713,9 +1721,16 @@ CssRuleView.prototype = {
clipboardHelper.copyString(this._colorToCopy);
},
/**
* Retrieve the url for the selected image and copy it to the clipboard
*/
_onCopyUrl: function() {
clipboardHelper.copyString(this._imageUrlToCopy);
},
/**
* Retrieve the image data for the selected image url and copy it to
* the clipboard
* the clipboard
*/
_onCopyImageDataUrl: Task.async(function*() {
let message;
@ -2012,6 +2027,11 @@ CssRuleView.prototype = {
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
this.menuitemCopyColor = null;
// Destroy Copy URL menuitem.
this.menuitemCopyUrl.removeEventListener("command",
this._onCopyUrl);
this.menuitemCopyUrl = null;
// Destroy Copy Data URI menuitem.
this.menuitemCopyImageDataUrl.removeEventListener("command",
this._onCopyImageDataUrl);

View File

@ -161,7 +161,7 @@ skip-if = e10s # bug 1040670 Cannot open inline styles in viewSourceUtils
[browser_ruleview_user-property-reset.js]
[browser_styleinspector_context-menu-copy-color_01.js]
[browser_styleinspector_context-menu-copy-color_02.js]
[browser_styleinspector_context-menu-copy-data-uri.js]
[browser_styleinspector_context-menu-copy-urls.js]
[browser_styleinspector_csslogic-content-stylesheets.js]
[browser_styleinspector_output-parser.js]
[browser_styleinspector_refresh_when_active.js]

View File

@ -1,6 +1,10 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/* Tests both Copy URL and Copy Data URL context menu items */
const PROPERTIES_URL = "chrome://global/locale/devtools/styleinspector.properties";
const TEST_DATA_URI = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=";
@ -36,20 +40,24 @@ function* startTest() {
let ruleViewData = yield openRuleView();
info("Test valid background image URL in rule view");
yield testCopyImageDataUrlToClipboard(ruleViewData, ".valid-background", TEST_DATA_URI);
yield testCopyUrlToClipboard(ruleViewData, "data-uri", ".valid-background", TEST_DATA_URI);
yield testCopyUrlToClipboard(ruleViewData, "url", ".valid-background", TEST_DATA_URI);
info("Test invalid background image URL in rue view");
yield testCopyImageDataUrlToClipboard(ruleViewData, ".invalid-background", ERROR_MESSAGE);
yield testCopyUrlToClipboard(ruleViewData, "data-uri", ".invalid-background", ERROR_MESSAGE);
yield testCopyUrlToClipboard(ruleViewData, "url", ".invalid-background", PROPERTIES_URL);
info("Opening computed view");
let computedViewData = yield openComputedView();
info("Test valid background image URL in computed view");
yield testCopyImageDataUrlToClipboard(computedViewData, ".valid-background", TEST_DATA_URI);
yield testCopyUrlToClipboard(computedViewData, "data-uri", ".valid-background", TEST_DATA_URI);
yield testCopyUrlToClipboard(computedViewData, "url", ".valid-background", TEST_DATA_URI);
info("Test invalid background image URL in computed view");
yield testCopyImageDataUrlToClipboard(computedViewData, ".invalid-background", ERROR_MESSAGE);
yield testCopyUrlToClipboard(computedViewData, "data-uri", ".invalid-background", ERROR_MESSAGE);
yield testCopyUrlToClipboard(computedViewData, "url", ".invalid-background", PROPERTIES_URL);
}
function* testCopyImageDataUrlToClipboard({view, inspector}, selector, expected) {
function* testCopyUrlToClipboard({view, inspector}, type, selector, expected) {
info("Select node in inspector panel");
yield selectNode(selector, inspector);
@ -74,8 +82,13 @@ function* testCopyImageDataUrlToClipboard({view, inspector}, selector, expected)
info("Context menu is displayed");
ok(!view.menuitemCopyImageDataUrl.hidden, "\"Copy Image Data-URL\" menu entry is displayed");
info("Click Copy Data URI and wait for clipboard");
yield waitForClipboard(() => view.menuitemCopyImageDataUrl.click(), expected);
if (type == "data-uri") {
info("Click Copy Data URI and wait for clipboard");
yield waitForClipboard(() => view.menuitemCopyImageDataUrl.click(), expected);
} else {
info("Click Copy URL and wait for clipboard");
yield waitForClipboard(() => view.menuitemCopyUrl.click(), expected);
}
info("Hide context menu");
view._contextmenu.hidePopup();

View File

@ -7,4 +7,4 @@
<!ENTITY aboutAccountsConfig.description "Sign in to sync your tabs, bookmarks, passwords &amp; more.">
<!ENTITY aboutAccountsConfig.startButton.label "Get started">
<!ENTITY aboutAccountsConfig.useOldSync.label "Using an older version of Sync?">
<!ENTITY aboutAccountsConfig.manage.label "Manage">
<!ENTITY aboutAccountsConfig.syncPreferences.label "Sync preferences">

View File

@ -6,6 +6,7 @@ profileName_format=%S %S
# Browser Specific
sourceNameIE=Internet Explorer
sourceNameEdge=Microsoft Edge
sourceNameSafari=Safari
sourceNameChrome=Google Chrome
sourceNameFirefox=Mozilla Firefox
@ -19,40 +20,47 @@ importedSafariReadingList=Reading List (From Safari)
# Note: When adding an import source for profile reset, add the string name to
# resetProfile.js if it should be listed in the reset dialog.
1_ie=Internet Options
1_edge=Settings
1_safari=Preferences
1_chrome=Preferences
1_360se=Preferences
2_ie=Cookies
2_edge=Cookies
2_safari=Cookies
2_chrome=Cookies
2_firefox=Cookies
2_360se=Cookies
4_ie=Browsing History
4_edge=Browsing History
4_safari=Browsing History
4_chrome=Browsing History
4_firefox_history_and_bookmarks=Browsing History and Bookmarks
4_360se=Browsing History
8_ie=Saved Form History
8_edge=Saved Form History
8_safari=Saved Form History
8_chrome=Saved Form History
8_firefox=Saved Form History
8_360se=Saved Form History
16_ie=Saved Passwords
16_edge=Saved Passwords
16_safari=Saved Passwords
16_chrome=Saved Passwords
16_firefox=Saved Passwords
16_360se=Saved Passwords
32_ie=Favorites
32_edge=Favorites
32_safari=Bookmarks
32_chrome=Bookmarks
32_360se=Bookmarks
64_ie=Other Data
64_edge=Other Data
64_safari=Other Data
64_chrome=Other Data
64_firefox_other=Other Data

View File

@ -3,3 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include ../../shared/controlcenter/panel.inc.css
.identity-popup-expander:-moz-focusring,
#identity-popup-more-info-button {
padding: 1px;
}
.identity-popup-expander:-moz-focusring > .button-box,
#identity-popup-more-info-button:-moz-focusring > .button-box {
outline: 1px -moz-dialogtext dotted;
}

View File

@ -2,8 +2,19 @@
* 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/. */
%include ../shared.inc
%include ../../shared/controlcenter/panel.inc.css
#identity-popup {
margin-top: 1px;
}
.identity-popup-expander:-moz-focusring,
#identity-popup-more-info-button {
padding: 2px;
}
.identity-popup-expander:-moz-focusring > .button-box,
#identity-popup-more-info-button:-moz-focusring > .button-box {
@hudButtonFocused@
}

View File

@ -21,6 +21,11 @@
max-height: 0;
}
.panel-mainview[panelid=identity-popup][viewtype=subview] > #identity-popup-mainView menulist,
.panel-mainview[panelid=identity-popup][viewtype=subview] > #identity-popup-mainView button:not([panel-multiview-anchor]) {
-moz-user-focus: ignore;
}
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
@ -133,16 +138,15 @@
}
}
.identity-popup-expander > .button-box,
.identity-popup-expander > .button-box:focus {
.identity-popup-expander > .button-box {
padding: 0;
-moz-appearance: none;
border: solid #e5e5e5;
border-width: 0 0 0 1px;
}
.identity-popup-expander[panel-multiview-anchor] > .button-box,
.identity-popup-expander[panel-multiview-anchor] > .button-box:focus {
.identity-popup-expander:-moz-focusring > .button-box,
.identity-popup-expander[panel-multiview-anchor] > .button-box {
border: 0 none;
}
@ -283,10 +287,14 @@
background: transparent;
-moz-appearance: none;
margin-top: 5px;
padding: 1.1em;
margin: 0;
}
#identity-popup-more-info-button > .button-box {
-moz-appearance: none;
padding: 1em;
}
#identity-popup-more-info-button:hover {
background-color: hsla(210,4%,10%,.07);
}
@ -296,3 +304,7 @@
background-color: hsla(210,4%,10%,.12);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
#identity-popup-more-info-button:-moz-focusring {
border-color: transparent;
}

View File

@ -18,6 +18,9 @@
%define conditionalForwardWithUrlbarWidth 30
:root {
--toolbarbutton-vertical-inner-padding: 2px;
--toolbarbutton-vertical-outer-padding: 8px;
--toolbarbutton-hover-background: hsla(210,4%,10%,.08);
--toolbarbutton-hover-bordercolor: hsla(210,4%,10%,.1);
--toolbarbutton-hover-boxshadow: none;
@ -633,7 +636,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
#nav-bar .toolbarbutton-1:not([type=menu-button]),
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
padding: 8px 2px;
padding: var(--toolbarbutton-vertical-outer-padding) 2px;
-moz-box-pack: center;
}
@ -672,7 +675,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
@conditionalForwardWithUrlbar@ > .toolbarbutton-1:-moz-any([disabled],:not([open]):not([disabled]):not(:active)) > .toolbarbutton-icon {
padding: 2px 6px;
padding: var(--toolbarbutton-vertical-inner-padding) 6px;
border: 1px solid;
border-color: transparent;
transition-property: background-color, border-color;
@ -740,7 +743,7 @@ toolbarbutton[cui-areatype="toolbar"] > :-moz-any(@nestedButtons@) > .toolbarbut
#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon,
#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-badge-container,
#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
padding: 3px 7px;
padding: calc(var(--toolbarbutton-vertical-inner-padding) + 1px) 7px;
}
/* Help SDK icons fit: */
@ -1246,6 +1249,12 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
font-size: 1.15em;
min-height: 28px;
}
:root {
/* let toolbar buttons match the location and search bar's minimum height */
--toolbarbutton-vertical-inner-padding: 4px;
--toolbarbutton-vertical-outer-padding: 5px;
}
}
#urlbar:-moz-lwtheme,
@ -1873,8 +1882,8 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
#bookmarks-menu-button[cui-areatype="toolbar"]:not(.bookmark-item):not([overflowedItem=true]) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
padding-top: 2px;
padding-bottom: 2px;
padding-top: var(--toolbarbutton-vertical-inner-padding);
padding-bottom: var(--toolbarbutton-vertical-inner-padding);
}
#BMB_bookmarksPopup[side="top"],

View File

@ -3,3 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include ../../shared/controlcenter/panel.inc.css
.identity-popup-expander:-moz-focusring,
#identity-popup-more-info-button {
padding: 1px;
}
.identity-popup-expander:-moz-focusring > .button-box,
#identity-popup-more-info-button:-moz-focusring > .button-box {
outline: 1px -moz-dialogtext dotted;
}

View File

@ -9,7 +9,7 @@ this.PHONE_NUMBER_META_DATA = {
"385": '["HR","00","0",,,"$NP$FG","\\d{6,12}","[1-7]\\d{5,8}|[89]\\d{6,11}",[["(1)(\\d{4})(\\d{3})","$1 $2 $3","1",,],["(6[09])(\\d{4})(\\d{3})","$1 $2 $3","6[09]",,],["(62)(\\d{3})(\\d{3,4})","$1 $2 $3","62",,],["([2-5]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[2-5]",,],["(9\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","9",,],["(9\\d)(\\d{4})(\\d{4})","$1 $2 $3","9",,],["(9\\d)(\\d{3,4})(\\d{3})(\\d{3})","$1 $2 $3 $4","9",,],["(\\d{2})(\\d{2})(\\d{2,3})","$1 $2 $3","6[145]|7",,],["(\\d{2})(\\d{3,4})(\\d{3})","$1 $2 $3","6[145]|7",,],["(80[01])(\\d{2})(\\d{2,3})","$1 $2 $3","8",,],["(80[01])(\\d{3,4})(\\d{3})","$1 $2 $3","8",,]]]',
"670": '["TL","00",,,,,"\\d{7,8}","[2-489]\\d{6}|7\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[2-489]",,],["(\\d{4})(\\d{4})","$1 $2","7",,]]]',
"258": '["MZ","00",,,,,"\\d{8,9}","[28]\\d{7,8}",[["([28]\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","2|8[2-7]",,],["(80\\d)(\\d{3})(\\d{3})","$1 $2 $3","80",,]]]',
"359": '["BG","00","0",,,"$NP$FG","\\d{5,9}","[23567]\\d{5,7}|[489]\\d{6,8}",[["(2)(\\d{5})","$1 $2","29",,],["(2)(\\d{3})(\\d{3,4})","$1 $2 $3","2",,],["(\\d{3})(\\d{4})","$1 $2","43[124-7]|70[1-9]",,],["(\\d{3})(\\d{3})(\\d{2})","$1 $2 $3","43[124-7]|70[1-9]",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","[78]00",,],["(\\d{2})(\\d{3})(\\d{2,3})","$1 $2 $3","[356]|4[124-7]|7[1-9]|8[1-6]|9[1-7]",,],["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","48|8[7-9]|9[08]",,]]]',
"359": '["BG","00","0",,,"$NP$FG","\\d{5,9}","[23567]\\d{5,7}|[489]\\d{6,8}",[["(2)(\\d{5})","$1 $2","29",,],["(2)(\\d{3})(\\d{3,4})","$1 $2 $3","2",,],["(\\d{3})(\\d{4})","$1 $2","43[124-7]|70[1-9]",,],["(\\d{3})(\\d{3})(\\d{2})","$1 $2 $3","43[124-7]|70[1-9]",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","[78]00",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","999",,],["(\\d{2})(\\d{3})(\\d{2,3})","$1 $2 $3","[356]|4[124-7]|7[1-9]|8[1-6]|9[1-7]",,],["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","48|8[7-9]|9[08]",,]]]',
"682": '["CK","00",,,,,"\\d{5}","[2-57]\\d{4}",[["(\\d{2})(\\d{3})","$1 $2",,,]]]',
"852": '["HK","00",,,,,"\\d{5,11}","[235-7]\\d{7}|8\\d{7,8}|9\\d{4,10}",[["(\\d{4})(\\d{4})","$1 $2","[235-7]|[89](?:0[1-9]|[1-9])",,],["(800)(\\d{3})(\\d{3})","$1 $2 $3","800",,],["(900)(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3 $4","900",,],["(900)(\\d{2,5})","$1 $2","900",,]]]',
"998": '["UZ","810","8",,,"$NP $FG","\\d{7,9}","[679]\\d{8}",[["([679]\\d)(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
@ -27,7 +27,7 @@ this.PHONE_NUMBER_META_DATA = {
"350": '["GI","00",,,,,"\\d{8}","[2568]\\d{7}",[["(\\d{3})(\\d{5})","$1 $2","2",,]]]',
"45": '["DK","00",,,,,"\\d{8}","[2-9]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"963": '["SY","00","0",,,"$NP$FG","\\d{6,9}","[1-59]\\d{7,8}",[["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","[1-5]",,],["(9\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","9",,]]]',
"226": '["BF","00",,,,,"\\d{8}","[24-7]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"226": '["BF","00",,,,,"\\d{8}","[267]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"974": '["QA","00",,,,,"\\d{7,8}","[2-8]\\d{6,7}",[["([28]\\d{2})(\\d{4})","$1 $2","[28]",,],["([3-7]\\d{3})(\\d{4})","$1 $2","[3-7]",,]]]',
"218": '["LY","00","0",,,"$NP$FG","\\d{7,9}","[25679]\\d{8}",[["([25679]\\d)(\\d{7})","$1-$2",,,]]]',
"51": '["PE","19(?:1[124]|77|90)00","0",,,"($NP$FG)","\\d{6,9}","[14-9]\\d{7,8}",[["(1)(\\d{7})","$1 $2","1",,],["([4-8]\\d)(\\d{6})","$1 $2","[4-7]|8[2-4]",,],["(\\d{3})(\\d{5})","$1 $2","80",,],["(9\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","9","$FG",]]]',
@ -41,7 +41,7 @@ this.PHONE_NUMBER_META_DATA = {
"420": '["CZ","00",,,,,"\\d{9,12}","[2-8]\\d{8}|9\\d{8,11}",[["([2-9]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[2-8]|9[015-7]",,],["(96\\d)(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4","96",,],["(9\\d)(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4","9[36]",,]]]',
"216": '["TN","00",,,,,"\\d{8}","[2-57-9]\\d{7}",[["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3",,,]]]',
"673": '["BN","00",,,,,"\\d{7}","[2-578]\\d{6}",[["([2-578]\\d{2})(\\d{4})","$1 $2",,,]]]',
"290": ['["SH","00",,,,,"\\d{4,5}","[2-79]\\d{3,4}",]','["TA","00",,,,,"\\d{4}","8\\d{3}",]'],
"290": ['["SH","00",,,,,"\\d{4,5}","[25]\\d{4}",]','["TA","00",,,,,"\\d{4}","8\\d{3}",]'],
"882": '["001",,,,,,"\\d{7,12}","[13]\\d{6,11}",[["(\\d{2})(\\d{4})(\\d{3})","$1 $2 $3","3[23]",,],["(\\d{2})(\\d{5})","$1 $2","16|342",,],["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","34[57]",,],["(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3","348",,],["(\\d{2})(\\d{2})(\\d{4})","$1 $2 $3","1",,],["(\\d{2})(\\d{3,4})(\\d{4})","$1 $2 $3","16",,],["(\\d{2})(\\d{4,5})(\\d{5})","$1 $2 $3","16",,]]]',
"267": '["BW","00",,,,,"\\d{7,8}","[2-79]\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[2-6]",,],["(7\\d)(\\d{3})(\\d{3})","$1 $2 $3","7",,],["(90)(\\d{5})","$1 $2","9",,]]]',
"94": '["LK","00","0",,,"$NP$FG","\\d{7,9}","[1-9]\\d{8}",[["(\\d{2})(\\d{1})(\\d{6})","$1 $2 $3","[1-689]",,],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","7",,]]]',
@ -52,16 +52,16 @@ this.PHONE_NUMBER_META_DATA = {
"692": '["MH","011","1",,,,"\\d{7}","[2-6]\\d{6}",[["(\\d{3})(\\d{4})","$1-$2",,,]]]',
"250": '["RW","00","0",,,,"\\d{8,9}","[027-9]\\d{7,8}",[["(2\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","2","$FG",],["([7-9]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[7-9]","$NP$FG",],["(0\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","0",,]]]',
"81": '["JP","010","0",,,"$NP$FG","\\d{8,17}","[1-9]\\d{8,9}|00(?:[36]\\d{7,14}|7\\d{5,7}|8\\d{7})",[["(\\d{3})(\\d{3})(\\d{3})","$1-$2-$3","(?:12|57|99)0",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","800",,],["(\\d{4})(\\d{4})","$1-$2","0077","$FG","NA"],["(\\d{4})(\\d{2})(\\d{3,4})","$1-$2-$3","0077","$FG","NA"],["(\\d{4})(\\d{2})(\\d{4})","$1-$2-$3","0088","$FG","NA"],["(\\d{4})(\\d{3})(\\d{3,4})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{4})(\\d{4,5})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{5})(\\d{5,6})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{6})(\\d{6,7})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{2})(\\d{4})(\\d{4})","$1-$2-$3","[2579]0|80[1-9]",,],["(\\d{4})(\\d)(\\d{4})","$1-$2-$3","1(?:26|3[79]|4[56]|5[4-68]|6[3-5])|5(?:76|97)|499|746|8(?:3[89]|63|47|51)|9(?:49|80|9[16])",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","1(?:2[3-6]|3[3-9]|4[2-6]|5[2-8]|[68][2-7]|7[2-689]|9[1-578])|2(?:2[03-689]|3[3-58]|4[0-468]|5[04-8]|6[013-8]|7[06-9]|8[02-57-9]|9[13])|4(?:2[28]|3[689]|6[035-7]|7[05689]|80|9[3-5])|5(?:3[1-36-9]|4[4578]|5[013-8]|6[1-9]|7[2-8]|8[14-7]|9[4-9])|7(?:2[15]|3[5-9]|4[02-9]|6[135-8]|7[0-4689]|9[014-9])|8(?:2[49]|3[3-8]|4[5-8]|5[2-9]|6[35-9]|7[579]|8[03-579]|9[2-8])|9(?:[23]0|4[02-46-9]|5[024-79]|6[4-9]|7[2-47-9]|8[02-7]|9[3-7])",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","1|2(?:2[37]|5[5-9]|64|78|8[39]|91)|4(?:2[2689]|64|7[347])|5(?:[2-589]|39)|60|8(?:[46-9]|3[279]|2[124589])|9(?:[235-8]|93)",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","2(?:9[14-79]|74|[34]7|[56]9)|82|993",,],["(\\d)(\\d{4})(\\d{4})","$1-$2-$3","3|4(?:2[09]|7[01])|6[1-9]",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","[2479][1-9]",,]]]',
"237": '["CM","00",,,,,"\\d{8,9}","[235-9]\\d{7,8}",[["([26])(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4 $5","[26]",,],["([2357-9]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23579]|88",,],["(800)(\\d{2})(\\d{3})","$1 $2 $3","80",,]]]',
"237": '["CM","00",,,,,"\\d{8,9}","[2368]\\d{7,8}",[["([26])(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4 $5","[26]",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23]|88",,],["(800)(\\d{2})(\\d{3})","$1 $2 $3","80",,]]]',
"351": '["PT","00",,,,,"\\d{9}","[2-46-9]\\d{8}",[["(2\\d)(\\d{3})(\\d{4})","$1 $2 $3","2[12]",,],["([2-46-9]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","2[3-9]|[346-9]",,]]]',
"246": '["IO","00",,,,,"\\d{7}","3\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
"227": '["NE","00",,,,,"\\d{8}","[0289]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[289]|09",,],["(08)(\\d{3})(\\d{3})","$1 $2 $3","08",,]]]',
"27": '["ZA","00","0",,,"$NP$FG","\\d{5,9}","[1-79]\\d{8}|8(?:[067]\\d{7}|[1-4]\\d{3,7})",[["(860)(\\d{3})(\\d{3})","$1 $2 $3","860",,],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","[1-79]|8(?:[0-47]|6[1-9])",,],["(\\d{2})(\\d{3,4})","$1 $2","8[1-4]",,],["(\\d{2})(\\d{3})(\\d{2,3})","$1 $2 $3","8[1-4]",,]]]',
"962": '["JO","00","0",,,"$NP$FG","\\d{7,9}","[235-9]\\d{7,8}",[["(\\d)(\\d{3})(\\d{4})","$1 $2 $3","[2356]|87","($NP$FG)",],["(7)(\\d{4})(\\d{4})","$1 $2 $3","7[457-9]",,],["(\\d{3})(\\d{5,6})","$1 $2","70|8[0158]|9",,]]]',
"962": '["JO","00","0",,,"$NP$FG","\\d{8,9}","[235-9]\\d{7,8}",[["(\\d)(\\d{3})(\\d{4})","$1 $2 $3","[2356]|87","($NP$FG)",],["(7)(\\d{4})(\\d{4})","$1 $2 $3","7[457-9]",,],["(\\d{3})(\\d{5,6})","$1 $2","70|8[0158]|9",,]]]',
"387": '["BA","00","0",,,"$NP$FG","\\d{6,9}","[3-9]\\d{7,8}",[["(\\d{2})(\\d{3})(\\d{3})","$1 $2-$3","[3-5]",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","6[1-356]|[7-9]",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3 $4","6[047]",,]]]',
"33": '["FR","00","0",,,"$NP$FG","\\d{9}","[1-9]\\d{8}",[["([1-79])(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4 $5","[1-79]",,],["(1\\d{2})(\\d{3})","$1 $2","11","$FG","NA"],["(8\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","8","$NP $FG",]]]',
"972": '["IL","0(?:0|1[2-9])","0",,,"$FG","\\d{4,10}","[17]\\d{6,9}|[2-589]\\d{3}(?:\\d{3,6})?|6\\d{3}",[["([2-489])(\\d{3})(\\d{4})","$1-$2-$3","[2-489]","$NP$FG",],["([57]\\d)(\\d{3})(\\d{4})","$1-$2-$3","[57]","$NP$FG",],["(1)([7-9]\\d{2})(\\d{3})(\\d{3})","$1-$2-$3-$4","1[7-9]",,],["(1255)(\\d{3})","$1-$2","125",,],["(1200)(\\d{3})(\\d{3})","$1-$2-$3","120",,],["(1212)(\\d{2})(\\d{2})","$1-$2-$3","121",,],["(1599)(\\d{6})","$1-$2","15",,],["(\\d{4})","*$1","[2-689]",,]]]',
"248": '["SC","0[0-2]",,,,,"\\d{6,7}","[24689]\\d{5,6}",[["(\\d{3})(\\d{3})","$1 $2","[89]",,],["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[246]",,]]]',
"248": '["SC","0[0-2]",,,,,"\\d{6,7}","[2468]\\d{5,6}",[["(\\d{3})(\\d{3})","$1 $2","8",,],["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[246]",,]]]',
"297": '["AW","00",,,,,"\\d{7}","[25-9]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
"421": '["SK","00","0",,,"$NP$FG","\\d{9}","[2-689]\\d{8}",[["(2)(\\d{3})(\\d{3})(\\d{2})","$1/$2 $3 $4","2",,],["([3-5]\\d)(\\d{3})(\\d{2})(\\d{2})","$1/$2 $3 $4","[3-5]",,],["([689]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[689]",,]]]',
"672": '["NF","00",,,,,"\\d{5,6}","[13]\\d{5}",[["(\\d{2})(\\d{4})","$1 $2","1",,],["(\\d)(\\d{5})","$1 $2","3",,]]]',
@ -77,7 +77,7 @@ this.PHONE_NUMBER_META_DATA = {
"257": '["BI","00",,,,,"\\d{8}","[267]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"683": '["NU","00",,,,,"\\d{4}","[1-5]\\d{3}",]',
"43": '["AT","00","0",,,"$NP$FG","\\d{3,13}","[1-9]\\d{3,12}",[["(1)(\\d{3,12})","$1 $2","1",,],["(5\\d)(\\d{3,5})","$1 $2","5[079]",,],["(5\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","5[079]",,],["(5\\d)(\\d{4})(\\d{4,7})","$1 $2 $3","5[079]",,],["(\\d{3})(\\d{3,10})","$1 $2","316|46|51|732|6(?:44|5[0-3579]|[6-9])|7(?:1|[28]0)|[89]",,],["(\\d{4})(\\d{3,9})","$1 $2","2|3(?:1[1-578]|[3-8])|4[2378]|5[2-6]|6(?:[12]|4[1-35-9]|5[468])|7(?:2[1-8]|35|4[1-8]|[5-79])",,]]]',
"247": '["AC","00",,,,,"\\d{4,6}","[2-7]\\d{3,5}",]',
"247": '["AC","00",,,,,"\\d{4,6}","[46]\\d{4}|[2-467]\\d{3}|[01589]\\d{5}",]',
"675": '["PG","00",,,,,"\\d{7,8}","[1-9]\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[13-689]|27",,],["(\\d{4})(\\d{4})","$1 $2","20|7",,]]]',
"376": '["AD","00",,,,,"\\d{6,8}","(?:[346-9]|180)\\d{5}",[["(\\d{3})(\\d{3})","$1 $2","[346-9]",,],["(180[02])(\\d{4})","$1 $2","1",,]]]',
"63": '["PH","00","0",,,,"\\d{5,13}","2\\d{5,7}|[3-9]\\d{7,9}|1800\\d{7,9}",[["(2)(\\d{3})(\\d{4})","$1 $2 $3","2","($NP$FG)",],["(2)(\\d{5})","$1 $2","2","($NP$FG)",],["(\\d{4})(\\d{4,6})","$1 $2","3(?:23|39|46)|4(?:2[3-6]|[35]9|4[26]|76)|5(?:22|44)|642|8(?:62|8[245])","($NP$FG)",],["(\\d{5})(\\d{4})","$1 $2","346|4(?:27|9[35])|883","($NP$FG)",],["([3-8]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[3-8]","($NP$FG)",],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","81|9","$NP$FG",],["(1800)(\\d{3})(\\d{4})","$1 $2 $3","1",,],["(1800)(\\d{1,2})(\\d{3})(\\d{4})","$1 $2 $3 $4","1",,]]]',
@ -85,10 +85,10 @@ this.PHONE_NUMBER_META_DATA = {
"590": ['["GP","00","0",,,"$NP$FG","\\d{9}","[56]\\d{8}",[["([56]90)(\\d{2})(\\d{4})","$1 $2-$3",,,]]]','["BL","00","0",,,,"\\d{9}","[56]\\d{8}",]','["MF","00","0",,,,"\\d{9}","[56]\\d{8}",]'],
"53": '["CU","119","0",,,"($NP$FG)","\\d{4,8}","[2-57]\\d{5,7}",[["(\\d)(\\d{6,7})","$1 $2","7",,],["(\\d{2})(\\d{4,6})","$1 $2","[2-4]",,],["(\\d)(\\d{7})","$1 $2","5","$NP$FG",]]]',
"64": '["NZ","0(?:0|161)","0",,,"$NP$FG","\\d{7,11}","6[235-9]\\d{6}|[2-57-9]\\d{7,10}",[["([34679])(\\d{3})(\\d{4})","$1-$2 $3","[346]|7[2-57-9]|9[1-9]",,],["(24099)(\\d{3})","$1 $2","240",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","21",,],["(\\d{2})(\\d{3})(\\d{3,5})","$1 $2 $3","2(?:1[1-9]|[69]|7[0-35-9])|70|86",,],["(2\\d)(\\d{3,4})(\\d{4})","$1 $2 $3","2[028]",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:10|74)|5|[89]0",,]]]',
"965": '["KW","00",,,,,"\\d{7,8}","[12569]\\d{6,7}",[["(\\d{4})(\\d{3,4})","$1 $2","[1269]",,],["(5[015]\\d)(\\d{5})","$1 $2","5",,]]]',
"965": '["KW","00",,,,,"\\d{7,8}","[12569]\\d{6,7}",[["(\\d{4})(\\d{3,4})","$1 $2","[126]|9[04-9]",,],["(\\d{3})(\\d{5})","$1 $2","5[015]|92",,]]]',
"224": '["GN","00",,,,,"\\d{8,9}","[367]\\d{7,8}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","3",,],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[67]",,]]]',
"973": '["BH","00",,,,,"\\d{8}","[136-9]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
"32": '["BE","00","0",,,"$NP$FG","\\d{8,9}","[1-9]\\d{7,8}",[["(4[6-9]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","4[6-9]",,],["([2-49])(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23]|[49][23]",,],["([15-8]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[156]|7[018]|8(?:0[1-9]|[1-79])",,],["([89]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","(?:80|9)0",,]]]',
"32": '["BE","00","0",,,"$NP$FG","\\d{8,9}","[1-9]\\d{7,8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","4[6-9]",,],["(\\d)(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23]|4[23]|9[2-4]",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[156]|7[018]|8(?:0[1-9]|[1-79])",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","(?:80|9)0",,]]]',
"249": '["SD","00","0",,,"$NP$FG","\\d{9}","[19]\\d{8}",[["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",,,]]]',
"678": '["VU","00",,,,,"\\d{5,7}","[2-57-9]\\d{4,6}",[["(\\d{3})(\\d{4})","$1 $2","[579]",,]]]',
"52": '["MX","0[09]","01","0[12]|04[45](\\d{10})","1$1","$NP $FG","\\d{7,11}","[1-9]\\d{9,10}",[["([358]\\d)(\\d{4})(\\d{4})","$1 $2 $3","33|55|81",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","[2467]|3[12457-9]|5[89]|8[02-9]|9[0-35-9]",,],["(1)([358]\\d)(\\d{4})(\\d{4})","044 $2 $3 $4","1(?:33|55|81)","$FG","$1 $2 $3 $4"],["(1)(\\d{3})(\\d{3})(\\d{4})","044 $2 $3 $4","1(?:[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9])","$FG","$1 $2 $3 $4"]]]',
@ -112,7 +112,7 @@ this.PHONE_NUMBER_META_DATA = {
"964": '["IQ","00","0",,,"$NP$FG","\\d{6,10}","[1-7]\\d{7,9}",[["(1)(\\d{3})(\\d{4})","$1 $2 $3","1",,],["([2-6]\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","[2-6]",,],["(7\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","7",,]]]',
"225": '["CI","00",,,,,"\\d{8}","[02-7]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"992": '["TJ","810","8",,,"($NP) $FG","\\d{3,9}","[3-59]\\d{8}",[["([349]\\d{2})(\\d{2})(\\d{4})","$1 $2 $3","[34]7|91[78]",,],["([459]\\d)(\\d{3})(\\d{4})","$1 $2 $3","4[48]|5|9(?:1[59]|[0235-9])",,],["(331700)(\\d)(\\d{2})","$1 $2 $3","331",,],["(\\d{4})(\\d)(\\d{4})","$1 $2 $3","3[1-5]",,]]]',
"55": '["BR","00(?:1[45]|2[135]|31|4[13])","0","(?:0|90)(?:(1[245]|2[135]|[34]1)(\\d{10,11}))?","$2",,"\\d{8,11}","[1-46-9]\\d{7,10}|5\\d{8,9}",[["(\\d{4})(\\d{4})","$1-$2","[2-9](?:[1-9]|0[1-9])","$FG","NA"],["(\\d{5})(\\d{4})","$1-$2","9(?:[1-9]|0[1-9])","$FG","NA"],["(\\d{3,5})","$1","1[125689]","$FG","NA"],["(\\d{2})(\\d{5})(\\d{4})","$1 $2-$3","(?:1[1-9]|2[12478]|9[1-9])9","($FG)",],["(\\d{2})(\\d{4})(\\d{4})","$1 $2-$3","[1-9][1-9]","($FG)",],["([34]00\\d)(\\d{4})","$1-$2","[34]00",,],["([3589]00)(\\d{2,3})(\\d{4})","$1 $2 $3","[3589]00","$NP$FG",]]]',
"55": '["BR","00(?:1[45]|2[135]|31|4[13])","0","(?:0|90)(?:(1[245]|2[135]|[34]1)(\\d{10,11}))?","$2",,"\\d{8,11}","[1-46-9]\\d{7,10}|5\\d{8,9}",[["(\\d{4})(\\d{4})","$1-$2","[2-9](?:[1-9]|0[1-9])","$FG","NA"],["(\\d{5})(\\d{4})","$1-$2","9(?:[1-9]|0[1-9])","$FG","NA"],["(\\d{3,5})","$1","1[125689]","$FG","NA"],["(\\d{2})(\\d{5})(\\d{4})","$1 $2-$3","(?:[189][1-9]|2[12478])9","($FG)",],["(\\d{2})(\\d{4})(\\d{4})","$1 $2-$3","[1-9][1-9]","($FG)",],["([34]00\\d)(\\d{4})","$1-$2","[34]00",,],["([3589]00)(\\d{2,3})(\\d{4})","$1 $2 $3","[3589]00","$NP$FG",]]]',
"674": '["NR","00",,,,,"\\d{7}","[458]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
"967": '["YE","00","0",,,"$NP$FG","\\d{6,9}","[1-7]\\d{6,8}",[["([1-7])(\\d{3})(\\d{3,4})","$1 $2 $3","[1-6]|7[24-68]",,],["(7\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","7[0137]",,]]]',
"49": '["DE","00","0",,,"$NP$FG","\\d{2,15}","[1-35-9]\\d{3,14}|4(?:[0-8]\\d{4,12}|9(?:[0-37]\\d|4(?:[1-35-8]|4\\d?)|5\\d{1,2}|6[1-8]\\d?)\\d{2,8})",[["(1\\d{2})(\\d{7,8})","$1 $2","1[67]",,],["(1\\d{3})(\\d{7})","$1 $2","15",,],["(\\d{2})(\\d{3,11})","$1 $2","3[02]|40|[68]9",,],["(\\d{3})(\\d{3,11})","$1 $2","2(?:\\d1|0[2389]|1[24]|28|34)|3(?:[3-9][15]|40)|[4-8][1-9]1|9(?:06|[1-9]1)",,],["(\\d{4})(\\d{2,11})","$1 $2","[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:[3569][02-46-9]|4[2-4679]|7[2-467]|8[2-46-8])",,],["(3\\d{4})(\\d{1,10})","$1 $2","3",,],["(800)(\\d{7,12})","$1 $2","800",,],["(177)(99)(\\d{7,8})","$1 $2 $3","177",,],["(\\d{3})(\\d)(\\d{4,10})","$1 $2 $3","(?:18|90)0|137",,],["(1\\d{2})(\\d{5,11})","$1 $2","181",,],["(18\\d{3})(\\d{6})","$1 $2","185",,],["(18\\d{2})(\\d{7})","$1 $2","18[68]",,],["(18\\d)(\\d{8})","$1 $2","18[2-579]",,],["(700)(\\d{4})(\\d{4})","$1 $2 $3","700",,],["(138)(\\d{4})","$1 $2","138",,]]]',
@ -122,7 +122,7 @@ this.PHONE_NUMBER_META_DATA = {
"856": '["LA","00","0",,,"$NP$FG","\\d{6,10}","[2-8]\\d{7,9}",[["(20)(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3 $4","20",,],["([2-8]\\d)(\\d{3})(\\d{3})","$1 $2 $3","2[13]|3[14]|[4-8]",,],["(30)(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3 $4","30",,]]]',
"354": '["IS","00",,,,,"\\d{7,9}","[4-9]\\d{6}|38\\d{7}",[["(\\d{3})(\\d{4})","$1 $2","[4-9]",,],["(3\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","3",,]]]',
"242": '["CG","00",,,,,"\\d{9}","[028]\\d{8}",[["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","[02]",,],["(\\d)(\\d{4})(\\d{4})","$1 $2 $3","8",,]]]',
"423": '["LI","00","0",,,,"\\d{7,9}","6\\d{8}|[23789]\\d{6}",[["(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3","[23]|7[3-57-9]|87",,],["(6\\d)(\\d{3})(\\d{3})","$1 $2 $3","6",,],["(6[567]\\d)(\\d{3})(\\d{3})","$1 $2 $3","6[567]",,],["(69)(7\\d{2})(\\d{4})","$1 $2 $3","697",,],["([7-9]0\\d)(\\d{2})(\\d{2})","$1 $2 $3","[7-9]0",,],["([89]0\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[89]0","$NP$FG",]]]',
"423": '["LI","00","0",,,,"\\d{7,9}","6\\d{8}|[23789]\\d{6}",[["(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3","[23789]",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","6[56]",,],["(69)(7\\d{2})(\\d{4})","$1 $2 $3","697",,]]]',
"213": '["DZ","00","0",,,"$NP$FG","\\d{8,9}","(?:[1-4]|[5-9]\\d)\\d{7}",[["([1-4]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[1-4]",,],["([5-8]\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[5-8]",,],["(9\\d)(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","9",,]]]',
"371": '["LV","00",,,,,"\\d{8}","[2689]\\d{7}",[["([2689]\\d)(\\d{3})(\\d{3})","$1 $2 $3",,,]]]',
"503": '["SV","00",,,,,"\\d{7,8}|\\d{11}","[267]\\d{7}|[89]\\d{6}(?:\\d{4})?",[["(\\d{4})(\\d{4})","$1 $2","[267]",,],["(\\d{3})(\\d{4})","$1 $2","[89]",,],["(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3","[89]",,]]]',
@ -148,7 +148,7 @@ this.PHONE_NUMBER_META_DATA = {
"971": '["AE","00","0",,,"$NP$FG","\\d{5,12}","[2-79]\\d{7,8}|800\\d{2,9}",[["([2-4679])(\\d{3})(\\d{4})","$1 $2 $3","[2-4679][2-8]",,],["(5[0256])(\\d{3})(\\d{4})","$1 $2 $3","5",,],["([479]00)(\\d)(\\d{5})","$1 $2 $3","[479]0","$FG",],["([68]00)(\\d{2,9})","$1 $2","60|8","$FG",]]]',
"30": '["GR","00",,,,,"\\d{10}","[26-9]\\d{9}",[["([27]\\d)(\\d{4})(\\d{4})","$1 $2 $3","21|7",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","2[2-9]1|[689]",,],["(2\\d{3})(\\d{6})","$1 $2","2[2-9][02-9]",,]]]',
"228": '["TG","00",,,,,"\\d{8}","[29]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"48": '["PL","00",,,,,"\\d{6,9}","[12]\\d{6,8}|[3-57-9]\\d{8}|6\\d{5,8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[124]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-79]|9[145]",,],["(\\d{2})(\\d{1})(\\d{4})","$1 $2 $3","[12]2",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","39|5[0137]|6[0469]|7[02389]|8[08]",,],["(\\d{3})(\\d{2})(\\d{2,3})","$1 $2 $3","64",,],["(\\d{3})(\\d{3})","$1 $2","64",,]]]',
"48": '["PL","00",,,,,"\\d{6,9}","[12]\\d{6,8}|[3-57-9]\\d{8}|6\\d{5,8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[14]|2[0-57-9]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-79]|9[145]",,],["(\\d{2})(\\d{1})(\\d{4})","$1 $2 $3","[12]2",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","261|39|5[0137]|6[0469]|7[02389]|8[08]",,],["(\\d{3})(\\d{2})(\\d{2,3})","$1 $2 $3","64",,],["(\\d{3})(\\d{3})","$1 $2","64",,]]]',
"886": '["TW","0(?:0[25679]|19)","0",,,"$NP$FG","\\d{8,10}","[2-689]\\d{7,8}|7\\d{7,9}",[["([2-8])(\\d{3,4})(\\d{4})","$1 $2 $3","[2-6]|[78][1-9]",,],["([89]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","80|9",,],["(70)(\\d{4})(\\d{4})","$1 $2 $3","70",,]]]',
"212": ['["MA","00","0",,,"$NP$FG","\\d{9}","[5689]\\d{8}",[["([56]\\d{2})(\\d{6})","$1-$2","5(?:2[015-7]|3[0-4])|6",,],["([58]\\d{3})(\\d{5})","$1-$2","5(?:2[2-489]|3[5-9])|892",,],["(5\\d{4})(\\d{4})","$1-$2","5(?:29|38)",,],["(8[09])(\\d{7})","$1-$2","8(?:0|9[013-9])",,]]]','["EH","00","0",,,"$NP$FG","\\d{9}","[5689]\\d{8}",]'],
"372": '["EE","00",,,,,"\\d{4,10}","1\\d{3,4}|[3-9]\\d{6,7}|800\\d{6,7}",[["([3-79]\\d{2})(\\d{4})","$1 $2","[369]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])|7[1-9]",,],["(70)(\\d{2})(\\d{4})","$1 $2 $3","70",,],["(8000)(\\d{3})(\\d{3})","$1 $2 $3","800",,],["([458]\\d{3})(\\d{3,4})","$1 $2","40|5|8(?:00|[1-5])",,]]]',
@ -156,7 +156,7 @@ this.PHONE_NUMBER_META_DATA = {
"502": '["GT","00",,,,,"\\d{8}(?:\\d{3})?","[2-7]\\d{7}|1[89]\\d{9}",[["(\\d{4})(\\d{4})","$1 $2","[2-7]",,],["(\\d{4})(\\d{3})(\\d{4})","$1 $2 $3","1",,]]]',
"82": '["KR","00(?:[124-68]|[37]\\d{2})","0","0(8[1-46-8]|85\\d{2})?",,"$NP$FG","\\d{4,10}","[1-7]\\d{3,9}|8\\d{8}",[["(\\d{2})(\\d{4})(\\d{4})","$1-$2-$3","1(?:0|1[19]|[69]9|5[458])|[57]0",,],["(\\d{2})(\\d{3,4})(\\d{4})","$1-$2-$3","1(?:[169][2-8]|[78]|5[1-4])|[68]0|[3-6][1-9][1-9]",,],["(\\d{3})(\\d)(\\d{4})","$1-$2-$3","131",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","131",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","13[2-9]",,],["(\\d{2})(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3-$4","30",,],["(\\d)(\\d{3,4})(\\d{4})","$1-$2-$3","2[1-9]",,],["(\\d)(\\d{3,4})","$1-$2","21[0-46-9]",,],["(\\d{2})(\\d{3,4})","$1-$2","[3-6][1-9]1",,],["(\\d{4})(\\d{4})","$1-$2","1(?:5[46-9]|6[04678]|8[0579])","$FG",]]]',
"253": '["DJ","00",,,,,"\\d{8}","[27]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"91": '["IN","00","0",,,"$NP$FG","\\d{6,13}","1\\d{7,12}|[2-9]\\d{9,10}",[["(\\d{5})(\\d{5})","$1 $2","7(?:0[2-9]|2[0579]|3[057-9]|4[0-389]|6[0-35-9]|[57]|8[0-79])|8(?:0[015689]|1[0-57-9]|2[2356-9]|3[0-57-9]|[45]|6[02457-9]|7[1-69]|8[0124-9]|9[02-9])|9",,],["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","11|2[02]|33|4[04]|79|80[2-46]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1(?:2[0-249]|3[0-25]|4[145]|[569][14]|7[1257]|8[1346]|[68][1-9])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[0-26-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91)",,],["(\\d{4})(\\d{3})(\\d{3})","$1 $2 $3","1(?:[23579]|[468][1-9])|[2-8]",,],["(1600)(\\d{2})(\\d{4})","$1 $2 $3","160","$FG",],["(1800)(\\d{4,5})","$1 $2","180","$FG",],["(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3","18[06]","$FG",],["(140)(\\d{3})(\\d{4})","$1 $2 $3","140","$FG",],["(\\d{4})(\\d{3})(\\d{4})(\\d{2})","$1 $2 $3 $4","18[06]","$FG",]]]',
"91": '["IN","00","0",,,"$NP$FG","\\d{6,13}","1\\d{7,12}|[2-9]\\d{9,10}",[["(\\d{5})(\\d{5})","$1 $2","7(?:0[2-9]|2[012579]|3[057-9]|4[0-389]|6[0-35-9]|[57]|8[0-79])|8(?:0[015689]|1[0-57-9]|2[2356-9]|3[0-57-9]|[45]|6[02457-9]|7[1-69]|8[0124-9]|9[02-9])|9",,],["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","11|2[02]|33|4[04]|79|80[2-46]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1(?:2[0-249]|3[0-25]|4[145]|[569][14]|7[1257]|8[1346]|[68][1-9])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[0-26-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:1[025]|[36][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91)",,],["(\\d{4})(\\d{3})(\\d{3})","$1 $2 $3","1(?:[23579]|[468][1-9])|[2-8]",,],["(1600)(\\d{2})(\\d{4})","$1 $2 $3","160","$FG",],["(1800)(\\d{4,5})","$1 $2","180","$FG",],["(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3","18[06]","$FG",],["(140)(\\d{3})(\\d{4})","$1 $2 $3","140","$FG",],["(\\d{4})(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4","18[06]","$FG",]]]',
"389": '["MK","00","0",,,"$NP$FG","\\d{8}","[2-578]\\d{7}",[["(2)(\\d{3})(\\d{4})","$1 $2 $3","2",,],["([347]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[347]",,],["([58]\\d{2})(\\d)(\\d{2})(\\d{2})","$1 $2 $3 $4","[58]",,]]]',
"1": ['["US","011","1",,,,"\\d{7}(?:\\d{3})?","[2-9]\\d{9}",[["(\\d{3})(\\d{4})","$1-$2",,,"NA"],["(\\d{3})(\\d{3})(\\d{4})","($1) $2-$3",,,"$1-$2-$3"]]]','["AI","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["AS","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["BB","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["BM","011","1",,,,"\\d{7}(?:\\d{3})?","[4589]\\d{9}",]','["BS","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["CA","011","1",,,,"\\d{7}(?:\\d{3})?","[2-9]\\d{9}|3\\d{6}",]','["DM","011","1",,,,"\\d{7}(?:\\d{3})?","[57-9]\\d{9}",]','["DO","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["GD","011","1",,,,"\\d{7}(?:\\d{3})?","[4589]\\d{9}",]','["GU","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["JM","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["KN","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["KY","011","1",,,,"\\d{7}(?:\\d{3})?","[3589]\\d{9}",]','["LC","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["MP","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["MS","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["PR","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["SX","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["TC","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["TT","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["AG","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["VC","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["VG","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["VI","011","1",,,,"\\d{7}(?:\\d{3})?","[3589]\\d{9}",]'],
"60": '["MY","00","0",,,,"\\d{6,10}","[13-9]\\d{7,9}",[["([4-79])(\\d{3})(\\d{4})","$1-$2 $3","[4-79]","$NP$FG",],["(3)(\\d{4})(\\d{4})","$1-$2 $3","3","$NP$FG",],["([18]\\d)(\\d{3})(\\d{3,4})","$1-$2 $3","1[02-46-9][1-9]|8","$NP$FG",],["(1)([36-8]00)(\\d{2})(\\d{4})","$1-$2-$3-$4","1[36-8]0",,],["(11)(\\d{4})(\\d{4})","$1-$2 $3","11","$NP$FG",],["(15[49])(\\d{3})(\\d{4})","$1-$2 $3","15","$NP$FG",]]]',
@ -184,15 +184,15 @@ this.PHONE_NUMBER_META_DATA = {
"680": '["PW","01[12]",,,,,"\\d{7}","[2-8]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
"263": '["ZW","00","0",,,"$NP$FG","\\d{3,10}","2(?:[012457-9]\\d{3,8}|6\\d{3,6})|[13-79]\\d{4,8}|8[06]\\d{8}",[["([49])(\\d{3})(\\d{2,5})","$1 $2 $3","4|9[2-9]",,],["([179]\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","[19]1|7",,],["(86\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","86[24]",,],["([2356]\\d{2})(\\d{3,5})","$1 $2","2(?:[278]|0[45]|[49]8)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:[278]|0[45]|48)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])|80",,],["([1-356]\\d)(\\d{3,5})","$1 $2","1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])",,],["([1-356]\\d)(\\d{3})(\\d{3})","$1 $2 $3","1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])",,],["([25]\\d{3})(\\d{3,5})","$1 $2","(?:25|54)8",,],["([25]\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","(?:25|54)8",,],["(8\\d{3})(\\d{6})","$1 $2","86",,]]]',
"90": '["TR","00","0",,,,"\\d{7,10}","[2-589]\\d{9}|444\\d{4}",[["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","[23]|4(?:[0-35-9]|4[0-35-9])","($NP$FG)",],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","[589]","$NP$FG",],["(444)(\\d{1})(\\d{3})","$1 $2 $3","444",,]]]',
"352": '["LU","00",,"(15(?:0[06]|1[12]|35|4[04]|55|6[26]|77|88|99)\\d)",,,"\\d{4,11}","[24-9]\\d{3,10}|3(?:[0-46-9]\\d{2,9}|5[013-9]\\d{1,8})",[["(\\d{2})(\\d{3})","$1 $2","[2-5]|7[1-9]|[89](?:[1-9]|0[2-9])",,],["(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3","[2-5]|7[1-9]|[89](?:[1-9]|0[2-9])",,],["(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","20",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{1,2})","$1 $2 $3 $4","2(?:[0367]|4[3-8])",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3 $4","20",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{1,2})","$1 $2 $3 $4 $5","2(?:[0367]|4[3-8])",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{1,4})","$1 $2 $3 $4","2(?:[12589]|4[12])|[3-5]|7[1-9]|[89](?:[1-9]|0[2-9])",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","[89]0[01]|70",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","6",,]]]',
"352": '["LU","00",,"(15(?:0[06]|1[12]|35|4[04]|55|6[26]|77|88|99)\\d)",,,"\\d{4,11}","[24-9]\\d{3,10}|3(?:[0-46-9]\\d{2,9}|5[013-9]\\d{1,8})",[["(\\d{2})(\\d{3})","$1 $2","[2-5]|7[1-9]|[89](?:[1-9]|0[2-9])",,],["(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3","[2-5]|7[1-9]|[89](?:[1-9]|0[2-9])",,],["(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","20",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{1,2})","$1 $2 $3 $4","2(?:[0367]|4[3-8])",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3 $4","20",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{1,2})","$1 $2 $3 $4 $5","2(?:[0367]|4[3-8])",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{1,4})","$1 $2 $3 $4","2(?:[12589]|4[12])|[3-5]|7[1-9]|8(?:[1-9]|0[2-9])|9(?:[1-9]|0[2-46-9])",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","70|80[01]|90[015]",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","6",,]]]',
"47": ['["NO","00",,,,,"\\d{5}(?:\\d{3})?","0\\d{4}|[2-9]\\d{7}",[["([489]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","[489]",,],["([235-7]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[235-7]",,]]]','["SJ","00",,,,,"\\d{5}(?:\\d{3})?","0\\d{4}|[4789]\\d{7}",]'],
"243": '["CD","00","0",,,"$NP$FG","\\d{7,9}","[2-6]\\d{6}|[18]\\d{6,8}|9\\d{8}",[["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","12",,],["([89]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","8[0-2459]|9",,],["(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","88",,],["(\\d{2})(\\d{5})","$1 $2","[1-6]",,]]]',
"220": '["GM","00",,,,,"\\d{7}","[2-9]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
"687": '["NC","00",,,,,"\\d{6}","[2-57-9]\\d{5}",[["(\\d{2})(\\d{2})(\\d{2})","$1.$2.$3","[2-46-9]|5[0-4]",,]]]',
"995": '["GE","00","0",,,,"\\d{6,9}","[34578]\\d{8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[348]","$NP$FG",],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","7","$NP$FG",],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","5","$FG",]]]',
"961": '["LB","00","0",,,,"\\d{7,8}","[13-9]\\d{6,7}",[["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[13-6]|7(?:[2-579]|62|8[0-7])|[89][2-9]","$NP$FG",],["([7-9]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[89][01]|7(?:[019]|6[013-9]|8[89])",,]]]',
"961": '["LB","00","0",,,,"\\d{7,8}","[13-9]\\d{6,7}",[["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[13-6]|7(?:[2-57]|62|8[0-7]|9[04-9])|8[02-9]|9","$NP$FG",],["([7-9]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[89][01]|7(?:[01]|6[013-9]|8[89]|9[1-3])",,]]]',
"40": '["RO","00","0",,,"$NP$FG","\\d{6,9}","2\\d{5,8}|[37-9]\\d{8}",[["([237]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[23]1",,],["(21)(\\d{4})","$1 $2","21",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","[23][3-7]|[7-9]",,],["(2\\d{2})(\\d{3})","$1 $2","2[3-6]",,]]]',
"232": '["SL","00","0",,,"($NP$FG)","\\d{6,8}","[2-578]\\d{7}",[["(\\d{2})(\\d{6})","$1 $2",,,]]]',
"232": '["SL","00","0",,,"($NP$FG)","\\d{6,8}","[2-57-9]\\d{7}",[["(\\d{2})(\\d{6})","$1 $2",,,]]]',
"594": '["GF","00","0",,,"$NP$FG","\\d{9}","[56]\\d{8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
"976": '["MN","001","0",,,"$NP$FG","\\d{6,10}","[12]\\d{7,9}|[57-9]\\d{7}",[["([12]\\d)(\\d{2})(\\d{4})","$1 $2 $3","[12]1",,],["([12]2\\d)(\\d{5,6})","$1 $2","[12]2[1-3]",,],["([12]\\d{3})(\\d{5})","$1 $2","[12](?:27|[3-5])",,],["(\\d{4})(\\d{4})","$1 $2","[57-9]","$FG",],["([12]\\d{4})(\\d{4,5})","$1 $2","[12](?:27|[3-5])",,]]]',
"20": '["EG","00","0",,,"$NP$FG","\\d{5,10}","1\\d{4,9}|[2456]\\d{8}|3\\d{7}|[89]\\d{8,9}",[["(\\d)(\\d{7,8})","$1 $2","[23]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1[012]|[89]00",,],["(\\d{2})(\\d{6,7})","$1 $2","1[35]|[4-6]|[89][2-9]",,]]]',
@ -210,7 +210,7 @@ this.PHONE_NUMBER_META_DATA = {
"211": '["SS","00","0",,,,"\\d{9}","[19]\\d{8}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3",,"$NP$FG",]]]',
"373": '["MD","00","0",,,"$NP$FG","\\d{8}","[235-9]\\d{7}",[["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","22|3",,],["([25-7]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","2[13-79]|[5-7]",,],["([89]\\d{2})(\\d{5})","$1 $2","[89]",,]]]',
"996": '["KG","00","0",,,"$NP$FG","\\d{5,10}","[235-8]\\d{8,9}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","[25-7]|31[25]",,],["(\\d{4})(\\d{5})","$1 $2","3(?:1[36]|[2-9])",,],["(\\d{3})(\\d{3})(\\d)(\\d{3})","$1 $2 $3 $4","8",,]]]',
"93": '["AF","00","0",,,"$NP$FG","\\d{7,9}","[2-7]\\d{8}",[["([2-7]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[2-6]|7[013-9]",,],["(729)(\\d{3})(\\d{3})","$1 $2 $3","729",,]]]',
"93": '["AF","00","0",,,"$NP$FG","\\d{7,9}","[2-7]\\d{8}",[["([2-7]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[2-7]",,]]]',
"260": '["ZM","00","0",,,"$NP$FG","\\d{9}","[289]\\d{8}",[["([29]\\d)(\\d{7})","$1 $2","[29]",,],["(800)(\\d{3})(\\d{3})","$1 $2 $3","8",,]]]',
"378": '["SM","00",,"(?:0549)?([89]\\d{5})","0549$1",,"\\d{6,10}","[05-7]\\d{7,9}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[5-7]",,],["(0549)(\\d{6})","$1 $2","0",,"($1) $2"],["(\\d{6})","0549 $1","[89]",,"(0549) $1"]]]',
"235": '["TD","00|16",,,,,"\\d{8}","[2679]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',

View File

@ -1,105 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import org.mozilla.gecko.R;
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
import org.mozilla.gecko.home.PanelLayout.DatasetBacked;
import org.mozilla.gecko.home.PanelLayout.FilterManager;
import org.mozilla.gecko.home.PanelLayout.OnItemOpenListener;
import org.mozilla.gecko.home.PanelLayout.PanelView;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
public class PanelGridView extends GridView
implements DatasetBacked, PanelView {
private static final String LOGTAG = "GeckoPanelGridView";
private final ViewConfig viewConfig;
private final PanelViewAdapter adapter;
private final PanelViewItemHandler itemHandler;
private OnItemOpenListener itemOpenListener;
private HomeContextMenuInfo mContextMenuInfo;
private HomeContextMenuInfo.Factory mContextMenuInfoFactory;
public PanelGridView(Context context, ViewConfig viewConfig) {
super(context, null, (viewConfig.getItemType() == HomeConfig.ItemType.ICON) ?
R.attr.panelIconGridViewStyle : R.attr.panelGridViewStyle);
this.viewConfig = viewConfig;
itemHandler = new PanelViewItemHandler(viewConfig);
adapter = new PanelViewAdapter(context, viewConfig);
setAdapter(adapter);
setOnItemClickListener(new PanelGridItemClickListener());
setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
if (cursor == null || mContextMenuInfoFactory == null) {
mContextMenuInfo = null;
return false;
}
mContextMenuInfo = mContextMenuInfoFactory.makeInfoForCursor(view, position, id, cursor);
return showContextMenuForChild(PanelGridView.this);
}
});
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
itemHandler.setOnItemOpenListener(itemOpenListener);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
itemHandler.setOnItemOpenListener(null);
}
@Override
public void setDataset(Cursor cursor) {
Log.d(LOGTAG, "Setting dataset: " + viewConfig.getDatasetId());
adapter.swapCursor(cursor);
}
@Override
public void setOnItemOpenListener(OnItemOpenListener listener) {
itemHandler.setOnItemOpenListener(listener);
itemOpenListener = listener;
}
@Override
public void setFilterManager(FilterManager filterManager) {
adapter.setFilterManager(filterManager);
itemHandler.setFilterManager(filterManager);
}
private class PanelGridItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
itemHandler.openItemAtPosition(adapter.getCursor(), position);
}
}
@Override
public HomeContextMenuInfo getContextMenuInfo() {
return mContextMenuInfo;
}
@Override
public void setContextMenuInfoFactory(HomeContextMenuInfo.Factory factory) {
mContextMenuInfoFactory = factory;
}
}

View File

@ -370,7 +370,7 @@ abstract class PanelLayout extends FrameLayout {
break;
case GRID:
view = new PanelGridView(getContext(), viewConfig);
view = new PanelRecyclerView(getContext(), viewConfig);
break;
default:

View File

@ -36,7 +36,7 @@ public class PanelListView extends HomeListView
super(context);
this.viewConfig = viewConfig;
itemHandler = new PanelViewItemHandler(viewConfig);
itemHandler = new PanelViewItemHandler();
adapter = new PanelViewAdapter(context, viewConfig);
setAdapter(adapter);

View File

@ -0,0 +1,133 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import org.mozilla.gecko.R;
import org.mozilla.gecko.home.PanelLayout.DatasetBacked;
import org.mozilla.gecko.home.PanelLayout.PanelView;
import org.mozilla.gecko.home.RecyclerViewItemClickListener.OnClickListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* RecyclerView implementation for grid home panels.
*/
@SuppressLint("ViewConstructor") // View is only created from code
public class PanelRecyclerView extends RecyclerView implements DatasetBacked, PanelView, OnClickListener {
private final PanelRecyclerViewAdapter adapter;
private final GridLayoutManager layoutManager;
private final PanelViewItemHandler itemHandler;
private final float columnWidth;
private final boolean autoFit;
private PanelLayout.OnItemOpenListener itemOpenListener;
private HomeContextMenuInfo contextMenuInfo;
private HomeContextMenuInfo.Factory contextMenuInfoFactory;
public PanelRecyclerView(Context context, HomeConfig.ViewConfig viewConfig) {
super(context);
final Resources resources = context.getResources();
int spanCount;
if (viewConfig.getItemType() == HomeConfig.ItemType.ICON) {
autoFit = false;
spanCount = getResources().getInteger(R.integer.panel_icon_grid_view_columns);
} else {
autoFit = true;
spanCount = 1;
}
columnWidth = resources.getDimension(R.dimen.panel_grid_view_column_width);
layoutManager = new GridLayoutManager(context, spanCount);
adapter = new PanelRecyclerViewAdapter(context, viewConfig);
itemHandler = new PanelViewItemHandler();
setLayoutManager(layoutManager);
setAdapter(adapter);
int horizontalSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_horizontal_spacing);
int verticalSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_vertical_spacing);
int outerSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_outer_spacing);
addItemDecoration(new SpacingDecoration(horizontalSpacing, verticalSpacing));
setPadding(outerSpacing, outerSpacing, outerSpacing, outerSpacing);
setClipToPadding(false);
addOnItemTouchListener(new RecyclerViewItemClickListener(context, this, this));
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (autoFit) {
// Adjust span based on space available (What GridView does when you say numColumns="auto_fit")
final int spanCount = (int) Math.max(1, getMeasuredWidth() / columnWidth);
layoutManager.setSpanCount(spanCount);
}
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
itemHandler.setOnItemOpenListener(itemOpenListener);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
itemHandler.setOnItemOpenListener(null);
}
@Override
public void setDataset(Cursor cursor) {
adapter.swapCursor(cursor);
}
@Override
public void setFilterManager(PanelLayout.FilterManager manager) {
adapter.setFilterManager(manager);
itemHandler.setFilterManager(manager);
}
@Override
public void setOnItemOpenListener(PanelLayout.OnItemOpenListener listener) {
itemOpenListener = listener;
itemHandler.setOnItemOpenListener(listener);
}
@Override
public HomeContextMenuInfo getContextMenuInfo() {
return contextMenuInfo;
}
@Override
public void setContextMenuInfoFactory(HomeContextMenuInfo.Factory factory) {
contextMenuInfoFactory = factory;
}
@Override
public void onClick(View view, int position) {
itemHandler.openItemAtPosition(adapter.getCursor(), position);
}
@Override
public void onLongClick(View view, int position) {
Cursor cursor = adapter.getCursor();
cursor.moveToPosition(position);
contextMenuInfo = contextMenuInfoFactory.makeInfoForCursor(view, position, -1, cursor);
showContextMenuForChild(PanelRecyclerView.this);
}
}

View File

@ -0,0 +1,118 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import org.mozilla.gecko.R;
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class PanelRecyclerViewAdapter extends RecyclerView.Adapter<PanelRecyclerViewAdapter.PanelViewHolder> {
private static final int VIEW_TYPE_ITEM = 0;
private static final int VIEW_TYPE_BACK = 1;
public static class PanelViewHolder extends RecyclerView.ViewHolder {
public static PanelViewHolder create(View itemView) {
// Wrap in a FrameLayout that will handle the highlight on touch
FrameLayout frameLayout = (FrameLayout) LayoutInflater.from(itemView.getContext())
.inflate(R.layout.panel_item_container, null);
frameLayout.addView(itemView, 0, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return new PanelViewHolder(frameLayout);
}
private PanelViewHolder(View itemView) {
super(itemView);
}
}
private final Context context;
private final HomeConfig.ViewConfig viewConfig;
private PanelLayout.FilterManager filterManager;
private Cursor cursor;
public PanelRecyclerViewAdapter(Context context, HomeConfig.ViewConfig viewConfig) {
this.context = context;
this.viewConfig = viewConfig;
}
public void setFilterManager(PanelLayout.FilterManager filterManager) {
this.filterManager = filterManager;
}
private boolean isShowingBack() {
return filterManager != null && filterManager.canGoBack();
}
public void swapCursor(Cursor cursor) {
this.cursor = cursor;
notifyDataSetChanged();
}
public Cursor getCursor() {
return cursor;
}
@Override
public int getItemViewType(int position) {
if (isShowingBack() && position == 0) {
return VIEW_TYPE_BACK;
} else {
return VIEW_TYPE_ITEM;
}
}
@Override
public PanelViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case VIEW_TYPE_BACK:
return PanelViewHolder.create(new PanelBackItemView(context, viewConfig.getBackImageUrl()));
case VIEW_TYPE_ITEM:
return PanelViewHolder.create(PanelItemView.create(context, viewConfig.getItemType()));
default:
throw new IllegalArgumentException("Unknown view type: " + viewType);
}
}
@Override
public void onBindViewHolder(PanelViewHolder panelViewHolder, int position) {
final View view = ((FrameLayout) panelViewHolder.itemView).getChildAt(0);
if (isShowingBack()) {
if (position == 0) {
final PanelBackItemView item = (PanelBackItemView) view;
item.updateFromFilter(filterManager.getPreviousFilter());
return;
}
position--;
}
cursor.moveToPosition(position);
final PanelItemView panelItemView = (PanelItemView) view;
panelItemView.updateFromCursor(cursor);
}
@Override
public int getItemCount() {
if (cursor == null) {
return 0;
}
return cursor.getCount() + (isShowingBack() ? 1 : 0);
}
}

View File

@ -16,14 +16,9 @@ import android.database.Cursor;
import java.util.EnumSet;
class PanelViewItemHandler {
private final ViewConfig mViewConfig;
private OnItemOpenListener mItemOpenListener;
private FilterManager mFilterManager;
public PanelViewItemHandler(ViewConfig viewConfig) {
mViewConfig = viewConfig;
}
public void setOnItemOpenListener(OnItemOpenListener listener) {
mItemOpenListener = listener;
}

View File

@ -0,0 +1,87 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
/**
* RecyclerView.OnItemTouchListener implementation that will notify an OnClickListener about clicks and long clicks
* on items displayed by the RecyclerView.
*/
public class RecyclerViewItemClickListener implements RecyclerView.OnItemTouchListener,
GestureDetector.OnGestureListener {
public interface OnClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
private final OnClickListener clickListener;
private final GestureDetector gestureDetector;
private final RecyclerView recyclerView;
public RecyclerViewItemClickListener(Context context, RecyclerView recyclerView, OnClickListener clickListener) {
this.clickListener = clickListener;
this.gestureDetector = new GestureDetector(context, this);
this.recyclerView = recyclerView;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onSingleTapUp(MotionEvent event) {
View childView = recyclerView.findChildViewUnder(event.getX(), event.getY());
if (childView != null) {
final int position = recyclerView.getChildAdapterPosition(childView);
clickListener.onClick(childView, position);
}
return true;
}
@Override
public void onLongPress(MotionEvent event) {
View childView = recyclerView.findChildViewUnder(event.getX(), event.getY());
if (childView != null) {
final int position = recyclerView.getChildAdapterPosition(childView);
childView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
clickListener.onLongClick(childView, position);
}
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {}
@Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean b) {}
}

View File

@ -0,0 +1,20 @@
package org.mozilla.gecko.home;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class SpacingDecoration extends RecyclerView.ItemDecoration {
private final int horizontalSpacing;
private final int verticalSpacing;
public SpacingDecoration(int horizontalSpacing, int verticalSpacing) {
this.horizontalSpacing = horizontalSpacing;
this.verticalSpacing = verticalSpacing;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(horizontalSpacing, verticalSpacing, horizontalSpacing, verticalSpacing);
}
}

View File

@ -326,11 +326,12 @@ gbjar.sources += [
'home/PanelAuthCache.java',
'home/PanelAuthLayout.java',
'home/PanelBackItemView.java',
'home/PanelGridView.java',
'home/PanelInfoManager.java',
'home/PanelItemView.java',
'home/PanelLayout.java',
'home/PanelListView.java',
'home/PanelRecyclerView.java',
'home/PanelRecyclerViewAdapter.java',
'home/PanelRefreshLayout.java',
'home/PanelViewAdapter.java',
'home/PanelViewItemHandler.java',
@ -338,6 +339,7 @@ gbjar.sources += [
'home/ReadingListPanel.java',
'home/ReadingListRow.java',
'home/RecentTabsPanel.java',
'home/RecyclerViewItemClickListener.java',
'home/RemoteTabsBaseFragment.java',
'home/RemoteTabsExpandableListFragment.java',
'home/RemoteTabsExpandableListState.java',
@ -349,6 +351,7 @@ gbjar.sources += [
'home/SearchEngineRow.java',
'home/SearchLoader.java',
'home/SimpleCursorLoader.java',
'home/SpacingDecoration.java',
'home/TabMenuStrip.java',
'home/TabMenuStripLayout.java',
'home/TopSitesGridItemView.java',

View File

@ -0,0 +1,12 @@
<!-- 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/. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@color/highlight" />
<item android:drawable="@android:color/transparent"/>
</selector>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/recyclerview_selector"
android:clickable="true"
android:importantForAccessibility="no" />
</FrameLayout>

View File

@ -38,8 +38,6 @@
<attr name="topSitesGridItemViewStyle" format="reference" />
<!-- Styles for dynamic panel grid views -->
<attr name="panelGridViewStyle" format="reference" />
<attr name="panelIconGridViewStyle" format="reference" />
<attr name="panelIconViewStyle" format="reference" />
<!-- Style for the TabsGridLayout -->

View File

@ -159,8 +159,11 @@
<dimen name="icongrid_columnwidth">128dp</dimen>
<dimen name="icongrid_padding">16dp</dimen>
<!-- PanelGridView dimensions -->
<!-- PanelRecyclerView dimensions -->
<dimen name="panel_grid_view_column_width">150dp</dimen>
<dimen name="panel_grid_view_horizontal_spacing">3dp</dimen>
<dimen name="panel_grid_view_vertical_spacing">3dp</dimen>
<dimen name="panel_grid_view_outer_spacing">3dp</dimen>
<!-- PanelItemView dimensions -->
<dimen name="panel_article_item_height">95dp</dimen>

View File

@ -179,29 +179,6 @@
<item name="android:orientation">vertical</item>
</style>
<style name="Widget.PanelGridView" parent="Widget.GridView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:paddingTop">0dp</item>
<item name="android:stretchMode">columnWidth</item>
<item name="android:numColumns">auto_fit</item>
<item name="android:columnWidth">@dimen/panel_grid_view_column_width</item>
<item name="android:horizontalSpacing">2dp</item>
<item name="android:verticalSpacing">2dp</item>
<item name="android:drawSelectorOnTop">true</item>
</style>
<style name="Widget.PanelIconGridView" parent="Widget.GridView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:numColumns">@integer/panel_icon_grid_view_columns</item>
<item name="android:horizontalSpacing">6dp</item>
<item name="android:verticalSpacing">6dp</item>
<item name="android:drawSelectorOnTop">true</item>
<item name="android:padding">6dp</item>
<item name="android:clipToPadding">false</item>
</style>
<style name="Widget.TabsGridLayout" parent="Widget.GridView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>

View File

@ -94,8 +94,6 @@
<item name="menuItemActionBarStyle">@style/Widget.MenuItemActionBar</item>
<item name="menuItemActionModeStyle">@style/GeckoActionBar.Button</item>
<item name="menuItemShareActionButtonStyle">@style/Widget.MenuItemSecondaryActionBar</item>
<item name="panelGridViewStyle">@style/Widget.PanelGridView</item>
<item name="panelIconGridViewStyle">@style/Widget.PanelIconGridView</item>
<item name="topSitesGridItemViewStyle">@style/Widget.TopSitesGridItemView</item>
<item name="topSitesGridViewStyle">@style/Widget.TopSitesGridView</item>
<item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>

View File

@ -38,7 +38,7 @@
<dependency>
<groupId>com.squareup.spoon</groupId>
<artifactId>spoon-runner</artifactId>
<version>1.1.10-SNAPSHOT</version>
<version>1.1.10</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -7616,6 +7616,45 @@
"releaseChannelCollection": "opt-out",
"description": "Number of times the sharing feature has been enabled and disabled (0=WINDOW_ENABLED, 1=WINDOW_DISABLED, 2=BROWSER_ENABLED, 3=BROWSER_DISABLED)"
},
"LOOP_SHARING_ROOM_URL": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "44",
"kind": "enumerated",
"n_values": 8,
"releaseChannelCollection": "opt-out",
"description": "Number of times a room URL is shared (0=COPY_FROM_PANEL, 1=COPY_FROM_CONVERSATION, 2=EMAIL_FROM_CALLFAILED, 3=EMAIL_FROM_CONVERSATION)"
},
"LOOP_ROOM_CREATE": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "44",
"kind": "enumerated",
"n_values": 4,
"releaseChannelCollection": "opt-out",
"description": "Number of times a room create action is performed (0=CREATE_SUCCESS, 1=CREATE_FAIL)"
},
"LOOP_ROOM_DELETE": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "44",
"kind": "enumerated",
"n_values": 4,
"releaseChannelCollection": "opt-out",
"description": "Number of times a room delete action is performed (0=DELETE_SUCCESS, 2=DELETE_FAIL)"
},
"LOOP_ROOM_CONTEXT_ADD": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "44",
"kind": "enumerated",
"n_values": 8,
"releaseChannelCollection": "opt-out",
"description": "Number of times a room context action is performed (0=ADD_FROM_PANEL, 1=ADD_FROM_CONVERSATION)"
},
"LOOP_ROOM_CONTEXT_CLICK": {
"alert_emails": ["firefox-dev@mozilla.org", "mdeboer@mozilla.com"],
"expires_in_version": "44",
"kind": "count",
"releaseChannelCollection": "opt-out",
"description": "Number times room context is clicked to visit the attached URL"
},
"E10S_AUTOSTART": {
"expires_in_version": "never",
"kind": "boolean",

View File

@ -849,6 +849,12 @@ let NodeFront = protocol.FrontClass(NodeActor, {
get nodeName() {
return this._form.nodeName;
},
get doctypeString() {
return '<!DOCTYPE ' + this._form.name +
(this._form.publicId ? ' PUBLIC "' + this._form.publicId + '"': '') +
(this._form.systemId ? ' "' + this._form.systemId + '"' : '') +
'>';
},
get baseURI() {
return this._form.baseURI;
@ -2399,11 +2405,11 @@ var WalkerActor = protocol.ActorClass({
* @param {NodeActor} node The node.
*/
outerHTML: method(function(node) {
let html = "";
let outerHTML = "";
if (!isNodeDead(node)) {
html = node.rawNode.outerHTML;
outerHTML = node.rawNode.outerHTML;
}
return LongStringActor(this.conn, html);
return LongStringActor(this.conn, outerHTML);
}, {
request: {
node: Arg(0, "domnode")

View File

@ -96,6 +96,15 @@ ruleView.contextmenu.copyColor=Copy Color
# the rule and computed view context menu "Copy Color" entry.
ruleView.contextmenu.copyColor.accessKey=L
# LOCALIZATION NOTE (styleinspector.contextmenu.copyUrl): In rule and computed view :
# text displayed in the context menu for an image URL.
# Clicking it copies the URL to the clipboard of the user.
styleinspector.contextmenu.copyUrl=Copy URL
# LOCALIZATION NOTE (styleinspector.contextmenu.copyUrl.accessKey): Access key for
# the rule and computed view context menu "Copy URL" entry.
styleinspector.contextmenu.copyUrl.accessKey=U
# LOCALIZATION NOTE (styleinspector.contextmenu.copyImageDataUrl): In rule and computed view :
# text displayed in the context menu for an image URL.
# Clicking it copies the image as Data-URL to the clipboard of the user.
@ -103,7 +112,7 @@ styleinspector.contextmenu.copyImageDataUrl=Copy Image Data-URL
# LOCALIZATION NOTE (styleinspector.contextmenu.copyDataUri.accessKey): Access key for
# the rule and computed view context menu "Copy Image Data-URL" entry.
styleinspector.contextmenu.copyImageDataUrl.accessKey=U
styleinspector.contextmenu.copyImageDataUrl.accessKey=I
# LOCALIZATION NOTE (styleinspector.copyDataUriError): Text set in the clipboard
# if an error occurs when using the copyImageDataUrl context menu action