From b52b5db415f15169ab6b0f6d3cd644d455888ce4 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Mon, 22 Dec 2014 15:42:04 -0500 Subject: [PATCH 01/15] Bug 1078796 - Remove special purpose Matchstick filtering code r=wesj --- mobile/android/chrome/content/CastingApps.js | 3 +-- toolkit/modules/secondscreen/SimpleServiceDiscovery.jsm | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/mobile/android/chrome/content/CastingApps.js b/mobile/android/chrome/content/CastingApps.js index 5e2bd3bdd37f..15055ba249f6 100644 --- a/mobile/android/chrome/content/CastingApps.js +++ b/mobile/android/chrome/content/CastingApps.js @@ -25,8 +25,7 @@ var matchstickDevice = { id: "matchstick:dial", target: "urn:dial-multiscreen-org:service:dial:1", filters: { - server: null, - modelName: "Eureka Dongle" + manufacturer: "openflint" }, factory: function(aService) { Cu.import("resource://gre/modules/MatchstickApp.jsm"); diff --git a/toolkit/modules/secondscreen/SimpleServiceDiscovery.jsm b/toolkit/modules/secondscreen/SimpleServiceDiscovery.jsm index 32e0bad2cc57..f1a600774684 100644 --- a/toolkit/modules/secondscreen/SimpleServiceDiscovery.jsm +++ b/toolkit/modules/secondscreen/SimpleServiceDiscovery.jsm @@ -87,19 +87,12 @@ var SimpleServiceDiscovery = { service.location = row.substr(10).trim(); } else if (name.startsWith("ST")) { service.target = row.substr(4).trim(); - } else if (name.startsWith("SERVER")) { - service.server = row.substr(8).trim(); } }.bind(this)); if (service.location && service.target) { service.location = this._forceTrailingSlash(service.location); - // We add the server as an additional way to filter services - if (!("server" in service)) { - service.server = null; - } - // When we find a valid response, package up the service information // and pass it on. try { From e77dbbc3e59fed8232a7b9f95d5bb20c9d7d5d83 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Mon, 22 Dec 2014 15:42:11 -0500 Subject: [PATCH 02/15] Bug 1078796 - Update the Matchstick casting code r=wesj --- mobile/android/chrome/content/CastingApps.js | 4 + mobile/android/modules/MatchstickApp.jsm | 628 ++++++++++--------- 2 files changed, 346 insertions(+), 286 deletions(-) diff --git a/mobile/android/chrome/content/CastingApps.js b/mobile/android/chrome/content/CastingApps.js index 15055ba249f6..8f0336e6ff80 100644 --- a/mobile/android/chrome/content/CastingApps.js +++ b/mobile/android/chrome/content/CastingApps.js @@ -648,6 +648,10 @@ var CastingApps = { }, _shutdown: function() { + if (!this.session) { + return; + } + this.session.app.stop(); let video = this.session.videoRef.get(); if (video) { diff --git a/mobile/android/modules/MatchstickApp.jsm b/mobile/android/modules/MatchstickApp.jsm index 86af905d0124..13073a17744d 100644 --- a/mobile/android/modules/MatchstickApp.jsm +++ b/mobile/android/modules/MatchstickApp.jsm @@ -7,307 +7,363 @@ this.EXPORTED_SYMBOLS = ["MatchstickApp"]; -const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/Services.jsm"); -// meta constants -const HEADER_META = ".meta"; -const PROTO_CMD_KEY = "cmd"; -const PROTO_CMD_VALUE_CREATE_SESSION = "create-session"; -const PROTO_CMD_VALUE_END_SESSION = "end-session"; -const PROTO_CMD_VALUE_ATTACH_APP = "attach-app"; -const PROTO_CMD_VALUE_SET_WIFI = "set-wifi"; -const PROTO_CMD_RESPONSE_PREFIX = "~"; -const PROTO_CMD_VALUE_START_APP = "start-app"; -const PROTO_CMD_VALUE_CANCEL_START_APP = "cancel-start-app"; -const PROTO_CMD_VALUE_DOWNLODING_APP = "downloading-app"; -const PROTO_CMD_VALUE_ATTACH_APP_MANAGER = "attach-app-manager"; -const PROTO_CMD_VALUE_EXCEPTION = "exception"; -const PROTO_EXCEPTION_KEY = "exception"; -const PROTO_EXCEPTION_NO_KEY = "errno"; -const PROTO_STATUS_VALUE_APP_CLOSED = "app-closed"; -const PROTO_STATUS_VALUE_TRY_LATER = "try-later"; -const PROTO_STATUS_VALUE_CANCELLED = "cancelled"; -const PROTO_STATUS_VALUE_REFUSED = "refused"; -const PROTO_STATUS_VALUE_TIMEOUT = "time-out"; -const PROTO_STATUS_VALUE_INVALID_APP = "app_not_exist"; -const PROTO_STATUS_VALUE_APP_CHECK_FAIL = "app_check_fail"; -const PROTO_STATUS_VALUE_APP_INSTALL_FAIL = "app_install_fail"; -const PROTO_STATUS_VALUE_APP_DOWNLOAD_FAIL = "app_download_fail"; -const PROTO_STATUS_VALUE_APP_LAUNCH_FAIL = "app_launch_fail"; -const PROTO_STATUS_KEY = "status"; -const PROTO_STATUS_VALUE_OK = "OK"; -const PROTO_STATUS_VALUE_FAILED = "FAILED_REASON"; -const PROTO_EXCEPTION_NO_APP_NAME_NULL = 10; -const PROTO_EXCEPTION_NO_MESSAGE_NULL = 11; -const PROTO_EXCEPTION_NO_NEW_GROUP_START = 12; -const PROTO_EXCEPTION_NO_UNKNOW_CMD = 13; -const PROTO_EXCEPTION_NO_JSON_DATA_ERROR = 14; -const PARAM_APP_NAME = "app-name"; -const PROTO_HOME_APP = "home"; -const PARAM_DOWNLOADING_PERCENT = "download-percent"; -const PARAM_KEEP_SESSION = "keep-session"; -const PROTO_SENDER_HOST_NAME_KEY = "sender-host-name"; -const PROTO_SENDER_PORT_KEY = "sender-port"; -const PROTO_APP_META_KEY = "app-meta"; -const PROTO_APP_META_NAME = "name"; -const PROTO_APP_META_TITLE = "title"; -const PROTO_APP_META_IMG_URI = "img-uri"; -const PROTO_MIME_DATA_KEY = "mime-data"; -const PROTO_APP_NAME_KEY = "app-name"; -const PARAM_WIFI_NAME = "wifi-name"; -const PARAM_WIFI_PASSWORD = "wifi-password"; -const PARAM_WIFI_TYPE = "wifi-type"; -const PARAM_WIFI_KEY = "key"; -const PROTO_MIME_DATA_KEY_TYPE = "type"; -const PROTO_MIME_DATA_KEY_DATA = "data"; +function log(msg) { + Services.console.logStringMessage(msg); +} -// RAMP constants -const RAMP_CMD_KEY_ID = "cmd_id"; -const RAMP_CMD_KEY_TYPE = "type"; -const RAMP_CMD_KEY_STATUS = "status"; -const RAMP_CMD_KEY_URL = "url"; -const RAMP_CMD_KEY_VALUE = "value"; -const RAMP_CMD_KEY_VIDEO_NAME = "videoname"; -const RAMP_CMD_KEY_EVENT_SEQ = "event_sequence"; -const NAMESPACE_RAMP = "ramp"; -const RAMP_CMD_ID_START = 0; -const RAMP_CMD_ID_INFO = 1; -const RAMP_CMD_ID_PLAY = 2; -const RAMP_CMD_ID_PAUSE = 3; -const RAMP_CMD_ID_STOP = 4; -const RAMP_CMD_ID_SEEKTO = 5; -const RAMP_CMD_ID_SETVOLUME = 6; -const RAMP_CMD_ID_MUTE = 7; -const RAMP_CMD_ID_DECONSTE = 8; -const RAMP_CMD_START = "START"; -const RAMP_CMD_INFO = "INFO"; -const RAMP_CMD_PLAY = "PLAY"; -const RAMP_CMD_PAUSE = "PAUSE"; -const RAMP_CMD_STOP = "STOP"; -const RAMP_CMD_SEEKTO = "SEEKTO"; -const RAMP_CMD_SETVOLUME = "SETVOLUME"; -const RAMP_CMD_MUTE = "MUTE"; -const RAMP_CMD_DECONSTE = "DECONSTE"; -const RAMP_CAST_STATUS_EVENT_SEQUENCE = "event_sequence"; -const RAMP_CAST_STATUS_STATE = "state"; -const RAMP_CAST_STATUS_CONTENT_ID = "content_id"; -const RAMP_CAST_STATUS_CURRENT_TIME = "current_time"; -const RAMP_CAST_STATUS_DURATION = "duration"; -const RAMP_CAST_STATUS_MUTED = "muted"; -const RAMP_CAST_STATUS_TIME_PROGRESS = "time_progress"; -const RAMP_CAST_STATUS_TITLE = "title"; -const RAMP_CAST_STATUS_VOLUME = "volume"; -const PLAYER_STATUS_PREPARING = 1; -const PLAYER_STATUS_PLAYING = 2; -const PLAYER_STATUS_PAUSE = 3; -const PLAYER_STATUS_STOP = 4; -const PLAYER_STATUS_IDLE = 5; -const PLAYER_STATUS_BUFFERING = 6; +const MATCHSTICK_PLAYER_URL = "http://openflint.github.io/flint-player/player.html"; -function MatchstickApp(service) { - let uri = Services.io.newURI(service.location, null, null); - this._ip = uri.host; -}; +const STATUS_RETRY_COUNT = 5; // Number of times we retry a partial status +const STATUS_RETRY_WAIT = 1000; // Delay between attempts in milliseconds + +/* MatchstickApp is a wrapper for interacting with a DIAL server. + * The basic interactions all use a REST API. + * See: https://github.com/openflint/openflint.github.io/wiki/Flint%20Protocol%20Docs + */ +function MatchstickApp(aServer) { + this.server = aServer; + this.app = "~flintplayer"; + this.resourceURL = this.server.appsURL + this.app; + this.token = null; + this.statusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + this.statusRetry = 0; +} MatchstickApp.prototype = { - _ip: null, - _port: 8888, - _cmd_socket: null, - _meta_callback: null, - _ramp_callbacks: {}, - _mediaListener: null, - _event_sequence: 0, - status: "unloaded", - _have_session: false, - _info_timer: null, + status: function status(aCallback) { + // Query the server to see if an application is already running + let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); + xhr.open("GET", this.resourceURL, true); + xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; + xhr.setRequestHeader("Accept", "application/xml; charset=utf8"); + xhr.setRequestHeader("Authorization", this.token); - _send_meta_cmd: function(cmd, callback, extras) { - this._meta_callback = callback; - let msg = extras ? extras : {}; - msg.cmd = cmd; - this._send_cmd(JSON.stringify([HEADER_META, msg]), 0); + xhr.addEventListener("load", (function() { + if (xhr.status == 200) { + let doc = xhr.responseXML; + let state = doc.querySelector("state").textContent; + + // The serviceURL can be missing if the player is not completely loaded + let serviceURL = null; + let serviceNode = doc.querySelector("channelBaseUrl"); + if (serviceNode) { + serviceURL = serviceNode.textContent + "/senders/" + this.token; + } + + if (aCallback) + aCallback({ state: state, serviceURL: serviceURL }); + } else { + if (aCallback) + aCallback({ state: "error" }); + } + }).bind(this), false); + + xhr.addEventListener("error", (function() { + if (aCallback) + aCallback({ state: "error" }); + }).bind(this), false); + + xhr.send(null); }, - _send_ramp_cmd: function(type, cmd_id, callback, extras) { - let msg = extras ? extras : {}; - msg.cmd_id = cmd_id; - msg.type = type; - msg.event_sequence = this._event_sequence++; - this._send_cmd(JSON.stringify([NAMESPACE_RAMP, msg]), 0); + start: function start(aCallback) { + // Start a given app with any extra query data. Each app uses it's own data scheme. + let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); + xhr.open("POST", this.resourceURL, true); + xhr.overrideMimeType("text/xml"); + xhr.setRequestHeader("Content-Type", "application/json"); + + xhr.addEventListener("load", (function() { + if (xhr.status == 200 || xhr.status == 201) { + this.statusRetry = 0; + + let response = JSON.parse(xhr.responseText); + this.token = response.token; + this.pingInterval = response.interval; + + if (aCallback) + aCallback(true); + } else { + if (aCallback) + aCallback(false); + } + }).bind(this), false); + + xhr.addEventListener("error", (function() { + if (aCallback) + aCallback(false); + }).bind(this), false); + + let data = { + type: "launch", + app_info: { + url: MATCHSTICK_PLAYER_URL, + useIpc: true, + maxInactive: -1 + } + }; + + xhr.send(JSON.stringify(data)); }, - _send_cmd: function(str, recursionDepth) { - if (!this._cmd_socket) { - let baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket); - this._cmd_socket = baseSocket.open(this._ip, 8888, { useSecureTransport: false, binaryType: "string" }); - if (!(this._cmd_socket)) { - dump("socket is null"); + stop: function stop(aCallback) { + // Send command to kill an app, if it's already running. + let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); + xhr.open("DELETE", this.resourceURL + "/run", true); + xhr.overrideMimeType("text/plain"); + xhr.setRequestHeader("Accept", "application/xml; charset=utf8"); + xhr.setRequestHeader("Authorization", this.token); + + xhr.addEventListener("load", (function() { + if (xhr.status == 200) { + if (aCallback) + aCallback(true); + } else { + if (aCallback) + aCallback(false); + } + }).bind(this), false); + + xhr.addEventListener("error", (function() { + if (aCallback) + aCallback(false); + }).bind(this), false); + + xhr.send(null); + }, + + remoteMedia: function remoteMedia(aCallback, aListener) { + this.status((aStatus) => { + if (aStatus.serviceURL) { + if (aCallback) { + aCallback(new RemoteMedia(aStatus.serviceURL, aListener, this)); + } return; } - this._cmd_socket.ondata = function(response) { - try { - let data = JSON.parse(response.data); - let res = data[1]; - switch (data[0]) { - case ".meta": - this._handle_meta_response(data[1]); - return; - case "ramp": - this._handle_ramp_response(data[1]); - return; - default: - dump("unknown response"); - } - } catch(ex) { - dump("error handling response: " + ex); - if (!this._info_timer) { - this._info_timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._info_timer.init(this, 200, Ci.nsITimer.TYPE_ONE_SHOT); - } + // It can take a few moments for the player app to load. Let's use a small delay + // and retry a few times. + if (this.statusRetry < STATUS_RETRY_COUNT) { + this.statusRetry++; + this.statusTimer.initWithCallback(() => { + this.remoteMedia(aCallback, aListener); + }, STATUS_RETRY_WAIT, Ci.nsITimer.TYPE_ONE_SHOT); + } else { + // Fail + if (aCallback) { + aCallback(); } - }.bind(this); - - this._cmd_socket.onerror = function(err) { - this.shutdown(); - Cu.reportError("error: " + err.data.name); - this._cmd_socket = null; - }.bind(this); - - this._cmd_socket.onclose = function() { - this.shutdown(); - this._cmd_socket = null; - Cu.reportError("closed tcp socket") - }.bind(this); - - this._cmd_socket.onopen = function() { - if (recursionDepth <= 2) { - this._send_cmd(str, ++recursionDepth); - } - }.bind(this); - } else { - try { - this._cmd_socket.send(str, str.length); - let data = JSON.parse(str); - if (data[1][PARAM_APP_NAME] == PROTO_HOME_APP) { - // assuming we got home OK - if (this._meta_callback) { - this._handle_meta_callback({ status: "OK" }); - } - } - } catch (ex) { - this._cmd_socket = null; - this._send_cmd(str); } - } - }, - - observe: function(subject, data, topic) { - if (data === "timer-callback") { - this._info_timer = null; - this._send_ramp_cmd(RAMP_CMD_INFO, RAMP_CMD_ID_INFO, null) - } - }, - - start: function(func) { - let cmd = this._have_session ? PROTO_CMD_VALUE_START_APP : PROTO_CMD_VALUE_CREATE_SESSION ; - this._send_meta_cmd(cmd, func, { "app-name": "Remote Player" }); - }, - - stop: function(func) { - if (func) { - func(true); - } - }, - - remoteMedia: function(func, listener) { - this._mediaListener = listener; - func(this); - if (listener) { - listener.onRemoteMediaStart(this); - } - }, - - _handle_meta_response: function(data) { - switch (data.cmd) { - case "create-session": - case "~create-session": - // if we get a response form start-app, assume we have a connection already - case "start-app": - case "~start-app": - this._have_session = (data.status == "OK"); - break; - case "end-session": - case "~end-session": - this._have_session = (data.status != "OK"); - break; - } - - if (this._meta_callback) { - let callback = this._meta_callback; - this._meta_callback = null; - callback(data.status == "OK"); - } - }, - - _handle_ramp_response: function(data) { - switch (data.status.state) { - case PLAYER_STATUS_PREPARING: - this.status = "preparing"; - break; - case PLAYER_STATUS_PLAYING: - this.status = "started"; - break; - case PLAYER_STATUS_PAUSE: - this.status = "paused"; - break; - case PLAYER_STATUS_STOP: - this.status = "stopped"; - break; - case PLAYER_STATUS_IDLE: - this.status = "idle"; - break; - case PLAYER_STATUS_BUFFERING: - this.status = "buffering"; - break; - } - - if (data.status.state == PLAYER_STATUS_STOP && data.status.current_time > 0 && data.status.current_time == data.status.duration) { - this.status = "completed"; - } else if (!this._info_timer) { - this._info_timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._info_timer.init(this, 200, Ci.nsITimer.TYPE_ONE_SHOT); - } - - if (this._mediaListener) { - this._mediaListener.onRemoteMediaStatus(this); - } - }, - - load: function(data) { - let meta = { - url: data.source, - videoname: data.title - }; - this._send_ramp_cmd(RAMP_CMD_START, RAMP_CMD_ID_START, null, meta); - }, - - play: function() { - this._send_ramp_cmd(RAMP_CMD_PLAY, RAMP_CMD_ID_PLAY, null); - }, - - pause: function() { - this._send_ramp_cmd(RAMP_CMD_PAUSE, RAMP_CMD_ID_PAUSE, null); - }, - - shutdown: function() { - this.stop(function() { - this._send_meta_cmd(PROTO_CMD_VALUE_END_SESSION); - if (this._mediaListener) { - this._mediaListener.onRemoteMediaStop(this); - } - }.bind(this)); + }); } -}; +} + +/* RemoteMedia provides a wrapper for using WebSockets and Flint protocol to control + * the Matchstick media player + * See: https://github.com/openflint/openflint.github.io/wiki/Flint%20Protocol%20Docs + * See: https://github.com/openflint/flint-receiver-sdk/blob/gh-pages/v1/libs/mediaplayer.js + */ +function RemoteMedia(aURL, aListener, aApp) { + this._active = false; + this._status = "uninitialized"; + + this.app = aApp; + this.listener = aListener; + + this.pingTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + + let uri = Services.io.newURI(aURL, null, null); + this.ws = Cc["@mozilla.org/network/protocol;1?name=ws"].createInstance(Ci.nsIWebSocketChannel); + this.ws.asyncOpen(uri, aURL, this, null); +} + +// Used to give us a small gap between not pinging too often and pinging too late +const PING_INTERVAL_BACKOFF = 200; + +RemoteMedia.prototype = { + _ping: function _ping() { + if (this.app.pingInterval == -1) { + return; + } + + let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); + xhr.open("GET", this.app.resourceURL, true); + xhr.setRequestHeader("Accept", "application/xml; charset=utf8"); + xhr.setRequestHeader("Authorization", this.app.token); + + xhr.addEventListener("load", () => { + if (xhr.status == 200) { + this.pingTimer.initWithCallback(() => { + this._ping(); + }, this.app.pingInterval - PING_INTERVAL_BACKOFF, Ci.nsITimer.TYPE_ONE_SHOT); + } + }); + + xhr.send(null); + }, + + _changeStatus: function _changeStatus(status) { + if (this._status != status) { + this._status = status; + if ("onRemoteMediaStatus" in this.listener) { + this.listener.onRemoteMediaStatus(this); + } + } + }, + + _teardown: function _teardown() { + if (!this._active) { + return; + } + + // Stop any queued ping event + this.pingTimer.cancel(); + + // Let the listener know we are finished + this._active = false; + if (this.listener && "onRemoteMediaStop" in this.listener) { + this.listener.onRemoteMediaStop(this); + } + }, + + _sendMsg: function _sendMsg(params) { + // Convert payload to a string + params.payload = JSON.stringify(params.payload); + + try { + this.ws.sendMsg(JSON.stringify(params)); + } catch (e if e.result == Cr.NS_ERROR_NOT_CONNECTED) { + // This shouldn't happen unless something gets out of sync with the + // connection. Let's make sure we try to cleanup. + this._teardown(); + } catch (e) { + log("Send Error: " + e) + } + }, + + get active() { + return this._active; + }, + + get status() { + return this._status; + }, + + shutdown: function shutdown() { + this.ws.close(Ci.nsIWebSocketChannel.CLOSE_NORMAL, "shutdown"); + }, + + play: function play() { + if (!this._active) { + return; + } + + let params = { + namespace: "urn:flint:org.openflint.fling.media", + payload: { + type: "PLAY", + requestId: "requestId-5", + } + }; + + this._sendMsg(params); + }, + + pause: function pause() { + if (!this._active) { + return; + } + + let params = { + namespace: "urn:flint:org.openflint.fling.media", + payload: { + type: "PAUSE", + requestId: "requestId-4", + } + }; + + this._sendMsg(params); + }, + + load: function load(aData) { + if (!this._active) { + return; + } + + let params = { + namespace: "urn:flint:org.openflint.fling.media", + payload: { + type: "LOAD", + requestId: "requestId-2", + media: { + contentId: aData.source, + contentType: "video/mp4", + metadata: { + title: "", + subtitle: "" + } + } + } + }; + + this._sendMsg(params); + }, + + onStart: function(aContext) { + this._active = true; + if (this.listener && "onRemoteMediaStart" in this.listener) { + this.listener.onRemoteMediaStart(this); + } + + this._ping(); + }, + + onStop: function(aContext, aStatusCode) { + // This will be called for internal socket failures and timeouts. Make + // sure we cleanup. + this._teardown(); + }, + + onAcknowledge: function(aContext, aSize) {}, + onBinaryMessageAvailable: function(aContext, aMessage) {}, + + onMessageAvailable: function(aContext, aMessage) { + let msg = JSON.parse(aMessage); + if (!msg) { + return; + } + + let payload = JSON.parse(msg.payload); + if (!payload) { + return; + } + + // Handle state changes using the player notifications + if (payload.type == "MEDIA_STATUS") { + let status = payload.status[0]; + let state = status.playerState.toLowerCase(); + if (state == "playing") { + this._changeStatus("started"); + } else if (state == "paused") { + this._changeStatus("paused"); + } else if (state == "idle" && "idleReason" in status) { + // Make sure we are really finished. IDLE can be sent at other times. + let reason = status.idleReason.toLowerCase(); + if (reason == "finished") { + this._changeStatus("completed"); + } + } + } + }, + + onServerClose: function(aContext, aStatusCode, aReason) { + // This will be fired from _teardown when we close the websocket, but it + // can also be called for other internal socket failures and timeouts. We + // make sure the _teardown bails on reentry. + this._teardown(); + } +} From 12ed8ba73865ee3724dafc1cddb10de6a0b65403 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Mon, 22 Dec 2014 14:13:26 -0800 Subject: [PATCH 03/15] Bug 1075797 - Move new tablet resources into regular resources. r=lucasr,rnewman,mcomella The move command was: $ cd mobile/android/base/newtablet/res $ find . -type f -exec hg mv {} ../../resources/{} \; --HG-- rename : mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_item_title.xml => mobile/android/base/resources/color-large-v11/new_tablet_tab_item_title.xml rename : mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_bg.xml => mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_bg.xml rename : mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_title.xml => mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_title.xml rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_default_favicon.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_default_favicon.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_menu.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_menu.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_nav_back.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_nav_back.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close_active.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close_active.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count.png rename : mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png => mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_default_favicon.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_default_favicon.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_menu.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_menu.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_nav_back.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_nav_back.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close_active.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close_active.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count.png rename : mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png => mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_action_bar_button.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_action_bar_button.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_level.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_level.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_unknown.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_unknown.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_item_close_button.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_tab_item_close_button.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_add_tab.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_add_tab.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_button.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_button.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_divider.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_divider.xml rename : mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_url_bar_nav_button.xml => mobile/android/base/resources/drawable-large-v11/new_tablet_url_bar_nav_button.xml rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_default_favicon.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_default_favicon.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_menu.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_menu.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_nav_back.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_nav_back.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count.png rename : mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png => mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_menu.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_menu.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_nav_back.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_nav_back.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png rename : mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png => mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png rename : mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png => mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png rename : mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png => mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename : mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png => mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png rename : mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png => mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename : mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png => mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png rename : mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png => mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename : mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png => mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png rename : mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png => mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename : mobile/android/base/newtablet/res/layout-large-v11/new_tablet_browser_toolbar.xml => mobile/android/base/resources/layout-large-v11/new_tablet_browser_toolbar.xml rename : mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tab_strip.xml => mobile/android/base/resources/layout-large-v11/new_tablet_tab_strip.xml rename : mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_counter.xml => mobile/android/base/resources/layout-large-v11/new_tablet_tabs_counter.xml rename : mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_panel_back_button.xml => mobile/android/base/resources/layout-large-v11/new_tablet_tabs_panel_back_button.xml rename : mobile/android/base/newtablet/res/layout-large-v11/tab_strip.xml => mobile/android/base/resources/layout-large-v11/tab_strip.xml rename : mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item.xml => mobile/android/base/resources/layout-large-v11/tab_strip_item.xml rename : mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item_view.xml => mobile/android/base/resources/layout-large-v11/tab_strip_item_view.xml extra : amend_source : 604733b38aa0e8d9f8b5334dfa99af9f1201a2ee --- mobile/android/base/build.gradle | 1 - mobile/android/base/moz.build | 1 - .../color-large-v11/new_tablet_tab_item_title.xml | 0 .../new_tablet_tab_strip_item_bg.xml | 0 .../new_tablet_tab_strip_item_title.xml | 0 .../new_tablet_default_favicon.png | Bin .../new_tablet_ic_menu_back.png | Bin .../new_tablet_ic_menu_forward.png | Bin .../new_tablet_ic_menu_reload.png | Bin .../drawable-large-hdpi-v11/new_tablet_menu.png | Bin .../drawable-large-hdpi-v11/new_tablet_nav_back.png | Bin .../new_tablet_tab_close.png | Bin .../new_tablet_tab_close_active.png | Bin .../new_tablet_tab_new_dark.png | Bin .../new_tablet_tabs_count.png | Bin .../new_tablet_tabs_count_foreground.png | Bin .../new_tablet_default_favicon.png | Bin .../new_tablet_ic_menu_back.png | Bin .../new_tablet_ic_menu_forward.png | Bin .../new_tablet_ic_menu_reload.png | Bin .../drawable-large-mdpi-v11/new_tablet_menu.png | Bin .../drawable-large-mdpi-v11/new_tablet_nav_back.png | Bin .../new_tablet_tab_close.png | Bin .../new_tablet_tab_close_active.png | Bin .../new_tablet_tab_new_dark.png | Bin .../new_tablet_tabs_count.png | Bin .../new_tablet_tabs_count_foreground.png | Bin .../new_tablet_action_bar_button.xml | 0 .../new_tablet_site_security_level.xml | 0 .../new_tablet_site_security_unknown.xml | 0 .../new_tablet_tab_item_close_button.xml | 0 .../new_tablet_tab_strip_add_tab.xml | 0 .../new_tablet_tab_strip_button.xml | 0 .../new_tablet_tab_strip_divider.xml | 0 .../new_tablet_url_bar_nav_button.xml | 0 .../new_tablet_default_favicon.png | Bin .../new_tablet_ic_menu_back.png | Bin .../new_tablet_ic_menu_forward.png | Bin .../new_tablet_ic_menu_reload.png | Bin .../drawable-large-xhdpi-v11/new_tablet_menu.png | Bin .../new_tablet_nav_back.png | Bin .../new_tablet_tab_close.png | Bin .../new_tablet_tab_close_active.png | Bin .../new_tablet_tab_new_dark.png | Bin .../new_tablet_tabs_count.png | Bin .../new_tablet_tabs_count_foreground.png | Bin .../new_tablet_default_favicon.png | Bin .../new_tablet_ic_menu_back.png | Bin .../new_tablet_ic_menu_forward.png | Bin .../new_tablet_ic_menu_reload.png | Bin .../drawable-large-xxhdpi-v11/new_tablet_menu.png | Bin .../new_tablet_nav_back.png | Bin .../new_tablet_tab_close.png | Bin .../new_tablet_tab_close_active.png | Bin .../new_tablet_tabs_count.png | Bin .../new_tablet_tabs_count_foreground.png | Bin .../new_tablet_ic_menu_bookmark_add.png | Bin .../new_tablet_ic_menu_bookmark_remove.png | Bin .../new_tablet_ic_menu_bookmark_add.png | Bin .../new_tablet_ic_menu_bookmark_remove.png | Bin .../new_tablet_ic_menu_bookmark_add.png | Bin .../new_tablet_ic_menu_bookmark_remove.png | Bin .../new_tablet_ic_menu_bookmark_add.png | Bin .../new_tablet_ic_menu_bookmark_remove.png | Bin .../layout-large-v11/new_tablet_browser_toolbar.xml | 0 .../layout-large-v11/new_tablet_tab_strip.xml | 0 .../layout-large-v11/new_tablet_tabs_counter.xml | 0 .../new_tablet_tabs_panel_back_button.xml | 0 .../layout-large-v11/tab_strip.xml | 0 .../layout-large-v11/tab_strip_item.xml | 0 .../layout-large-v11/tab_strip_item_view.xml | 0 71 files changed, 2 deletions(-) rename mobile/android/base/{newtablet/res => resources}/color-large-v11/new_tablet_tab_item_title.xml (100%) rename mobile/android/base/{newtablet/res => resources}/color-large-v11/new_tablet_tab_strip_item_bg.xml (100%) rename mobile/android/base/{newtablet/res => resources}/color-large-v11/new_tablet_tab_strip_item_title.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_default_favicon.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_menu.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_nav_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_tab_close.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_tab_close_active.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_tabs_count.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_default_favicon.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_menu.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_nav_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_tab_close.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_tab_close_active.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_tabs_count.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_action_bar_button.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_site_security_level.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_site_security_unknown.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_tab_item_close_button.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_tab_strip_add_tab.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_tab_strip_button.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_tab_strip_divider.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-v11/new_tablet_url_bar_nav_button.xml (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_default_favicon.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_menu.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_nav_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_tab_close.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_tabs_count.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_menu.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_nav_back.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_tab_close.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png (100%) rename mobile/android/base/{newtablet/res => resources}/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/new_tablet_browser_toolbar.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/new_tablet_tab_strip.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/new_tablet_tabs_counter.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/new_tablet_tabs_panel_back_button.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/tab_strip.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/tab_strip_item.xml (100%) rename mobile/android/base/{newtablet/res => resources}/layout-large-v11/tab_strip_item_view.xml (100%) diff --git a/mobile/android/base/build.gradle b/mobile/android/base/build.gradle index 055526d244fa..8737f995b15b 100644 --- a/mobile/android/base/build.gradle +++ b/mobile/android/base/build.gradle @@ -52,7 +52,6 @@ android { } res { - srcDir "newtablet/res" srcDir "../branding/unofficial/res" srcDir "${topobjdir}/mobile/android/base/res" // The main resources are symlinked in here. diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index f57ec594d3ca..b36e5ffeec0c 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -547,7 +547,6 @@ if CONFIG['MOZ_ANDROID_NEW_TABLET_UI'] and max_sdk_version >= 11: 'tabs/TabStripItemView.java', 'tabs/TabStripView.java' ] - ANDROID_RES_DIRS += [ SRCDIR + '/newtablet/res' ] gbjar.sources += sync_java_files gbjar.extra_jars += [ diff --git a/mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_item_title.xml b/mobile/android/base/resources/color-large-v11/new_tablet_tab_item_title.xml similarity index 100% rename from mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_item_title.xml rename to mobile/android/base/resources/color-large-v11/new_tablet_tab_item_title.xml diff --git a/mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_bg.xml b/mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_bg.xml similarity index 100% rename from mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_bg.xml rename to mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_bg.xml diff --git a/mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_title.xml b/mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_title.xml similarity index 100% rename from mobile/android/base/newtablet/res/color-large-v11/new_tablet_tab_strip_item_title.xml rename to mobile/android/base/resources/color-large-v11/new_tablet_tab_strip_item_title.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_default_favicon.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_default_favicon.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_default_favicon.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_default_favicon.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_forward.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_ic_menu_reload.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_menu.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_menu.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_menu.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_menu.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_nav_back.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_nav_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_nav_back.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_nav_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close_active.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close_active.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_close_active.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_close_active.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tab_new_dark.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count.png diff --git a/mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png b/mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png rename to mobile/android/base/resources/drawable-large-hdpi-v11/new_tablet_tabs_count_foreground.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_default_favicon.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_default_favicon.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_default_favicon.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_default_favicon.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_forward.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_ic_menu_reload.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_menu.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_menu.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_menu.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_menu.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_nav_back.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_nav_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_nav_back.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_nav_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close_active.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close_active.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_close_active.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_close_active.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tab_new_dark.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count.png diff --git a/mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png b/mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png rename to mobile/android/base/resources/drawable-large-mdpi-v11/new_tablet_tabs_count_foreground.png diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_action_bar_button.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_action_bar_button.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_action_bar_button.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_action_bar_button.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_level.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_level.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_level.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_level.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_unknown.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_unknown.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_site_security_unknown.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_site_security_unknown.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_item_close_button.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_tab_item_close_button.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_item_close_button.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_tab_item_close_button.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_add_tab.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_add_tab.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_add_tab.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_add_tab.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_button.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_button.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_button.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_button.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_divider.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_divider.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_tab_strip_divider.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_tab_strip_divider.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_url_bar_nav_button.xml b/mobile/android/base/resources/drawable-large-v11/new_tablet_url_bar_nav_button.xml similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-v11/new_tablet_url_bar_nav_button.xml rename to mobile/android/base/resources/drawable-large-v11/new_tablet_url_bar_nav_button.xml diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_default_favicon.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_default_favicon.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_default_favicon.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_default_favicon.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_forward.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_ic_menu_reload.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_menu.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_menu.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_menu.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_menu.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_nav_back.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_nav_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_nav_back.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_nav_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_close_active.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tab_new_dark.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png b/mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png rename to mobile/android/base/resources/drawable-large-xhdpi-v11/new_tablet_tabs_count_foreground.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_default_favicon.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_forward.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_ic_menu_reload.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_menu.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_menu.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_menu.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_menu.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_nav_back.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_nav_back.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_nav_back.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_nav_back.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tab_close_active.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count.png diff --git a/mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png b/mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png rename to mobile/android/base/resources/drawable-large-xxhdpi-v11/new_tablet_tabs_count_foreground.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png b/mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png rename to mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_add.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png b/mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename to mobile/android/base/resources/drawable-xlarge-hdpi-v11/new_tablet_ic_menu_bookmark_remove.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png b/mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png rename to mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_add.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png b/mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename to mobile/android/base/resources/drawable-xlarge-mdpi-v11/new_tablet_ic_menu_bookmark_remove.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png b/mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png rename to mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_add.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png b/mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename to mobile/android/base/resources/drawable-xlarge-xhdpi-v11/new_tablet_ic_menu_bookmark_remove.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png b/mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png rename to mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_add.png diff --git a/mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png b/mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png similarity index 100% rename from mobile/android/base/newtablet/res/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png rename to mobile/android/base/resources/drawable-xlarge-xxhdpi-v11/new_tablet_ic_menu_bookmark_remove.png diff --git a/mobile/android/base/newtablet/res/layout-large-v11/new_tablet_browser_toolbar.xml b/mobile/android/base/resources/layout-large-v11/new_tablet_browser_toolbar.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/new_tablet_browser_toolbar.xml rename to mobile/android/base/resources/layout-large-v11/new_tablet_browser_toolbar.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tab_strip.xml b/mobile/android/base/resources/layout-large-v11/new_tablet_tab_strip.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tab_strip.xml rename to mobile/android/base/resources/layout-large-v11/new_tablet_tab_strip.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_counter.xml b/mobile/android/base/resources/layout-large-v11/new_tablet_tabs_counter.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_counter.xml rename to mobile/android/base/resources/layout-large-v11/new_tablet_tabs_counter.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_panel_back_button.xml b/mobile/android/base/resources/layout-large-v11/new_tablet_tabs_panel_back_button.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/new_tablet_tabs_panel_back_button.xml rename to mobile/android/base/resources/layout-large-v11/new_tablet_tabs_panel_back_button.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/tab_strip.xml b/mobile/android/base/resources/layout-large-v11/tab_strip.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/tab_strip.xml rename to mobile/android/base/resources/layout-large-v11/tab_strip.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item.xml b/mobile/android/base/resources/layout-large-v11/tab_strip_item.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item.xml rename to mobile/android/base/resources/layout-large-v11/tab_strip_item.xml diff --git a/mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item_view.xml b/mobile/android/base/resources/layout-large-v11/tab_strip_item_view.xml similarity index 100% rename from mobile/android/base/newtablet/res/layout-large-v11/tab_strip_item_view.xml rename to mobile/android/base/resources/layout-large-v11/tab_strip_item_view.xml From b634dd7ea5f460d39c42dce52e274a9a137e21d2 Mon Sep 17 00:00:00 2001 From: Patrick Brosset Date: Mon, 22 Dec 2014 23:36:35 +0100 Subject: [PATCH 04/15] Bug 1105825 - Disable all devtools animation actor tests since the waapi is pref'd off in beta/release; r=me --- toolkit/devtools/server/tests/browser/browser.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/toolkit/devtools/server/tests/browser/browser.ini b/toolkit/devtools/server/tests/browser/browser.ini index 64f125acc668..3268f26597d9 100644 --- a/toolkit/devtools/server/tests/browser/browser.ini +++ b/toolkit/devtools/server/tests/browser/browser.ini @@ -15,10 +15,15 @@ support-files = timeline-iframe-parent.html [browser_animation_actors_01.js] +skip-if = true # Bug 1114780 - Enable when the Web Animations API is pref'd on. [browser_animation_actors_02.js] +skip-if = true # Bug 1114780 - Enable when the Web Animations API is pref'd on. [browser_animation_actors_03.js] +skip-if = true # Bug 1114780 - Enable when the Web Animations API is pref'd on. [browser_animation_actors_04.js] +skip-if = true # Bug 1114780 - Enable when the Web Animations API is pref'd on. [browser_animation_actors_05.js] +skip-if = true # Bug 1114780 - Enable when the Web Animations API is pref'd on. [browser_navigateEvents.js] [browser_storage_dynamic_windows.js] [browser_storage_listings.js] From 9e04066b1dfe7581751567f5ccc66dab39c65e8c Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Mon, 22 Dec 2014 16:11:56 -0800 Subject: [PATCH 05/15] Bug 1087934 Share panel UI updates, r=markh --- browser/base/content/browser-social.js | 61 +++++++------ browser/base/content/browser.xul | 13 ++- .../test/social/browser_social_flyout.js | 19 ++-- .../content/test/social/social_flyout.html | 2 +- browser/modules/Social.jsm | 43 ++++++--- browser/themes/linux/browser.css | 51 +++++------ browser/themes/osx/browser.css | 88 +++++++++--------- .../customizableui/panelUIOverlay.inc.css | 4 + browser/themes/shared/social/chat.inc.css | 17 ++-- browser/themes/windows/browser.css | 90 +++++++------------ browser/themes/windows/jar.mn | 2 + 11 files changed, 194 insertions(+), 196 deletions(-) diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index 7955579113dd..eaba45b1df6b 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -479,11 +479,9 @@ SocialShare = { }, get iframe() { - // first element is our menu vbox. - if (this.panel.childElementCount == 1) - return null; - else - return this.panel.lastChild; + // panel.firstChild is our toolbar hbox, panel.lastChild is the iframe + // container hbox used for an interstitial "loading" graphic + return this.panel.lastChild.firstChild; }, uninit: function () { @@ -505,7 +503,7 @@ SocialShare = { iframe.setAttribute("tooltip", "aHTMLTooltip"); iframe.setAttribute("disableglobalhistory", "true"); iframe.setAttribute("flex", "1"); - panel.appendChild(iframe); + panel.lastChild.appendChild(iframe); iframe.addEventListener("load", function _firstload() { iframe.removeEventListener("load", _firstload, true); iframe.messageManager.loadFrameScript("chrome://browser/content/content.js", true); @@ -537,13 +535,13 @@ SocialShare = { // remove everything before the add-share-provider button (which should also // be lastChild if any share providers were added) let addButton = document.getElementById("add-share-provider"); - while (hbox.firstChild != addButton) { - hbox.removeChild(hbox.firstChild); + while (hbox.lastChild != addButton) { + hbox.removeChild(hbox.lastChild); } let selectedProvider = this.getSelectedProvider(); for (let provider of providers) { let button = document.createElement("toolbarbutton"); - button.setAttribute("class", "toolbarbutton share-provider-button"); + button.setAttribute("class", "toolbarbutton-1 share-provider-button"); button.setAttribute("type", "radio"); button.setAttribute("group", "share-providers"); button.setAttribute("image", provider.iconURL); @@ -554,7 +552,7 @@ SocialShare = { if (provider == selectedProvider) { this.defaultButton = button; } - hbox.insertBefore(button, addButton); + hbox.appendChild(button); } if (!this.defaultButton) { this.defaultButton = addButton; @@ -577,7 +575,7 @@ SocialShare = { _onclick: function() { Services.telemetry.getHistogramById("SOCIAL_PANEL_CLICKS").add(0); }, - + onShowing: function() { this.anchor.setAttribute("open", "true"); this.iframe.addEventListener("click", this._onclick, true); @@ -682,48 +680,40 @@ SocialShare = { let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData); + this._dynamicResizer.stop(); let size = provider.getPageSize("share"); if (size) { - this._dynamicResizer.stop(); + // let the css on the share panel define width, but height + // calculations dont work on all sites, so we allow that to be + // defined. + delete size.width; } // if we've already loaded this provider/page share endpoint, we don't want // to add another load event listener. - let reload = true; let endpointMatch = shareEndpoint == iframe.getAttribute("src"); - let docLoaded = iframe.contentDocument && iframe.contentDocument.readyState == "complete"; - if (endpointMatch && docLoaded) { - reload = shareEndpoint != iframe.contentDocument.location.spec; - } - if (!reload) { - if (!size) - this._dynamicResizer.start(this.panel, iframe); + if (endpointMatch) { + this._dynamicResizer.start(iframe.parentNode, iframe, size); iframe.docShell.isActive = true; iframe.docShell.isAppTab = true; let evt = iframe.contentDocument.createEvent("CustomEvent"); evt.initCustomEvent("OpenGraphData", true, true, JSON.stringify(pageData)); iframe.contentDocument.documentElement.dispatchEvent(evt); } else { + iframe.parentNode.setAttribute("loading", "true"); // first time load, wait for load and dispatch after load iframe.addEventListener("load", function panelBrowserOnload(e) { iframe.removeEventListener("load", panelBrowserOnload, true); iframe.docShell.isActive = true; iframe.docShell.isAppTab = true; + iframe.parentNode.removeAttribute("loading"); // to support standard share endpoints mimick window.open by setting // window.opener, some share endpoints rely on w.opener to know they // should close the window when done. iframe.contentWindow.opener = iframe.contentWindow; - setTimeout(function() { - if (size) { - let panel = SocialShare.panel; - let {width, height} = size; - width += panel.boxObject.width - iframe.boxObject.width; - height += panel.boxObject.height - iframe.boxObject.height; - panel.sizeTo(width, height); - } else { - SocialShare._dynamicResizer.start(iframe.parentNode, iframe); - } - }, 0); + + SocialShare._dynamicResizer.start(iframe.parentNode, iframe, size); + let evt = iframe.contentDocument.createEvent("CustomEvent"); evt.initCustomEvent("OpenGraphData", true, true, JSON.stringify(pageData)); iframe.contentDocument.documentElement.dispatchEvent(evt); @@ -747,9 +737,18 @@ SocialShare = { showDirectory: function() { this._createFrame(); let iframe = this.iframe; + if (iframe.getAttribute("src") == "about:providerdirectory") + return; iframe.removeAttribute("origin"); + iframe.parentNode.setAttribute("loading", "true"); + iframe.addEventListener("DOMContentLoaded", function _dcl(e) { + iframe.removeEventListener("DOMContentLoaded", _dcl, true); + iframe.parentNode.removeAttribute("loading"); + }, true); + iframe.addEventListener("load", function panelBrowserOnload(e) { iframe.removeEventListener("load", panelBrowserOnload, true); + hookWindowCloseForPanelClose(iframe.contentWindow); SocialShare._dynamicResizer.start(iframe.parentNode, iframe); diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 3bb17d3647b1..a42f415bf87b 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -287,17 +287,22 @@ { is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing"); }); let port = SocialSidebar.provider.getWorkerPort(); @@ -75,8 +80,7 @@ var tests = { is(cs.height, "400px", "should be 400px high"); is(iframe.boxObject.height, 400, "iframe should now be 400px high"); - iframe.contentWindow.addEventListener("resize", function _doneHandler() { - iframe.contentWindow.removeEventListener("resize", _doneHandler, false); + ensureEventFired(iframe.contentWindow, "resize").then(() => { cs = iframe.contentWindow.getComputedStyle(body); is(cs.width, "500px", "should now be 500px wide"); @@ -86,7 +90,7 @@ var tests = { panel.hidePopup(); port.close(); next(); - }, false); + }); SocialFlyout.dispatchPanelEvent("socialTest-MakeWider"); break; } @@ -117,13 +121,12 @@ var tests = { if (e.data.result != "shown") return; let iframe = panel.firstChild; - iframe.contentDocument.addEventListener("SocialTest-DoneCloseSelf", function _doneHandler() { - iframe.contentDocument.removeEventListener("SocialTest-DoneCloseSelf", _doneHandler, false); + ensureEventFired(iframe.contentDocument, "SocialTest-DoneCloseSelf").then(() => { port.close(); is(panel.state, "closed", "flyout should have closed itself"); Services.prefs.setBoolPref(ALLOW_SCRIPTS_TO_CLOSE_PREF, oldAllowScriptsToClose); next(); - }, false); + }); is(panel.state, "open", "flyout should be open"); SocialFlyout.dispatchPanelEvent("socialTest-CloseSelf"); break; diff --git a/browser/base/content/test/social/social_flyout.html b/browser/base/content/test/social/social_flyout.html index ff426783a541..f0265ffe43d4 100644 --- a/browser/base/content/test/social/social_flyout.html +++ b/browser/base/content/test/social/social_flyout.html @@ -31,7 +31,7 @@

This is a test social flyout panel.

- test link + test link diff --git a/browser/modules/Social.jsm b/browser/modules/Social.jsm index 8becf62c42ad..cf48542eb561 100644 --- a/browser/modules/Social.jsm +++ b/browser/modules/Social.jsm @@ -400,7 +400,7 @@ SocialErrorListener.prototype = { }; -function sizeSocialPanelToContent(panel, iframe) { +function sizeSocialPanelToContent(panel, iframe, requestedSize) { let doc = iframe.contentDocument; if (!doc || !doc.body) { return; @@ -408,14 +408,15 @@ function sizeSocialPanelToContent(panel, iframe) { // We need an element to use for sizing our panel. See if the body defines // an id for that element, otherwise use the body itself. let body = doc.body; + let docEl = doc.documentElement; let bodyId = body.getAttribute("contentid"); if (bodyId) { body = doc.getElementById(bodyId) || doc.body; } // offsetHeight/Width don't include margins, so account for that. let cs = doc.defaultView.getComputedStyle(body); - let width = PANEL_MIN_WIDTH; - let height = PANEL_MIN_HEIGHT; + let width = Math.max(PANEL_MIN_WIDTH, docEl.offsetWidth); + let height = Math.max(PANEL_MIN_HEIGHT, docEl.offsetHeight); // if the panel is preloaded prior to being shown, cs will be null. in that // case use the minimum size for the panel until it is shown. if (cs) { @@ -425,19 +426,33 @@ function sizeSocialPanelToContent(panel, iframe) { width = Math.max(computedWidth, width); } - // only add the extra space if the iframe has been loaded + // if our scrollHeight is still larger than the iframe, the css calculations + // above did not work for this site, increase the height. This can happen if + // the site increases its height for additional UI. + if (docEl.scrollHeight > iframe.boxObject.height) + height = docEl.scrollHeight; + + // if a size was defined in the manifest use it as a minimum + if (requestedSize) { + if (requestedSize.height) + height = Math.max(height, requestedSize.height); + if (requestedSize.width) + width = Math.max(width, requestedSize.width); + } + + // add the extra space used by the panel (toolbar, borders, etc) if the iframe + // has been loaded if (iframe.boxObject.width && iframe.boxObject.height) { // add extra space the panel needs if any width += panel.boxObject.width - iframe.boxObject.width; height += panel.boxObject.height - iframe.boxObject.height; } - // when size is computed, we want to be sure changes are "significant" since - // some sites will resize when the iframe is resized by a small amount, making - // the panel slowly shrink to some minimum. - if (Math.abs(panel.boxObject.width - width) > 2 || Math.abs(panel.boxObject.height - height) > 2) { - panel.sizeTo(width, height); - } + // using panel.sizeTo will ignore css transitions, set size via style + if (Math.abs(panel.boxObject.width - width) >= 2) + panel.style.width = width + "px"; + if (Math.abs(panel.boxObject.height - height) >= 2) + panel.style.height = height + "px"; } function DynamicResizeWatcher() { @@ -445,18 +460,18 @@ function DynamicResizeWatcher() { } DynamicResizeWatcher.prototype = { - start: function DynamicResizeWatcher_start(panel, iframe) { + start: function DynamicResizeWatcher_start(panel, iframe, requestedSize) { this.stop(); // just in case... let doc = iframe.contentDocument; - this._mutationObserver = new iframe.contentWindow.MutationObserver(function(mutations) { - sizeSocialPanelToContent(panel, iframe); + this._mutationObserver = new iframe.contentWindow.MutationObserver((mutations) => { + sizeSocialPanelToContent(panel, iframe, requestedSize); }); // Observe anything that causes the size to change. let config = {attributes: true, characterData: true, childList: true, subtree: true}; this._mutationObserver.observe(doc, config); // and since this may be setup after the load event has fired we do an // initial resize now. - sizeSocialPanelToContent(panel, iframe); + sizeSocialPanelToContent(panel, iframe, requestedSize); }, stop: function DynamicResizeWatcher_stop() { if (this._mutationObserver) { diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css index 927bfd50b9b4..f70ee3b519e9 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -1609,46 +1609,47 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- /* social share panel */ .social-share-frame { - background: linear-gradient(to bottom, rgba(242,242,242,.99), rgba(242,242,242,.95)); - border-left: 1px solid #f8f8f8; - width: 330px; + border-top: 1px solid #f8f8f8; + width: 756px; height: 150px; - /* we resize our panels dynamically, make it look nice */ - transition: height 100ms ease-out, width 100ms ease-out; +} + +#share-container { + min-width: 756px; + background-color: white; + background-repeat: no-repeat; + background-position: center center; +} +#share-container[loading] { + background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png); +} +#share-container > browser { + transition: opacity 150ms ease-in-out; + opacity: 1; +} +#share-container[loading] > browser { + opacity: 0; } .social-share-toolbar { - border-right: 1px solid #dedede; - background: linear-gradient(to bottom, rgba(247,247,247,.99), rgba(247,247,247,.95)); + border-bottom: 1px solid #dedede; + padding: 2px; } #social-share-provider-buttons { - border-right: 1px solid #fbfbfb; - padding: 6px; -} - -#social-share-provider-buttons > .share-provider-button { - padding: 6px; + padding: 0; margin: 0; - border: none; - border-radius: 2px; } -#social-share-provider-buttons > .share-provider-button[checked], -#social-share-provider-buttons > .share-provider-button:active { +.share-provider-button { padding: 5px; - border: 1px solid #b5b5b8; - box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2); + margin: 2px; } -#social-share-provider-buttons > .share-provider-button[checked] { - background: linear-gradient(to bottom, #d9d9d9, #e3e3e3); -} - -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text { +.share-provider-button > .toolbarbutton-text { display: none; } -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon { +.share-provider-button > .toolbarbutton-icon { width: 16px; min-height: 16px; max-height: 16px; diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css index 9e130ac27fa4..d6f63884d6e4 100644 --- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -2514,46 +2514,55 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url- /* social share panel */ .social-share-frame { - background: linear-gradient(to bottom, rgba(242,242,242,.99), rgba(242,242,242,.95)); - border-left: 1px solid #f8f8f8; - width: 330px; + border-top: 1px solid #f8f8f8; + min-width: 756px; height: 150px; /* we resize our panels dynamically, make it look nice */ - transition: height 100ms ease-out, width 100ms ease-out; +} + +#share-container { + min-width: 756px; + background-color: white; + background-repeat: no-repeat; + background-position: center center; +} +#share-container[loading] { + background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png); +} +#share-container > browser { + transition: opacity 150ms ease-in-out; + opacity: 1; +} +#share-container[loading] > browser { + opacity: 0; +} + +#manage-share-providers, +#social-sidebar-button:hover, +#social-sidebar-button:hover:active { + -moz-image-region: rect(18px, 468px, 36px, 450px); } .social-share-toolbar { - border-right: 1px solid #dedede; - background: linear-gradient(to bottom, rgba(247,247,247,.99), rgba(247,247,247,.95)); + border-bottom: 1px solid #dedede; + padding: 2px; } #social-share-provider-buttons { - border-right: 1px solid #fbfbfb; - padding: 6px; -} - -#social-share-provider-buttons > .share-provider-button { - padding: 6px; + padding: 0; margin: 0; - border: none; - border-radius: 2px; } -#social-share-provider-buttons > .share-provider-button[checked], -#social-share-provider-buttons > .share-provider-button:active { +.share-provider-button { padding: 5px; - border: 1px solid #b5b5b8; - box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2); + margin: 2px; } -#social-share-provider-buttons > .share-provider-button[checked] { - background: linear-gradient(to bottom, #d9d9d9, #e3e3e3); -} - -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text { +.share-provider-button > .toolbarbutton-text { display: none; } -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon { + +.share-provider-button > .toolbarbutton-icon { width: 16px; min-height: 16px; max-height: 16px; @@ -4500,44 +4509,27 @@ menulist.translate-infobar-element > .menulist-dropmarker { } #social-share-panel { - max-height: 600px; min-height: 100px; - max-width: 800px; min-width: 300px; + transition: height .3s ease-in-out, width .3s ease-in-out; } -.social-share-frame:-moz-locale-dir(ltr) { +#share-container, +.social-share-frame { border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-top-right-radius: inherit; - border-bottom-right-radius: inherit; -} - -.social-share-frame:-moz-locale-dir(rtl) { - border-top-left-radius: inherit; border-bottom-left-radius: inherit; border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -#social-share-panel > .social-share-toolbar:-moz-locale-dir(ltr) { - border-top-left-radius: inherit; - border-bottom-left-radius: inherit; -} - -#social-share-panel > .social-share-toolbar:-moz-locale-dir(rtl) { - border-top-right-radius: inherit; border-bottom-right-radius: inherit; } -#social-share-provider-buttons:-moz-locale-dir(ltr) { +#social-share-panel > .social-share-toolbar { border-top-left-radius: inherit; - border-bottom-left-radius: inherit; + border-top-right-radius: inherit; } -#social-share-provider-buttons:-moz-locale-dir(rtl) { +#social-share-provider-buttons { + border-top-left-radius: inherit; border-top-right-radius: inherit; - border-bottom-right-radius: inherit; } /* === end of social toolbar provider menu === */ diff --git a/browser/themes/shared/customizableui/panelUIOverlay.inc.css b/browser/themes/shared/customizableui/panelUIOverlay.inc.css index 05d2c0ca4c4c..b99a412da844 100644 --- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css +++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css @@ -702,6 +702,7 @@ panelview .toolbarbutton-1, .subviewbutton, .widget-overflow-list .toolbarbutton-1, .panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button, +.share-provider-button, .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton { -moz-appearance: none; padding: 0 6px; @@ -714,6 +715,7 @@ panelview .toolbarbutton-1, panelview .toolbarbutton-1, .subviewbutton, .widget-overflow-list .toolbarbutton-1, +.share-provider-button, .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton { border-width: 1px; } @@ -786,6 +788,7 @@ panelview .toolbarbutton-1@buttonStateHover@, toolbarbutton.subviewbutton@buttonStateHover@, menu.subviewbutton@menuStateHover@, menuitem.subviewbutton@menuStateHover@, +.share-provider-button@buttonStateHover@, .widget-overflow-list .toolbarbutton-1@buttonStateHover@, .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton@buttonStateHover@ { background-color: hsla(210,4%,10%,.08); @@ -800,6 +803,7 @@ panelview .toolbarbutton-1:-moz-any(@buttonStateActive@,[checked=true]), toolbarbutton.subviewbutton@buttonStateActive@, menu.subviewbutton@menuStateActive@, menuitem.subviewbutton@menuStateActive@, +.share-provider-button:-moz-any(@buttonStateActive@,[checked=true]), .widget-overflow-list .toolbarbutton-1@buttonStateActive@, .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton@buttonStateActive@ { background-color: hsla(210,4%,10%,.12); diff --git a/browser/themes/shared/social/chat.inc.css b/browser/themes/shared/social/chat.inc.css index 4804aa9d90fc..1da11e96dbf5 100644 --- a/browser/themes/shared/social/chat.inc.css +++ b/browser/themes/shared/social/chat.inc.css @@ -8,21 +8,24 @@ padding: 3px; } +#manage-share-providers, +#social-sidebar-button { + list-style-image: url("chrome://browser/skin/Toolbar.png"); + -moz-image-region: rect(0, 468px, 18px, 450px); +} + #social-sidebar-button { -moz-appearance: none; - list-style-image: url(chrome://browser/skin/social/gear_default.png); border: none; padding: 0; margin: 2px; } +#manage-share-providers > .toolbarbutton-icon, #social-sidebar-button > .toolbarbutton-icon { - min-height: 16px; - min-width: 16px; -} -#social-sidebar-button:hover, -#social-sidebar-button:hover:active { - list-style-image: url(chrome://browser/skin/social/gear_clicked.png); + min-height: 18px; + min-width: 18px; } + #social-sidebar-button > .toolbarbutton-menu-dropmarker { display: none; } diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index 9e296cf510f0..38361928ebdb 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -1573,46 +1573,46 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- /* social share panel */ -#social-share-panel > iframe { - background: linear-gradient(to bottom, #f0f4f7, #fafbfc); - width: 300px; +.social-share-frame { + min-width: 756px; height: 150px; } +#share-container { + min-width: 756px; + background-color: white; + background-repeat: no-repeat; + background-position: center center; +} +#share-container[loading] { + background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png); +} +#share-container > browser { + transition: opacity 150ms ease-in-out; + opacity: 1; +} +#share-container[loading] > browser { + opacity: 0; +} .social-share-toolbar { - border-right: 1px solid #e2e5e8; - background: linear-gradient(to bottom, #ffffff, #f5f7fa); + border-bottom: 1px solid #e2e5e8; + padding: 2px; } #social-share-provider-buttons { - padding: 6px; + padding: 0; + margin: 0; } -#social-share-provider-buttons > .share-provider-button { - -moz-appearance: none; +.share-provider-button { padding: 5px; - margin: 1px; - border: none; - background: none; - border-radius: 2px; + margin: 2px; } -#social-share-provider-buttons > .share-provider-button[checked="true"]:not([disabled="true"]), -#social-share-provider-buttons > .share-provider-button:hover, -#social-share-provider-buttons > .share-provider-button:active { - padding: 4px; - border: 1px solid #aeb8c1; - box-shadow: inset 1px 1px 1px rgba(10, 31, 51, 0.1); -} - -#social-share-provider-buttons > .share-provider-button[checked="true"]:not([disabled="true"]) { - background: linear-gradient(to bottom, rgba(230,232,234,.65), #d2d5d9); -} - -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-text { +.share-provider-button > .toolbarbutton-text { display: none; } -#social-share-provider-buttons > .share-provider-button > .toolbarbutton-icon { +.share-provider-button > .toolbarbutton-icon { width: 16px; min-height: 16px; max-height: 16px; @@ -1632,52 +1632,26 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { } #social-share-panel { - max-height: 600px; min-height: 100px; - max-width: 800px; - min-width: 300px; + min-width: 766px; } +#share-container, .social-share-frame { - background: linear-gradient(to bottom, #f0f4f7, #fafbfc); - width: 330px; - height: 150px; - /* we resize our panels dynamically, make it look nice */ - transition: height 100ms ease-out, width 100ms ease-out; -} - -.social-share-frame:-moz-locale-dir(ltr) { border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-top-right-radius: inherit; - border-bottom-right-radius: inherit; -} - -.social-share-frame:-moz-locale-dir(rtl) { - border-top-left-radius: inherit; border-bottom-left-radius: inherit; border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -#social-share-panel > .social-share-toolbar:-moz-locale-dir(ltr) { - border-top-left-radius: inherit; - border-bottom-left-radius: inherit; -} - -#social-share-panel > .social-share-toolbar:-moz-locale-dir(rtl) { - border-top-right-radius: inherit; border-bottom-right-radius: inherit; } -#social-share-provider-buttons:-moz-locale-dir(ltr) { +#social-share-panel > .social-share-toolbar { border-top-left-radius: inherit; - border-bottom-left-radius: inherit; + border-top-right-radius: inherit; } -#social-share-provider-buttons:-moz-locale-dir(rtl) { +#social-share-provider-buttons { + border-top-left-radius: inherit; border-top-right-radius: inherit; - border-bottom-right-radius: inherit; } /* social recommending panel */ diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index 853995c6f666..0040fb14e4b1 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -686,6 +686,8 @@ browser.jar: skin/classic/aero/browser/tabbrowser/tab-background-end@2x.png (tabbrowser/tab-background-end@2x.png) skin/classic/aero/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png) + skin/classic/aero/browser/tabbrowser/pendingpaint.png (../shared/tabbrowser/pendingpaint.png) + # NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in # Makefile.in with a non-default marker of "%" and the result of that gets packaged. skin/classic/aero/browser/tabbrowser/tab-selected-end.svg (tab-selected-end-aero.svg) From b55dfdb095b7bdd518973c48d3bfe69bbc15ec0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Qu=C3=A8ze?= Date: Tue, 23 Dec 2014 02:12:36 +0100 Subject: [PATCH 06/15] Bug 1110678 - Re-implement Ctrl+up/down and Alt+up/down in the search field, r=felipe. --- browser/base/content/urlbarBindings.xml | 52 ++++++++++------- browser/components/search/content/search.xml | 60 ++++++++++++++++++-- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 0194b95005b7..1d87d1a751e6 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -1000,6 +1000,32 @@ class="search-setting-button search-panel-header" label="&changeSearchSettings.button;"/> + + + + + with:" header. let headerSearchText = @@ -1074,6 +1081,8 @@ let addEngines = gBrowser.selectedBrowser.engines; if (addEngines && addEngines.length > 0) { + const kBundleURI = "chrome://browser/locale/search.properties"; + let bundle = Services.strings.createBundle(kBundleURI); for (let engine of addEngines) { let button = document.createElementNS(kXULNS, "button"); let label = bundle.formatStringFromName("cmd_addFoundEngine", @@ -1109,8 +1118,9 @@ hiddenList = []; } + let currentEngineName = Services.search.currentEngine.name; let engines = Services.search.getVisibleEngines() - .filter(e => e.name != currentEngine.name && + .filter(e => e.name != currentEngineName && hiddenList.indexOf(e.name) == -1); let header = document.getAnonymousElementByAttribute(this, "anonid", diff --git a/browser/components/search/content/search.xml b/browser/components/search/content/search.xml index 78388bbcbf55..e370865de917 100644 --- a/browser/components/search/content/search.xml +++ b/browser/components/search/content/search.xml @@ -467,6 +467,9 @@ aEvent.preventDefault(); aEvent.stopPropagation(); + + if (this.hasAttribute("oneoffui")) + this.openSuggestionsPanel(); ]]> @@ -647,10 +650,9 @@ false - + @@ -914,7 +916,11 @@ Date: Mon, 22 Dec 2014 19:49:04 -0800 Subject: [PATCH 07/15] Bug 1098239 - Rewrite mobile/android Gradle integration. r=me This is a big patch, but it's essentially NPOTB. The part that is POTB is ... removing Gradle integration from the build. I've implemented |mach gradle-install| as a substitute for the build system stuff; it's just so much easier to iterate on a mach command than a moz.build and Makefile.in. I'm landing this with self-review because this lessens the impact of the Gradle integration on the build system and because I am the only person who understands either the old or the new system. You'll need to run |mach gradle-install| at top level to configure the new Gradle integration. But |mach gradle ...| does the right thing configuration steps too. This patch rewrites most of the Gradle integration. The major changes are: * all .gradle files move into mobile/android/gradle; * all the Gradle projects live in the object directory; * mozconfig exposed to all build.gradle files; * simplification of Android configuration between build.gradle files; * support for user-specified version of build tools; * first steps towards supporting builds from the source directory; * bumps Gradle to 2.2.1; * bumps the Android-Gradle plugin to 0.14.4. This is seemingly a step backwards given that we'd prefer to ship the .idea directory in the source directory. But in fact we get closer to that; it's possible to run ./gradlew in the source directory and get a reasonable build. We'll progress with this in time. The win right now is that the projects are nested, which makes importing work better on Linux machines. Unfortunately IntelliJ 13 and 14 now have conflicting Android-Gradle plugin version requirements, so we now only support IntelliJ 14.0.2 and above. --HG-- rename : mobile/android/base/gradle_AndroidManifest.xml => mobile/android/gradle/base/AndroidManifest.xml rename : mobile/android/base/gradle_AndroidManifest.xml => mobile/android/gradle/branding/AndroidManifest.xml rename : mobile/android/gradle/omnijar/gradle_AndroidManifest.xml => mobile/android/gradle/omnijar/AndroidManifest.xml rename : mobile/android/base/gradle_AndroidManifest.xml => mobile/android/gradle/preprocessed_code/AndroidManifest.xml rename : mobile/android/base/gradle_AndroidManifest.xml => mobile/android/gradle/preprocessed_resources/AndroidManifest.xml rename : mobile/android/thirdparty/gradle_AndroidManifest.xml => mobile/android/gradle/thirdparty/AndroidManifest.xml --- .gitignore | 3 + .hgignore | 3 + mobile/android/app/build.gradle | 61 --------- mobile/android/base/build.gradle | 4 +- mobile/android/base/docs/gradle.rst | 12 +- mobile/android/gradle/Makefile.in | 59 --------- mobile/android/gradle/android.gradle | 29 +++++ mobile/android/gradle/app/build.gradle | 28 +++++ .../base/AndroidManifest.xml} | 0 mobile/android/gradle/base/build.gradle | 66 ++++++++++ .../gradle/branding/AndroidManifest.xml | 4 + mobile/android/gradle/branding/build.gradle | 16 +++ mobile/android/gradle/build.gradle | 29 +++-- mobile/android/gradle/gradle.properties | 2 + mobile/android/gradle/gradle.properties.in | 14 +-- .../gradle/gradle/wrapper/gradle-wrapper.jar | Bin 51348 -> 51018 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- mobile/android/gradle/moz.build | 5 - ...ndroidManifest.xml => AndroidManifest.xml} | 0 mobile/android/gradle/omnijar/build.gradle | 52 +++++--- .../preprocessed_code/AndroidManifest.xml | 4 + .../gradle/preprocessed_code/build.gradle | 16 +++ .../AndroidManifest.xml | 4 + .../preprocessed_resources/build.gradle | 24 ++++ mobile/android/gradle/settings.gradle | 49 +++++++- .../thirdparty/AndroidManifest.xml} | 0 mobile/android/gradle/thirdparty/build.gradle | 21 ++++ mobile/android/mach_commands.py | 119 ++++++++++++++++++ mobile/android/moz.build | 1 - mobile/android/thirdparty/build.gradle | 49 -------- 30 files changed, 448 insertions(+), 230 deletions(-) delete mode 100644 mobile/android/app/build.gradle delete mode 100644 mobile/android/gradle/Makefile.in create mode 100644 mobile/android/gradle/android.gradle create mode 100644 mobile/android/gradle/app/build.gradle rename mobile/android/{base/gradle_AndroidManifest.xml => gradle/base/AndroidManifest.xml} (100%) create mode 100644 mobile/android/gradle/base/build.gradle create mode 100644 mobile/android/gradle/branding/AndroidManifest.xml create mode 100644 mobile/android/gradle/branding/build.gradle create mode 100644 mobile/android/gradle/gradle.properties delete mode 100644 mobile/android/gradle/moz.build rename mobile/android/gradle/omnijar/{gradle_AndroidManifest.xml => AndroidManifest.xml} (100%) create mode 100644 mobile/android/gradle/preprocessed_code/AndroidManifest.xml create mode 100644 mobile/android/gradle/preprocessed_code/build.gradle create mode 100644 mobile/android/gradle/preprocessed_resources/AndroidManifest.xml create mode 100644 mobile/android/gradle/preprocessed_resources/build.gradle rename mobile/android/{thirdparty/gradle_AndroidManifest.xml => gradle/thirdparty/AndroidManifest.xml} (100%) create mode 100644 mobile/android/gradle/thirdparty/build.gradle delete mode 100644 mobile/android/thirdparty/build.gradle diff --git a/.gitignore b/.gitignore index 5d4dca0b1476..8f5f436d6cc9 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ GPATH # Git clone directory for updating web-platform-tests testing/web-platform/sync/ + +# Android Gradle artifacts. +mobile/android/gradle/.gradle diff --git a/.hgignore b/.hgignore index 619012cedad9..2771ebb4e75f 100644 --- a/.hgignore +++ b/.hgignore @@ -93,3 +93,6 @@ GPATH # including the following three lines ^browser/components/loop/standalone/content/legal/styles/.*\.css$ ^browser/components/loop/standalone/content/legal/terms/en_US\.html$ + +# Android Gradle artifacts. +^mobile/android/gradle/.gradle diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle deleted file mode 100644 index 259254e906d3..000000000000 --- a/mobile/android/app/build.gradle +++ /dev/null @@ -1,61 +0,0 @@ -project.buildDir = "${topobjdir}/mobile/android/gradle/app/build" - -apply plugin: 'android' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - - defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - } - - buildTypes { - release { - runProguard false - proguardFile getDefaultProguardFile('proguard-android.txt') - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - - android { - lintOptions { - abortOnError false - } - } - - sourceSets { - main { - manifest { - srcFile "${topobjdir}/mobile/android/base/AndroidManifest.xml" - } - - assets { - srcDir "${topobjdir}/dist/fennec/assets" - } - - jniLibs { - srcDir "${topobjdir}/dist/fennec/lib" - } - } - - androidTest { - java { - srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/robocop_harness/java" - srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/robocop/java" - srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/background/java" - srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/browser/java" - } - } - } -} - -dependencies { - compile project(':base') - androidTestCompile fileTree(dir: "../../../build/mobile/robocop", include: ['*.jar']) -} diff --git a/mobile/android/base/build.gradle b/mobile/android/base/build.gradle index 8737f995b15b..6468135f6b1c 100644 --- a/mobile/android/base/build.gradle +++ b/mobile/android/base/build.gradle @@ -1,6 +1,6 @@ project.buildDir = "${topobjdir}/mobile/android/gradle/base/build" -apply plugin: 'android-library' +apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion @@ -14,7 +14,7 @@ android { buildTypes { release { - runProguard false + minifyEnabled false proguardFile getDefaultProguardFile('proguard-android.txt') } } diff --git a/mobile/android/base/docs/gradle.rst b/mobile/android/base/docs/gradle.rst index 02980cc06bfa..7be8b1e7f96b 100644 --- a/mobile/android/base/docs/gradle.rst +++ b/mobile/android/base/docs/gradle.rst @@ -18,10 +18,10 @@ The debug APK will be at The ``$OBJDIR/mobile/android/gradle`` directory can be imported into IntelliJ as follows: -- File > Import Project +- File > Import Project... - [select ``$OBJDIR/mobile/android/gradle``] - Import project from external model > Gradle -- [select Use default Gradle wrapper] +- [select Use customizable Gradle wrapper] When prompted, do not add any files to git. You may need to re-open the project, or restart IntelliJ, to pick up a compiler language-level change. @@ -42,11 +42,11 @@ Caveats How the Gradle project is laid out ---------------------------------- -To the greatest extent possible, the Gradle configuration lives in the source -directory. The only Gradle configuration that lives in the object directory is -installed when building the ``mobile/android/gradle`` directory. +To the greatest extent possible, the Gradle configuration lives in the object +directory. -At the time of writing, their are three sub-modules: *app*, *base*, and *thirdparty*. +At the time of writing, their are three main sub-modules: *app*, *base*, and +*thirdparty*, and several smaller sub-modules. *app* is the Fennec wrapper; it generates the **org.mozilla.fennec.R** resource package. *base* is the Gecko code; it generates the **org.mozilla.gecko.R** diff --git a/mobile/android/gradle/Makefile.in b/mobile/android/gradle/Makefile.in deleted file mode 100644 index ce217a748ece..000000000000 --- a/mobile/android/gradle/Makefile.in +++ /dev/null @@ -1,59 +0,0 @@ -# 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/. - -gradle := \ - local.properties.in \ - gradle.properties.in \ - $(NULL) - -gradle_PATH := $(CURDIR) -gradle_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir)) -gradle_FLAGS += -Dtopobjdir=$(abspath $(DEPTH)) -gradle_FLAGS += -DANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT) -gradle_KEEP_PATH := 1 -PP_TARGETS += gradle - -wrapper_FILES := \ - build.gradle \ - settings.gradle \ - gradle/wrapper/gradle-wrapper.jar \ - gradle/wrapper/gradle-wrapper.properties \ - gradlew \ - $(NULL) - -wrapper_DEST := $(CURDIR) -wrapper_KEEP_PATH := 1 -INSTALL_TARGETS += wrapper - -base/src/main/java/org/mozilla/gecko: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/mobile/android/base $@ -libs:: base/src/main/java/org/mozilla/gecko - -base/src/main/res: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/mobile/android/base/resources $@ -libs:: base/src/main/res - -app/src/androidTest/robocop_harness/java/org/mozilla/gecko: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/build/mobile/robocop $@ -libs:: app/src/androidTest/robocop_harness/java/org/mozilla/gecko - -app/src/androidTest/robocop/java/org/mozilla/gecko/tests: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/mobile/android/base/tests $@ -libs:: app/src/androidTest/robocop/java/org/mozilla/gecko/tests - -app/src/androidTest/browser/java/org/mozilla/gecko: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/mobile/android/tests/browser/junit3/src $@ -libs:: app/src/androidTest/browser/java/org/mozilla/gecko - -app/src/androidTest/background/java/org/mozilla/gecko/background: - $(NSINSTALL) -D ${@D} - ln -s $(topsrcdir)/mobile/android/tests/background/junit3/src $@ -libs:: app/src/androidTest/background/java/org/mozilla/gecko/background - -include $(topsrcdir)/config/rules.mk diff --git a/mobile/android/gradle/android.gradle b/mobile/android/gradle/android.gradle new file mode 100644 index 000000000000..2c9cd85a8e18 --- /dev/null +++ b/mobile/android/gradle/android.gradle @@ -0,0 +1,29 @@ +// Configure shared Android settings. This should be run (using "apply from") +// immediately after applying the Android plugin. Be aware that IntelliJ does +// not parse these values correctly: the Android-Gradle facet panel manually +// parses build.gradle rather than interrogating the Gradle model. + +android { + compileSdkVersion "android-${mozconfig.defines.ANDROID_TARGET_SDK}" + // Turn "android-sdk/build-tools/21.1.1" into "21.1.1". + buildToolsVersion (new File(mozconfig.substs.ANDROID_BUILD_TOOLS).getName()) + + defaultConfig { + targetSdkVersion mozconfig.defines.ANDROID_TARGET_SDK + minSdkVersion mozconfig.defines.MOZ_ANDROID_MIN_SDK_VERSION + if (mozconfig.defines.MOZ_ANDROID_MAX_SDK_VERSION) { + maxSdkVersion mozconfig.defines.MOZ_ANDROID_MAX_SDK_VERSION + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + android { + lintOptions { + abortOnError false + } + } +} diff --git a/mobile/android/gradle/app/build.gradle b/mobile/android/gradle/app/build.gradle new file mode 100644 index 000000000000..884d189b9ffc --- /dev/null +++ b/mobile/android/gradle/app/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'com.android.application' + +apply from: rootProject.file("${topsrcdir}/mobile/android/gradle/android.gradle") + +android { + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } + + sourceSets { + androidTest { + java { + srcDir "${topobjdir}/mobile/android/gradle/app/src/robocop_harness" + srcDir "${topobjdir}/mobile/android/gradle/app/src/robocop" + srcDir "${topobjdir}/mobile/android/gradle/app/src/background" + srcDir "${topobjdir}/mobile/android/gradle/app/src/browser" + } + } + } +} + +dependencies { + compile project(':base') + androidTestCompile fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/mobile/android/base/gradle_AndroidManifest.xml b/mobile/android/gradle/base/AndroidManifest.xml similarity index 100% rename from mobile/android/base/gradle_AndroidManifest.xml rename to mobile/android/gradle/base/AndroidManifest.xml diff --git a/mobile/android/gradle/base/build.gradle b/mobile/android/gradle/base/build.gradle new file mode 100644 index 000000000000..1d4d6c99ecc3 --- /dev/null +++ b/mobile/android/gradle/base/build.gradle @@ -0,0 +1,66 @@ +apply plugin: 'com.android.library' + +apply from: "${topsrcdir}/mobile/android/gradle/android.gradle" + +android { + defaultConfig { + applicationId 'org.mozilla.gecko' + } + + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } + + sourceSets { + main { + java { + exclude 'org/mozilla/gecko/tests/**' + exclude 'org/mozilla/gecko/resources/**' + if (!mozconfig.substs.MOZ_CRASHREPORTER) { + exclude 'org/mozilla/gecko/CrashReporter.java' + } + } + + res { + if (mozconfig.substs.MOZ_CRASHREPORTER) { + srcDir "src/crashreporter/res" + } + } + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:support-v4:19.1.+' + + if (mozconfig.substs.MOZ_NATIVE_DEVICES) { + compile 'com.android.support:appcompat-v7:19.1.+' + compile 'com.android.support:mediarouter-v7:19.1.+' + compile 'com.google.android.gms:play-services:5.+' + } + + compile project(':branding') + compile project(':omnijar') + compile project(':preprocessed_code') + compile project(':preprocessed_resources') + compile project(':thirdparty') +} + +android.libraryVariants.all { variant -> + variant.checkManifest.dependsOn generateCodeAndResources +} + +apply plugin: 'idea' + +idea { + module { + // excludeDirs = [] + excludeDirs += file('src/main/java/org/mozilla/gecko/tests') + excludeDirs += file('org/mozilla/gecko/tests') + excludeDirs += file('tests') + } +} diff --git a/mobile/android/gradle/branding/AndroidManifest.xml b/mobile/android/gradle/branding/AndroidManifest.xml new file mode 100644 index 000000000000..6f0ecf04b968 --- /dev/null +++ b/mobile/android/gradle/branding/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/mobile/android/gradle/branding/build.gradle b/mobile/android/gradle/branding/build.gradle new file mode 100644 index 000000000000..dde5bb96030d --- /dev/null +++ b/mobile/android/gradle/branding/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.android.library' + +apply from: "${topsrcdir}/mobile/android/gradle/android.gradle" + +android { + defaultConfig { + applicationId 'org.mozilla.gecko.branding' + } + + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } +} diff --git a/mobile/android/gradle/build.gradle b/mobile/android/gradle/build.gradle index 577a0e7ded92..26bc9de8873d 100644 --- a/mobile/android/gradle/build.gradle +++ b/mobile/android/gradle/build.gradle @@ -1,23 +1,34 @@ -buildDir = "${topobjdir}/mobile/android/gradle/build" - -ext { - compileSdkVersion = "${compileSdkVersion}" - buildToolsVersion = "${buildToolsVersion}" - - targetSdkVersion = "${targetSdkVersion}" - minSdkVersion = "${minSdkVersion}" +allprojects { + // Expose the per-object-directory configuration to all projects. + ext { + mozconfig = gradle.mozconfig + topsrcdir = gradle.mozconfig.topsrcdir + topobjdir = gradle.mozconfig.topobjdir + } } +buildDir "${topobjdir}/mobile/android/gradle/build" + buildscript { repositories { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:0.12.2' + classpath 'com.android.tools.build:gradle:0.14.4' } } repositories { jcenter() } + +subprojects { + task generateCodeAndResources(type:Exec) { + workingDir "${topobjdir}" + + commandLine "${topsrcdir}/mach" + args 'build' + args 'mobile/android/base/gradle-targets' + } +} diff --git a/mobile/android/gradle/gradle.properties b/mobile/android/gradle/gradle.properties new file mode 100644 index 000000000000..40ca366b2f0e --- /dev/null +++ b/mobile/android/gradle/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.parallel=true +org.gradle.daemon=true diff --git a/mobile/android/gradle/gradle.properties.in b/mobile/android/gradle/gradle.properties.in index 3f1a73f29462..faefe6dba05c 100644 --- a/mobile/android/gradle/gradle.properties.in +++ b/mobile/android/gradle/gradle.properties.in @@ -1,15 +1,5 @@ #filter substitution +#include gradle.properties + topsrcdir=@topsrcdir@ topobjdir=@topobjdir@ -compileSdkVersion=android-@ANDROID_TARGET_SDK@ -buildToolsVersion=20.0.0 -targetSdkVersion=@ANDROID_TARGET_SDK@ -minSdkVersion=@MOZ_ANDROID_MIN_SDK_VERSION@ -#ifdef MOZ_ANDROID_MAX_SDK_VERSION -maxSdkVersion=@MOZ_ANDROID_MAX_SDK_VERSION@ -#endif -#if MOZ_CRASHREPORTER -MOZ_CRASHREPORTER=true -#else -MOZ_CRASHREPORTER=false -#endif diff --git a/mobile/android/gradle/gradle/wrapper/gradle-wrapper.jar b/mobile/android/gradle/gradle/wrapper/gradle-wrapper.jar index 0087cd3b18659b5577cf6ad3ef61f8eb9416ebba..c97a8bdb9088d370da7e88784a7a093b971aa23a 100644 GIT binary patch delta 10956 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 delta 11402 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 - inputs.sourceDir srcDir - } + // project.sourceSets.main.java.srcDirs.each { srcDir -> + // inputs.sourceDir srcDir + // } + + inputs.sourceDir 'src/main/java/locales' + inputs.sourceDir 'src/main/java/chrome' + inputs.sourceDir 'src/main/java/components' + inputs.sourceDir 'src/main/java/modules' + inputs.sourceDir 'src/main/java/themes' + // Produce a single output file. outputs.file "${topobjdir}/dist/fennec/assets/omni.ja" @@ -40,3 +45,10 @@ task rebuildOmnijar(type:Exec) { // Rebuild the omnijar before the earliest Java task. tasks.compileJava.dependsOn rebuildOmnijar + +apply plugin: 'idea' + +idea { + module { + } +} diff --git a/mobile/android/gradle/preprocessed_code/AndroidManifest.xml b/mobile/android/gradle/preprocessed_code/AndroidManifest.xml new file mode 100644 index 000000000000..b51508815c4b --- /dev/null +++ b/mobile/android/gradle/preprocessed_code/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/mobile/android/gradle/preprocessed_code/build.gradle b/mobile/android/gradle/preprocessed_code/build.gradle new file mode 100644 index 000000000000..c1c5e4cbb8b2 --- /dev/null +++ b/mobile/android/gradle/preprocessed_code/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'android-library' + +apply from: "${topsrcdir}/mobile/android/gradle/android.gradle" + +android { + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } +} + +android.libraryVariants.all { variant -> + variant.checkManifest.dependsOn generateCodeAndResources +} diff --git a/mobile/android/gradle/preprocessed_resources/AndroidManifest.xml b/mobile/android/gradle/preprocessed_resources/AndroidManifest.xml new file mode 100644 index 000000000000..40744740afff --- /dev/null +++ b/mobile/android/gradle/preprocessed_resources/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/mobile/android/gradle/preprocessed_resources/build.gradle b/mobile/android/gradle/preprocessed_resources/build.gradle new file mode 100644 index 000000000000..89c470f1a2d6 --- /dev/null +++ b/mobile/android/gradle/preprocessed_resources/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'com.android.library' + +apply from: "${topsrcdir}/mobile/android/gradle/android.gradle" + +android { + defaultConfig { + applicationId 'org.mozilla.gecko.preprocessed_resources' + } + + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } +} + +android.libraryVariants.all { variant -> + variant.checkManifest.dependsOn generateCodeAndResources +} + +dependencies { + compile project(':branding') +} diff --git a/mobile/android/gradle/settings.gradle b/mobile/android/gradle/settings.gradle index 271edc973d00..8ce2199a406e 100644 --- a/mobile/android/gradle/settings.gradle +++ b/mobile/android/gradle/settings.gradle @@ -1,9 +1,50 @@ +// If our root project is in the object directory, we expect to be given +// topsrcdir from our environment via gradle.properties. If we don't get it, +// our root project is in the source directory, so we extract topsrcdir relative +// to the location of this script. +if (!hasProperty('topsrcdir')) { + // In the source directory, we're not worried about links crossing directories. + binding.variables['topsrcdir'] = new File("../../..").getCanonicalPath() + logger.warn("topsrcdir is undefined: assuming source directory Gradle invocation with topsrcdir=${topsrcdir}.") +} + +def command = ["${topsrcdir}/mach", "environment", "--format", "json", "--verbose"] +def proc = command.execute(null, new File(topsrcdir)) +def sout = new StringBuffer() +def serr = new StringBuffer() +proc.consumeProcessOutput(sout, serr) +proc.waitFor() + +if (proc.exitValue() != 0) { + throw new GradleException("Could not extract mozconfig/build environment from |${topsrcdir}/mach environment|!"); +} + +import groovy.json.JsonSlurper +def slurper = new JsonSlurper() +def json = slurper.parseText(sout.toString()) + include ':app' include ':base' +include ':branding' include ':omnijar' +include ':preprocessed_code' +include ':preprocessed_resources' include ':thirdparty' -project(':app').projectDir = new File("${topsrcdir}/mobile/android/app") -project(':base').projectDir = new File("${topsrcdir}/mobile/android/base") -project(':omnijar').projectDir = new File("${topsrcdir}/mobile/android/gradle/omnijar") -project(':thirdparty').projectDir = new File("${topsrcdir}/mobile/android/thirdparty") +def gradleRoot = new File("${json.topobjdir}/mobile/android/gradle") +project(':app').projectDir = new File(gradleRoot, 'app') +project(':base').projectDir = new File(gradleRoot, 'base') +project(':branding').projectDir = new File(gradleRoot, 'branding') +project(':omnijar').projectDir = new File(gradleRoot, 'omnijar') +project(':preprocessed_code').projectDir = new File(gradleRoot, 'preprocessed_code') +project(':preprocessed_resources').projectDir = new File(gradleRoot, 'preprocessed_resources') +project(':thirdparty').projectDir = new File(gradleRoot, 'thirdparty') + +// The Gradle instance is shared between settings.gradle and all the +// other build.gradle files (see +// http://forums.gradle.org/gradle/topics/define_extension_properties_from_settings_xml). +// We use this ext property to pass the per-object-directory mozconfig +// between scripts. This lets us execute set-up code before we gradle +// tries to configure the project even once, and as a side benefit +// saves invoking |mach environment| multiple times. +gradle.ext.mozconfig = json diff --git a/mobile/android/thirdparty/gradle_AndroidManifest.xml b/mobile/android/gradle/thirdparty/AndroidManifest.xml similarity index 100% rename from mobile/android/thirdparty/gradle_AndroidManifest.xml rename to mobile/android/gradle/thirdparty/AndroidManifest.xml diff --git a/mobile/android/gradle/thirdparty/build.gradle b/mobile/android/gradle/thirdparty/build.gradle new file mode 100644 index 000000000000..a4391d408c17 --- /dev/null +++ b/mobile/android/gradle/thirdparty/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'com.android.library' + +apply from: "${topsrcdir}/mobile/android/gradle/android.gradle" + +android { + defaultConfig { + applicationId 'org.mozilla.gecko.thirdparty' + } + + buildTypes { + release { + minifyEnabled false + proguardFile getDefaultProguardFile('proguard-android.txt') + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:support-v4:19.1.+' +} diff --git a/mobile/android/mach_commands.py b/mobile/android/mach_commands.py index 91750167ff7f..19572c6993f6 100644 --- a/mobile/android/mach_commands.py +++ b/mobile/android/mach_commands.py @@ -6,6 +6,8 @@ from __future__ import print_function, unicode_literals import argparse import logging +import os + import mozpack.path as mozpath from mozbuild.base import ( @@ -13,12 +15,25 @@ from mozbuild.base import ( MachCommandConditions as conditions, ) +from mozbuild.util import ( + FileAvoidWrite, +) + from mach.decorators import ( CommandArgument, CommandProvider, Command, ) +SUCCESS = ''' +You should be ready to build with Gradle and import into IntelliJ! Test with + + ./mach gradle build + +and in IntelliJ select File > Import project... and choose + + {topobjdir}/mobile/android/gradle +''' @CommandProvider class MachCommands(MachCommandBase): @@ -30,7 +45,111 @@ class MachCommands(MachCommandBase): # Avoid logging the command self.log_manager.terminal_handler.setLevel(logging.CRITICAL) + code = self.gradle_install(quiet=True) + if code: + return code + return self.run_process(['./gradlew'] + args, pass_thru=True, # Allow user to run gradle interactively. ensure_exit_code=False, # Don't throw on non-zero exit code. cwd=mozpath.join(self.topobjdir, 'mobile', 'android', 'gradle')) + + @Command('gradle-install', category='devenv', + description='Install gradle environment.', + conditions=[conditions.is_android]) + def gradle_install(self, quiet=False): + import mozpack.manifests + m = mozpack.manifests.InstallManifest() + + def srcdir(dst, src): + m.add_symlink(os.path.join(self.topsrcdir, src), dst) + + def objdir(dst, src): + m.add_symlink(os.path.join(self.topobjdir, src), dst) + + srcdir('build.gradle', 'mobile/android/gradle/build.gradle') + srcdir('settings.gradle', 'mobile/android/gradle/settings.gradle') + + m.add_pattern_copy(os.path.join(self.topsrcdir, 'mobile/android/gradle/gradle/wrapper'), '**', 'gradle/wrapper') + m.add_copy(os.path.join(self.topsrcdir, 'mobile/android/gradle/gradlew'), 'gradlew') + + defines = { + 'topsrcdir': self.topsrcdir, + 'topobjdir': self.topobjdir, + 'ANDROID_SDK_ROOT': self.substs['ANDROID_SDK_ROOT'], + } + m.add_preprocess(os.path.join(self.topsrcdir, 'mobile/android/gradle/gradle.properties.in'), + 'gradle.properties', + defines=defines, + deps=os.path.join(self.topobjdir, 'mobile/android/gradle/.deps/gradle.properties.pp')) + m.add_preprocess(os.path.join(self.topsrcdir, 'mobile/android/gradle/local.properties.in'), + 'local.properties', + defines=defines, + deps=os.path.join(self.topobjdir, 'mobile/android/gradle/.deps/local.properties.pp')) + + srcdir('branding/build.gradle', 'mobile/android/gradle/branding/build.gradle') + srcdir('branding/src/main/AndroidManifest.xml', 'mobile/android/gradle/branding/AndroidManifest.xml') + srcdir('branding/src/main/res', os.path.join(self.substs['MOZ_BRANDING_DIRECTORY'], 'res')) + + srcdir('preprocessed_code/build.gradle', 'mobile/android/gradle/preprocessed_code/build.gradle') + srcdir('preprocessed_code/src/main/AndroidManifest.xml', 'mobile/android/gradle/preprocessed_code/AndroidManifest.xml') + objdir('preprocessed_code/src/main/java', 'mobile/android/base/generated/preprocessed') + + srcdir('preprocessed_resources/build.gradle', 'mobile/android/gradle/preprocessed_resources/build.gradle') + srcdir('preprocessed_resources/src/main/AndroidManifest.xml', 'mobile/android/gradle/preprocessed_resources/AndroidManifest.xml') + objdir('preprocessed_resources/src/main/res', 'mobile/android/base/res') + + srcdir('thirdparty/build.gradle', 'mobile/android/gradle/thirdparty/build.gradle') + srcdir('thirdparty/src/main/AndroidManifest.xml', 'mobile/android/gradle/thirdparty/AndroidManifest.xml') + srcdir('thirdparty/src/main/java', 'mobile/android/thirdparty') + + srcdir('omnijar/build.gradle', 'mobile/android/gradle/omnijar/build.gradle') + srcdir('omnijar/src/main/java/locales', 'mobile/android/locales') + srcdir('omnijar/src/main/java/chrome', 'mobile/android/chrome') + srcdir('omnijar/src/main/java/components', 'mobile/android/components') + srcdir('omnijar/src/main/java/modules', 'mobile/android/modules') + srcdir('omnijar/src/main/java/themes', 'mobile/android/themes') + + srcdir('app/build.gradle', 'mobile/android/gradle/app/build.gradle') + objdir('app/src/main/AndroidManifest.xml', 'mobile/android/base/AndroidManifest.xml') + objdir('app/src/main/assets', 'dist/fennec/assets') + objdir('app/src/main/jniLibs', 'dist/fennec/lib') + # Test code. + srcdir('app/src/robocop_harness/org/mozilla/gecko', 'build/mobile/robocop') + srcdir('app/src/robocop/org/mozilla/gecko/tests', 'mobile/android/base/tests') + srcdir('app/src/background/org/mozilla/gecko', 'mobile/android/tests/background/junit3/src') + srcdir('app/src/browser/org/mozilla/gecko', 'mobile/android/tests/browser/junit3/src') + # Test libraries. + srcdir('app/libs', 'build/mobile/robocop') + + srcdir('base/build.gradle', 'mobile/android/gradle/base/build.gradle') + srcdir('base/src/main/AndroidManifest.xml', 'mobile/android/gradle/base/AndroidManifest.xml') + srcdir('base/src/main/java/org/mozilla/gecko', 'mobile/android/base') + srcdir('base/src/main/java/org/mozilla/mozstumbler', 'mobile/android/stumbler/java/org/mozilla/mozstumbler') + srcdir('base/src/main/java/org/mozilla/search', 'mobile/android/search/java/org/mozilla/search') + srcdir('base/src/main/res', 'mobile/android/base/resources') + srcdir('base/src/newtablet/res', 'mobile/android/base/newtablet/res') + srcdir('base/src/crashreporter/res', 'mobile/android/base/crashreporter/res') + + manifest_path = os.path.join(self.topobjdir, 'mobile', 'android', 'gradle.manifest') + with FileAvoidWrite(manifest_path) as f: + m.write(fileobj=f) + + self.virtualenv_manager.ensure() + code = self.run_process([ + self.virtualenv_manager.python_path, + os.path.join(self.topsrcdir, 'python/mozbuild/mozbuild/action/process_install_manifest.py'), + '--no-remove', + '--no-remove-all-directory-symlinks', + '--no-remove-empty-directories', + os.path.join(self.topobjdir, 'mobile', 'android', 'gradle'), + manifest_path], + pass_thru=True, # Allow user to run gradle interactively. + ensure_exit_code=False, # Don't throw on non-zero exit code. + cwd=mozpath.join(self.topsrcdir, 'mobile', 'android')) + + if not quiet: + if not code: + print(SUCCESS.format(topobjdir=self.topobjdir)) + + return code diff --git a/mobile/android/moz.build b/mobile/android/moz.build index 51cd2e0a9ada..8c12accb59bb 100644 --- a/mobile/android/moz.build +++ b/mobile/android/moz.build @@ -24,7 +24,6 @@ DIRS += [ 'fonts', 'geckoview_library', 'extensions', - 'gradle', ] if not CONFIG['LIBXUL_SDK']: diff --git a/mobile/android/thirdparty/build.gradle b/mobile/android/thirdparty/build.gradle deleted file mode 100644 index 084c42d9366f..000000000000 --- a/mobile/android/thirdparty/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -project.buildDir = "${topobjdir}/mobile/android/gradle/thirdparty/build" - -apply plugin: 'android-library' - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - - defaultConfig { - applicationId 'org.mozilla.gecko.thirdparty' - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - } - - buildTypes { - release { - runProguard false - proguardFile getDefaultProguardFile('proguard-android.txt') - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - - android { - lintOptions { - abortOnError false - } - } - - sourceSets { - main { - manifest { - srcFile 'gradle_AndroidManifest.xml' - } - - java { - srcDir "." - } - } - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:19.1.+' -} From a9106282099aed41a8c6cd840916b5d5cbce377a Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 23 Dec 2014 13:37:43 +0900 Subject: [PATCH 08/15] Bug 1112566 - Use jemalloc C99 msvc compat headers when building mozjemalloc compat glue and jemalloc3 replace-malloc library. r=glandium --- memory/build/moz.build | 2 ++ memory/replace/jemalloc/moz.build | 2 ++ 2 files changed, 4 insertions(+) diff --git a/memory/build/moz.build b/memory/build/moz.build index e6cf45a0a570..5945470a2278 100644 --- a/memory/build/moz.build +++ b/memory/build/moz.build @@ -30,6 +30,8 @@ if CONFIG['MOZ_JEMALLOC3']: GENERATED_INCLUDES += ['../jemalloc/src/include'] if CONFIG['_MSC_VER']: LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat'] + if not CONFIG['HAVE_INTTYPES_H']: + LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat/C99'] if CONFIG['MOZ_REPLACE_MALLOC']: SOURCES += [ diff --git a/memory/replace/jemalloc/moz.build b/memory/replace/jemalloc/moz.build index 74d03e99c390..861de37b3be7 100644 --- a/memory/replace/jemalloc/moz.build +++ b/memory/replace/jemalloc/moz.build @@ -29,5 +29,7 @@ DEFINES['MOZ_REPLACE_JEMALLOC'] = True GENERATED_INCLUDES += ['../../jemalloc/src/include'] if CONFIG['_MSC_VER']: LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat'] + if not CONFIG['HAVE_INTTYPES_H']: + LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat/C99'] DISABLE_STL_WRAPPING = True From aa02623d994b8b7fae8ff684876af54b6460b076 Mon Sep 17 00:00:00 2001 From: Guilherme Goncalves Date: Wed, 17 Dec 2014 14:46:35 -0200 Subject: [PATCH 09/15] Bug 1112566 - Move variable declaration to the top its block for MSVC compatibility. r=jasone,r=glandium --- ...claration-to-the-top-its-block-for-M.patch | 35 +++++++++++++++++++ memory/jemalloc/src/src/arena.c | 4 +-- memory/jemalloc/update.sh | 1 + 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 memory/jemalloc/0002-Move-variable-declaration-to-the-top-its-block-for-M.patch diff --git a/memory/jemalloc/0002-Move-variable-declaration-to-the-top-its-block-for-M.patch b/memory/jemalloc/0002-Move-variable-declaration-to-the-top-its-block-for-M.patch new file mode 100644 index 000000000000..83a75ac69d74 --- /dev/null +++ b/memory/jemalloc/0002-Move-variable-declaration-to-the-top-its-block-for-M.patch @@ -0,0 +1,35 @@ +From 9c6a8d3b0cc14fd26b119ad08f190e537771464f Mon Sep 17 00:00:00 2001 +From: Guilherme Goncalves +Date: Wed, 17 Dec 2014 14:46:35 -0200 +Subject: [PATCH] Move variable declaration to the top its block for MSVC + compatibility. + +--- + src/arena.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/arena.c b/src/arena.c +index bf78995..1eb4000 100644 +--- a/src/arena.c ++++ b/src/arena.c +@@ -2022,6 +2022,7 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, + * following run, then merge the first part with the existing + * allocation. + */ ++ arena_run_t *run; + size_t flag_dirty, splitsize, usize; + + usize = s2u(size + extra); +@@ -2030,8 +2031,7 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, + assert(usize >= usize_min); + splitsize = usize - oldsize; + +- arena_run_t *run = &arena_miscelm_get(chunk, +- pageind+npages)->run; ++ run = &arena_miscelm_get(chunk, pageind+npages)->run; + arena_run_split_large(arena, run, splitsize, zero); + + size = oldsize + splitsize; +-- +2.1.3 + diff --git a/memory/jemalloc/src/src/arena.c b/memory/jemalloc/src/src/arena.c index bf789950234d..1eb4000acf67 100644 --- a/memory/jemalloc/src/src/arena.c +++ b/memory/jemalloc/src/src/arena.c @@ -2022,6 +2022,7 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, * following run, then merge the first part with the existing * allocation. */ + arena_run_t *run; size_t flag_dirty, splitsize, usize; usize = s2u(size + extra); @@ -2030,8 +2031,7 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, assert(usize >= usize_min); splitsize = usize - oldsize; - arena_run_t *run = &arena_miscelm_get(chunk, - pageind+npages)->run; + run = &arena_miscelm_get(chunk, pageind+npages)->run; arena_run_split_large(arena, run, splitsize, zero); size = oldsize + splitsize; diff --git a/memory/jemalloc/update.sh b/memory/jemalloc/update.sh index 385f436289a6..73ca408a7320 100755 --- a/memory/jemalloc/update.sh +++ b/memory/jemalloc/update.sh @@ -15,6 +15,7 @@ git describe --long --abbrev=40 > VERSION rm -rf .git .gitignore .gitattributes autom4te.cache .autom4te.cfg patch -p1 < ../0001-Dont-overwrite-VERSION-on-a-git-repository.patch +patch -p1 < ../0002-Move-variable-declaration-to-the-top-its-block-for-M.patch cd .. hg addremove -q src From c41a18c8d2534a94c155d6889a980a7f96fc5c45 Mon Sep 17 00:00:00 2001 From: Guilherme Goncalves Date: Thu, 18 Dec 2014 15:01:21 +0900 Subject: [PATCH 10/15] Bug 1112566 - Add a isblank definition for MSVC < 2013. r=glandium --- ...d-a-isblank-definition-for-MSVC-2013.patch | 30 +++++++++++++++++++ .../internal/jemalloc_internal_decls.h | 7 +++++ memory/jemalloc/update.sh | 1 + 3 files changed, 38 insertions(+) create mode 100644 memory/jemalloc/0003-Add-a-isblank-definition-for-MSVC-2013.patch diff --git a/memory/jemalloc/0003-Add-a-isblank-definition-for-MSVC-2013.patch b/memory/jemalloc/0003-Add-a-isblank-definition-for-MSVC-2013.patch new file mode 100644 index 000000000000..6b75dd367ba6 --- /dev/null +++ b/memory/jemalloc/0003-Add-a-isblank-definition-for-MSVC-2013.patch @@ -0,0 +1,30 @@ +From 4dd4193c59ff3f77e4ab36214ec63425ca834323 Mon Sep 17 00:00:00 2001 +From: Guilherme Goncalves +Date: Thu, 18 Dec 2014 15:01:21 +0900 +Subject: [PATCH] Add a isblank definition for MSVC < 2013 + +--- + include/jemalloc/internal/jemalloc_internal_decls.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/include/jemalloc/internal/jemalloc_internal_decls.h b/include/jemalloc/internal/jemalloc_internal_decls.h +index fb2effb..65f2e4b 100644 +--- a/include/jemalloc/internal/jemalloc_internal_decls.h ++++ b/include/jemalloc/internal/jemalloc_internal_decls.h +@@ -52,6 +52,13 @@ typedef intptr_t ssize_t; + # define __func__ __FUNCTION__ + /* Disable warnings about deprecated system functions. */ + # pragma warning(disable: 4996) ++#if _MSC_VER < 1800 ++static int ++isblank(int c) ++{ ++ return (c == '\t' || c == ' '); ++} ++#endif + #else + # include + #endif +-- +2.1.3 + diff --git a/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_decls.h b/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_decls.h index fb2effbf2a83..65f2e4bfe705 100644 --- a/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_decls.h +++ b/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_decls.h @@ -52,6 +52,13 @@ typedef intptr_t ssize_t; # define __func__ __FUNCTION__ /* Disable warnings about deprecated system functions. */ # pragma warning(disable: 4996) +#if _MSC_VER < 1800 +static int +isblank(int c) +{ + return (c == '\t' || c == ' '); +} +#endif #else # include #endif diff --git a/memory/jemalloc/update.sh b/memory/jemalloc/update.sh index 73ca408a7320..7b2ae74b4ae4 100755 --- a/memory/jemalloc/update.sh +++ b/memory/jemalloc/update.sh @@ -16,6 +16,7 @@ rm -rf .git .gitignore .gitattributes autom4te.cache .autom4te.cfg patch -p1 < ../0001-Dont-overwrite-VERSION-on-a-git-repository.patch patch -p1 < ../0002-Move-variable-declaration-to-the-top-its-block-for-M.patch +patch -p1 < ../0003-Add-a-isblank-definition-for-MSVC-2013.patch cd .. hg addremove -q src From 61bbfc882e5c67d604ce5ec14a2fcd9a77fd3873 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 18 Dec 2014 20:03:53 +0900 Subject: [PATCH 11/15] Bug 1108858 - Avoid building libxul twice as much as necessary during Linux PGO builds. r=mshal --- toolkit/library/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 580852b14fc3..79c97c9db51a 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -14,7 +14,7 @@ endif include $(topsrcdir)/config/rules.mk ifdef COMPILE_ENVIRONMENT -libs:: $(FINAL_TARGET)/dependentlibs.list +target:: $(FINAL_TARGET)/dependentlibs.list endif $(FINAL_TARGET)/dependentlibs.list: $(topsrcdir)/toolkit/library/dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list)))) From 1366dd750a97e6f9bd0a54865655e7daa37b9d45 Mon Sep 17 00:00:00 2001 From: Matthew Noorenberghe Date: Tue, 23 Dec 2014 02:35:28 -0500 Subject: [PATCH 12/15] Bug 1113574 - Check that the room is still open before resuming the tour from a join notification. r=dmose,markh The room participant list only gets updated after getting a push notification and this can lead to the Rooms store still showing the user in their room even after they have left. To avoid this, we check that the for the room is actually still present. --HG-- extra : rebase_source : f4133b922e8be4cc3ece3aebc9e96162efd3190e --- browser/components/loop/MozLoopService.jsm | 103 +++++++++++++-------- browser/modules/Chat.jsm | 55 +++++++---- 2 files changed, 98 insertions(+), 60 deletions(-) diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index 81b06b5c3654..17c1d93d0c13 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -784,6 +784,22 @@ let MozLoopServiceInternal = { }, pc.id); }, + getChatWindowID: function(conversationWindowData) { + // Try getting a window ID that can (re-)identify this conversation, or resort + // to a globally unique one as a last resort. + // XXX We can clean this up once rooms and direct contact calling are the only + // two modes left. + let windowId = ("contact" in conversationWindowData) ? + conversationWindowData.contact._guid || gLastWindowId++ : + conversationWindowData.roomToken || conversationWindowData.callId || + gLastWindowId++; + return windowId.toString(); + }, + + getChatURL: function(chatWindowId) { + return "about:loopconversation#" + chatWindowId; + }, + /** * Opens the chat window * @@ -794,20 +810,11 @@ let MozLoopServiceInternal = { openChatWindow: function(conversationWindowData) { // So I guess the origin is the loop server!? let origin = this.loopServerUri; - // Try getting a window ID that can (re-)identify this conversation, or resort - // to a globally unique one as a last resort. - // XXX We can clean this up once rooms and direct contact calling are the only - // two modes left. - let windowId = ("contact" in conversationWindowData) ? - conversationWindowData.contact._guid || gLastWindowId++ : - conversationWindowData.roomToken || conversationWindowData.callId || - gLastWindowId++; - // Store the id as a string, as that's what we use elsewhere. - windowId = windowId.toString(); + let windowId = this.getChatWindowID(conversationWindowData); gConversationWindowData.set(windowId, conversationWindowData); - let url = "about:loopconversation#" + windowId; + let url = this.getChatURL(windowId); let callback = chatbox => { // We need to use DOMContentLoaded as otherwise the injection will happen @@ -1099,36 +1106,7 @@ this.MozLoopService = { } }); - // Resume the tour (re-opening the tab, if necessary) if someone else joins - // a room of ours and it's currently open. - LoopRooms.on("joined", (e, room, participant) => { - let isOwnerInRoom = false; - let isOtherInRoom = false; - - if (!this.getLoopPref("gettingStarted.resumeOnFirstJoin")) { - return; - } - - if (!room.participants) { - return; - } - - // The particpant that joined isn't necessarily included in room.participants (depending on - // when the broadcast happens) so concatenate. - for (let participant of room.participants.concat(participant)) { - if (participant.owner) { - isOwnerInRoom = true; - } else { - isOtherInRoom = true; - } - } - - if (!isOwnerInRoom || !isOtherInRoom) { - return; - } - - this.resumeTour("open"); - }); + LoopRooms.on("joined", this.maybeResumeTourOnRoomJoined.bind(this)); // If expiresTime is not in the future and the user hasn't // previously authenticated then skip registration. @@ -1144,6 +1122,49 @@ this.MozLoopService = { return deferredInitialization.promise; }), + /** + * Maybe resume the tour (re-opening the tab, if necessary) if someone else joins + * a room of ours and it's currently open. + */ + maybeResumeTourOnRoomJoined: function(e, room, participant) { + let isOwnerInRoom = false; + let isOtherInRoom = false; + + if (!this.getLoopPref("gettingStarted.resumeOnFirstJoin")) { + return; + } + + if (!room.participants) { + return; + } + + // The particpant that joined isn't necessarily included in room.participants (depending on + // when the broadcast happens) so concatenate. + for (let participant of room.participants.concat(participant)) { + if (participant.owner) { + isOwnerInRoom = true; + } else { + isOtherInRoom = true; + } + } + + if (!isOwnerInRoom || !isOtherInRoom) { + return; + } + + // Check that the room chatbox is still actually open using its URL + let chatboxesForRoom = [...Chat.chatboxes].filter(chatbox => { + return chatbox.src == MozLoopServiceInternal.getChatURL(room.roomToken); + }); + + if (!chatboxesForRoom.length) { + log.warn("Tried to resume the tour from a join when the chatbox was closed", room); + return; + } + + this.resumeTour("open"); + }, + /** * The core of the initialization work that happens once the browser is ready * (after a timer when called during startup). diff --git a/browser/modules/Chat.jsm b/browser/modules/Chat.jsm index ebb06ac5e27b..a6a4809ba19d 100644 --- a/browser/modules/Chat.jsm +++ b/browser/modules/Chat.jsm @@ -50,6 +50,38 @@ function getChromeWindow(contentWin) { */ let Chat = { + + /** + * Iterator of elements from this module in all windows. + */ + get chatboxes() { + return function*() { + let winEnum = Services.wm.getEnumerator("navigator:browser"); + while (winEnum.hasMoreElements()) { + let win = winEnum.getNext(); + let chatbar = win.document.getElementById("pinnedchats"); + if (!chatbar) + continue; + + // Make a new array instead of the live NodeList so this iterator can be + // used for closing/deleting. + let chatboxes = [c for (c of chatbar.children)]; + for (let chatbox of chatboxes) { + yield chatbox; + } + } + + // include standalone chat windows + winEnum = Services.wm.getEnumerator("Social:Chat"); + while (winEnum.hasMoreElements()) { + let win = winEnum.getNext(); + if (win.closed) + continue; + yield win.document.getElementById("chatter"); + } + }(); + }, + /** * Open a new chatbox. * @@ -108,26 +140,11 @@ let Chat = { * The origin from which all chats should be closed. */ closeAll: function(origin) { - // close all attached chat windows - let winEnum = Services.wm.getEnumerator("navigator:browser"); - while (winEnum.hasMoreElements()) { - let win = winEnum.getNext(); - let chatbar = win.document.getElementById("pinnedchats"); - if (!chatbar) + for (let chatbox of this.chatboxes) { + if (chatbox.content.getAttribute("origin") != origin) { continue; - let chats = [c for (c of chatbar.children) if (c.content.getAttribute("origin") == origin)]; - [c.close() for (c of chats)]; - } - - // close all standalone chat windows - winEnum = Services.wm.getEnumerator("Social:Chat"); - while (winEnum.hasMoreElements()) { - let win = winEnum.getNext(); - if (win.closed) - continue; - let chatOrigin = win.document.getElementById("chatter").content.getAttribute("origin"); - if (origin == chatOrigin) - win.close(); + } + chatbox.close(); } }, From 195ece985173c7d58eecd0e5a7cf9b02e01b5e44 Mon Sep 17 00:00:00 2001 From: anirudhgp Date: Sat, 20 Dec 2014 02:45:00 +0100 Subject: [PATCH 13/15] Bug 1079336 - Updated runtime details to show 'unknown (requires ADB Helper 0.4.0 or later)' in WebIDE properties; r=jryans --- browser/devtools/webide/content/runtimedetails.js | 2 +- browser/locales/en-US/chrome/browser/devtools/webide.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/devtools/webide/content/runtimedetails.js b/browser/devtools/webide/content/runtimedetails.js index a3826a8ad5e2..65f513b6b118 100644 --- a/browser/devtools/webide/content/runtimedetails.js +++ b/browser/devtools/webide/content/runtimedetails.js @@ -71,7 +71,7 @@ function CheckLockState() { let sYes = Strings.GetStringFromName("runtimedetails_checkyes"); let sNo = Strings.GetStringFromName("runtimedetails_checkno"); - let sUnknown = Strings.GetStringFromName("runtimedetails_checkunkown"); + let sUnknown = Strings.GetStringFromName("runtimedetails_checkunknown"); let sNotUSB = Strings.GetStringFromName("runtimedetails_notUSBDevice"); flipCertPerfButton.setAttribute("disabled", "true"); diff --git a/browser/locales/en-US/chrome/browser/devtools/webide.properties b/browser/locales/en-US/chrome/browser/devtools/webide.properties index c658c439920b..93805b008bb9 100644 --- a/browser/locales/en-US/chrome/browser/devtools/webide.properties +++ b/browser/locales/en-US/chrome/browser/devtools/webide.properties @@ -65,7 +65,7 @@ addons_status_installing=installing runtimedetails_checkno=no runtimedetails_checkyes=yes -runtimedetails_checkunkown=unknown +runtimedetails_checkunknown=unknown (requires ADB Helper 0.4.0 or later) runtimedetails_notUSBDevice=Not a USB device # Validation status From bf42323805995e15b76ebb5f2f00dbe8685d6b39 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 17 Dec 2014 09:22:00 +0100 Subject: [PATCH 14/15] Bug 1112644 - make timeline tests work on e10s. r=paul --- docshell/test/browser/browser.ini | 8 +- .../browser/browser_timelineMarkers-02.js | 158 +----------------- .../browser/browser_timelineMarkers-03.js | 137 +-------------- .../browser/browser_timelineMarkers-04.js | 89 +--------- .../browser_timelineMarkers-frame-02.js | 95 +++++++++++ .../browser_timelineMarkers-frame-03.js | 91 ++++++++++ .../browser_timelineMarkers-frame-04.js | 27 +++ docshell/test/browser/frame-head.js | 105 ++++++++++++ docshell/test/browser/head.js | 53 ++++++ 9 files changed, 382 insertions(+), 381 deletions(-) create mode 100644 docshell/test/browser/browser_timelineMarkers-frame-02.js create mode 100644 docshell/test/browser/browser_timelineMarkers-frame-03.js create mode 100644 docshell/test/browser/browser_timelineMarkers-frame-04.js create mode 100644 docshell/test/browser/frame-head.js create mode 100644 docshell/test/browser/head.js diff --git a/docshell/test/browser/browser.ini b/docshell/test/browser/browser.ini index 660fa6866f60..b08b5d09a333 100644 --- a/docshell/test/browser/browser.ini +++ b/docshell/test/browser/browser.ini @@ -36,6 +36,11 @@ support-files = print_postdata.sjs test-form_sjis.html timelineMarkers-04.html + browser_timelineMarkers-frame-02.js + browser_timelineMarkers-frame-03.js + browser_timelineMarkers-frame-04.js + head.js + frame-head.js [browser_bug134911.js] skip-if = e10s # Bug ?????? - BrowserSetForcedCharacterSet() in browser.js references docShell @@ -98,8 +103,5 @@ skip-if = e10s [browser_search_notification.js] [browser_timelineMarkers-01.js] [browser_timelineMarkers-02.js] -skip-if = e10s [browser_timelineMarkers-03.js] -skip-if = e10s [browser_timelineMarkers-04.js] -skip-if = e10s diff --git a/docshell/test/browser/browser_timelineMarkers-02.js b/docshell/test/browser/browser_timelineMarkers-02.js index 0539cb06d9d2..e285d09a9031 100644 --- a/docshell/test/browser/browser_timelineMarkers-02.js +++ b/docshell/test/browser/browser_timelineMarkers-02.js @@ -3,9 +3,6 @@ "use strict"; -// Test that the docShell profile timeline API returns the right markers when -// restyles, reflows and paints occur - let URL = '
'; +URL = "data:text/html;charset=utf8," + encodeURIComponent(URL); -let TESTS = [{ - desc: "Changing the width of the test element", - searchFor: "Paint", - setup: function(div) { - div.setAttribute("class", "resize-change-color"); - }, - check: function(markers) { - ok(markers.length > 0, "markers were returned"); - console.log(markers); - info(JSON.stringify(markers.filter(m => m.name == "Paint"))); - ok(markers.some(m => m.name == "Reflow"), "markers includes Reflow"); - ok(markers.some(m => m.name == "Paint"), "markers includes Paint"); - for (let marker of markers.filter(m => m.name == "Paint")) { - // This change should generate at least one rectangle. - ok(marker.rectangles.length >= 1, "marker has one rectangle"); - // One of the rectangles should contain the div. - ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100))); - } - ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); - } -}, { - desc: "Changing the test element's background color", - searchFor: "Paint", - setup: function(div) { - div.setAttribute("class", "change-color"); - }, - check: function(markers) { - ok(markers.length > 0, "markers were returned"); - ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow"); - ok(markers.some(m => m.name == "Paint"), "markers includes Paint"); - for (let marker of markers.filter(m => m.name == "Paint")) { - // This change should generate at least one rectangle. - ok(marker.rectangles.length >= 1, "marker has one rectangle"); - // One of the rectangles should contain the div. - ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50))); - } - ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); - } -}, { - desc: "Changing the test element's classname", - searchFor: "Paint", - setup: function(div) { - div.setAttribute("class", "change-color add-class"); - }, - check: function(markers) { - ok(markers.length > 0, "markers were returned"); - ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow"); - ok(!markers.some(m => m.name == "Paint"), "markers doesn't include Paint"); - ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); - } -}, { - desc: "sync console.time/timeEnd", - searchFor: "ConsoleTime", - setup: function(div, docShell) { - content.console.time("FOOBAR"); - content.console.timeEnd("FOOBAR"); - let markers = docShell.popProfileTimelineMarkers(); - is(markers.length, 1, "Got one marker"); - is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker"); - is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail"); - content.console.time("FOO"); - content.setTimeout(() => { - content.console.time("BAR"); - content.setTimeout(() => { - content.console.timeEnd("FOO"); - content.console.timeEnd("BAR"); - }, 100); - }, 100); - }, - check: function(markers) { - is(markers.length, 2, "Got 2 markers"); - is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker"); - is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail"); - is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker"); - is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail"); - } -}]; - -let test = Task.async(function*() { - waitForExplicitFinish(); - - yield openUrl("data:text/html;charset=utf8," + encodeURIComponent(URL)); - - let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - - let div = content.document.querySelector("div"); - - info("Start recording"); - docShell.recordProfileTimelineMarkers = true; - - for (let {desc, searchFor, setup, check} of TESTS) { - - info("Running test: " + desc); - - info("Flushing the previous markers if any"); - docShell.popProfileTimelineMarkers(); - - info("Running the test setup function"); - let onMarkers = waitForMarkers(docShell, searchFor); - setup(div, docShell); - info("Waiting for new markers on the docShell"); - let markers = yield onMarkers; - - info("Running the test check function"); - check(markers); - } - - info("Stop recording"); - docShell.recordProfileTimelineMarkers = false; - - gBrowser.removeCurrentTab(); - finish(); -}); - -function openUrl(url) { - return new Promise(function(resolve, reject) { - window.focus(); - - let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url); - let linkedBrowser = tab.linkedBrowser; - - linkedBrowser.addEventListener("load", function onload() { - linkedBrowser.removeEventListener("load", onload, true); - resolve(tab); - }, true); - }); -} - -function waitForMarkers(docshell, searchFor) { - return new Promise(function(resolve, reject) { - let waitIterationCount = 0; - let maxWaitIterationCount = 10; // Wait for 2sec maximum - let markers = []; - - let interval = setInterval(() => { - let newMarkers = docshell.popProfileTimelineMarkers(); - markers = [...markers, ...newMarkers]; - if (newMarkers.some(m => m.name == searchFor) || - waitIterationCount > maxWaitIterationCount) { - clearInterval(interval); - resolve(markers); - } - waitIterationCount++; - }, 200); - }); -} - -function rectangleContains(rect, x, y, width, height) { - return rect.x <= x && rect.y <= y && rect.width >= width && - rect.height >= height; -} +let test = makeTimelineTest("browser_timelineMarkers-frame-02.js", URL); diff --git a/docshell/test/browser/browser_timelineMarkers-03.js b/docshell/test/browser/browser_timelineMarkers-03.js index c511525b10fd..379e5dfce659 100644 --- a/docshell/test/browser/browser_timelineMarkers-03.js +++ b/docshell/test/browser/browser_timelineMarkers-03.js @@ -3,139 +3,6 @@ "use strict"; -// Test that the docShell profile timeline API returns the right -// markers for DOM events. +let URL = "data:text/html;charset=utf-8,

Test page

"; -let TESTS = [{ - desc: "Event dispatch with single handler", - setup: function() { - content.document.body.addEventListener("dog", - function(e) { console.log("hi"); }, - true); - content.document.body.dispatchEvent(new Event("dog")); - }, - check: function(markers) { - is(markers.length, 1, "Got 1 marker"); - is(markers[0].type, "dog", "Got dog event name"); - is(markers[0].eventPhase, 2, "Got phase 2"); - } -}, { - desc: "Event dispatch with a second handler", - setup: function() { - content.document.body.addEventListener("dog", - function(e) { console.log("hi"); }, - false); - content.document.body.dispatchEvent(new Event("dog")); - }, - check: function(markers) { - is(markers.length, 2, "Got 2 markers"); - } -}, { - desc: "Event targeted at child", - setup: function() { - let child = content.document.body.firstElementChild; - child.addEventListener("dog", function(e) { }); - child.dispatchEvent(new Event("dog")); - }, - check: function(markers) { - is(markers.length, 2, "Got 2 markers"); - is(markers[0].eventPhase, 1, "Got phase 1 marker"); - is(markers[1].eventPhase, 2, "Got phase 2 marker"); - } -}, { - desc: "Event dispatch on a new document", - setup: function() { - let doc = content.document.implementation.createHTMLDocument("doc"); - let p = doc.createElement("p"); - p.innerHTML = "inside"; - doc.body.appendChild(p); - - p.addEventListener("zebra", function(e) {console.log("hi");}); - p.dispatchEvent(new Event("zebra")); - }, - check: function(markers) { - is(markers.length, 1, "Got 1 marker"); - } -}, { - desc: "Event dispatch on window", - setup: function() { - let doc = content.window.addEventListener("aardvark", function(e) { - console.log("I like ants!"); - }); - - content.window.dispatchEvent(new Event("aardvark")); - }, - check: function(markers) { - is(markers.length, 1, "Got 1 marker"); - } -}]; - -let test = Task.async(function*() { - waitForExplicitFinish(); - - yield openUrl("data:text/html;charset=utf-8,

Test page

"); - - let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - - info("Start recording"); - docShell.recordProfileTimelineMarkers = true; - - for (let {desc, setup, check} of TESTS) { - - info("Running test: " + desc); - - info("Flushing the previous markers if any"); - docShell.popProfileTimelineMarkers(); - - info("Running the test setup function"); - let onMarkers = waitForMarkers(docShell); - setup(); - info("Waiting for new markers on the docShell"); - let markers = yield onMarkers; - - info("Running the test check function"); - check(markers.filter(m => m.name == "DOMEvent")); - } - - info("Stop recording"); - docShell.recordProfileTimelineMarkers = false; - - gBrowser.removeCurrentTab(); - finish(); -}); - -function openUrl(url) { - return new Promise(function(resolve, reject) { - window.focus(); - - let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url); - let linkedBrowser = tab.linkedBrowser; - - linkedBrowser.addEventListener("load", function onload() { - linkedBrowser.removeEventListener("load", onload, true); - resolve(tab); - }, true); - }); -} - -function waitForMarkers(docshell) { - return new Promise(function(resolve, reject) { - let waitIterationCount = 0; - let maxWaitIterationCount = 10; // Wait for 2sec maximum - - let interval = setInterval(() => { - let markers = docshell.popProfileTimelineMarkers(); - if (markers.length > 0) { - clearInterval(interval); - resolve(markers); - } - if (waitIterationCount > maxWaitIterationCount) { - clearInterval(interval); - resolve([]); - } - waitIterationCount++; - }, 200); - }); -} +let test = makeTimelineTest("browser_timelineMarkers-frame-03.js", URL); diff --git a/docshell/test/browser/browser_timelineMarkers-04.js b/docshell/test/browser/browser_timelineMarkers-04.js index dfb99d189ba7..70196e6a6145 100644 --- a/docshell/test/browser/browser_timelineMarkers-04.js +++ b/docshell/test/browser/browser_timelineMarkers-04.js @@ -3,91 +3,6 @@ "use strict"; -// Test that the docShell profile timeline API returns the right -// markers for XMLHttpRequest events. +const URL = "http://mochi.test:8888/browser/docshell/test/browser/timelineMarkers-04.html"; -let TESTS = [{ - desc: "Event dispatch from XMLHttpRequest", - setup: function() { - content.dispatchEvent(new Event("dog")); - }, - check: function(markers) { - // One subtlety here is that we have five events: the event we - // inject in "setup", plus the four state transition events. The - // first state transition is reported synchronously and so should - // show up as a nested marker. - is(markers.length, 5, "Got 5 markers"); - } -}]; - -let test = Task.async(function*() { - waitForExplicitFinish(); - - const testDir = "http://mochi.test:8888/browser/docshell/test/browser/"; - const testName = "timelineMarkers-04.html"; - - yield openUrl(testDir + testName); - - let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - - info("Start recording"); - docShell.recordProfileTimelineMarkers = true; - - for (let {desc, setup, check} of TESTS) { - - info("Running test: " + desc); - - info("Flushing the previous markers if any"); - docShell.popProfileTimelineMarkers(); - - info("Running the test setup function"); - let onMarkers = waitForDOMMarkers(docShell, 5); - setup(); - info("Waiting for new markers on the docShell"); - let markers = yield onMarkers; - - info("Running the test check function"); - check(markers); - } - - info("Stop recording"); - docShell.recordProfileTimelineMarkers = false; - - gBrowser.removeCurrentTab(); - finish(); -}); - -function openUrl(url) { - return new Promise(function(resolve, reject) { - window.focus(); - - let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url); - let linkedBrowser = tab.linkedBrowser; - - linkedBrowser.addEventListener("load", function onload() { - linkedBrowser.removeEventListener("load", onload, true); - resolve(tab); - }, true); - }); -} - -function waitForDOMMarkers(docshell, numExpected) { - return new Promise(function(resolve, reject) { - let waitIterationCount = 0; - let maxWaitIterationCount = 10; // Wait for 2sec maximum - let markers = []; - - let interval = setInterval(() => { - let newMarkers = docshell.popProfileTimelineMarkers(); - markers = [...markers, ...newMarkers.filter(m => m.name == "DOMEvent")]; - if (markers.length >= numExpected - || waitIterationCount > maxWaitIterationCount) { - clearInterval(interval); - resolve(markers); - } - waitIterationCount++; - }, 200); - }); -} +let test = makeTimelineTest("browser_timelineMarkers-frame-04.js", URL); diff --git a/docshell/test/browser/browser_timelineMarkers-frame-02.js b/docshell/test/browser/browser_timelineMarkers-frame-02.js new file mode 100644 index 000000000000..82039c624881 --- /dev/null +++ b/docshell/test/browser/browser_timelineMarkers-frame-02.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that the docShell profile timeline API returns the right markers when +// restyles, reflows and paints occur + +function rectangleContains(rect, x, y, width, height) { + return rect.x <= x && rect.y <= y && rect.width >= width && + rect.height >= height; +} + +let TESTS = [{ + desc: "Changing the width of the test element", + searchFor: "Paint", + setup: function(docShell) { + let div = content.document.querySelector("div"); + div.setAttribute("class", "resize-change-color"); + }, + check: function(markers) { + ok(markers.length > 0, "markers were returned"); + console.log(markers); + info(JSON.stringify(markers.filter(m => m.name == "Paint"))); + ok(markers.some(m => m.name == "Reflow"), "markers includes Reflow"); + ok(markers.some(m => m.name == "Paint"), "markers includes Paint"); + for (let marker of markers.filter(m => m.name == "Paint")) { + // This change should generate at least one rectangle. + ok(marker.rectangles.length >= 1, "marker has one rectangle"); + // One of the rectangles should contain the div. + ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100))); + } + ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); + } +}, { + desc: "Changing the test element's background color", + searchFor: "Paint", + setup: function(docShell) { + let div = content.document.querySelector("div"); + div.setAttribute("class", "change-color"); + }, + check: function(markers) { + ok(markers.length > 0, "markers were returned"); + ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow"); + ok(markers.some(m => m.name == "Paint"), "markers includes Paint"); + for (let marker of markers.filter(m => m.name == "Paint")) { + // This change should generate at least one rectangle. + ok(marker.rectangles.length >= 1, "marker has one rectangle"); + // One of the rectangles should contain the div. + ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50))); + } + ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); + } +}, { + desc: "Changing the test element's classname", + searchFor: "Paint", + setup: function(docShell) { + let div = content.document.querySelector("div"); + div.setAttribute("class", "change-color add-class"); + }, + check: function(markers) { + ok(markers.length > 0, "markers were returned"); + ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow"); + ok(!markers.some(m => m.name == "Paint"), "markers doesn't include Paint"); + ok(markers.some(m => m.name == "Styles"), "markers includes Restyle"); + } +}, { + desc: "sync console.time/timeEnd", + searchFor: "ConsoleTime", + setup: function(docShell) { + content.console.time("FOOBAR"); + content.console.timeEnd("FOOBAR"); + let markers = docShell.popProfileTimelineMarkers(); + is(markers.length, 1, "Got one marker"); + is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker"); + is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail"); + content.console.time("FOO"); + content.setTimeout(() => { + content.console.time("BAR"); + content.setTimeout(() => { + content.console.timeEnd("FOO"); + content.console.timeEnd("BAR"); + }, 100); + }, 100); + }, + check: function(markers) { + is(markers.length, 2, "Got 2 markers"); + is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker"); + is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail"); + is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker"); + is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail"); + } +}]; + +timelineContentTest(TESTS); diff --git a/docshell/test/browser/browser_timelineMarkers-frame-03.js b/docshell/test/browser/browser_timelineMarkers-frame-03.js new file mode 100644 index 000000000000..a59f92172baa --- /dev/null +++ b/docshell/test/browser/browser_timelineMarkers-frame-03.js @@ -0,0 +1,91 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that the docShell profile timeline API returns the right +// markers for DOM events. + +let TESTS = [{ + desc: "Event dispatch with single handler", + searchFor: 'DOMEvent', + setup: function(docShell) { + content.document.body.addEventListener("dog", + function(e) { console.log("hi"); }, + true); + content.document.body.dispatchEvent(new content.Event("dog")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == 'DOMEvent'); + is(markers.length, 1, "Got 1 marker"); + is(markers[0].type, "dog", "Got dog event name"); + is(markers[0].eventPhase, 2, "Got phase 2"); + } +}, { + desc: "Event dispatch with a second handler", + searchFor: function(markers) { + return markers.filter(m => m.name == 'DOMEvent').length >= 2; + }, + setup: function(docShell) { + content.document.body.addEventListener("dog", + function(e) { console.log("hi"); }, + false); + content.document.body.dispatchEvent(new content.Event("dog")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == 'DOMEvent'); + is(markers.length, 2, "Got 2 markers"); + } +}, { + desc: "Event targeted at child", + searchFor: function(markers) { + return markers.filter(m => m.name == 'DOMEvent').length >= 2; + }, + setup: function(docShell) { + let child = content.document.body.firstElementChild; + child.addEventListener("dog", function(e) { }); + child.dispatchEvent(new content.Event("dog")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == 'DOMEvent'); + is(markers.length, 2, "Got 2 markers"); + is(markers[0].eventPhase, 1, "Got phase 1 marker"); + is(markers[1].eventPhase, 2, "Got phase 2 marker"); + } +}, { + desc: "Event dispatch on a new document", + searchFor: function(markers) { + return markers.filter(m => m.name == 'DOMEvent').length >= 2; + }, + setup: function(docShell) { + let doc = content.document.implementation.createHTMLDocument("doc"); + let p = doc.createElement("p"); + p.innerHTML = "inside"; + doc.body.appendChild(p); + + p.addEventListener("zebra", function(e) {console.log("hi");}); + p.dispatchEvent(new content.Event("zebra")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == 'DOMEvent'); + is(markers.length, 1, "Got 1 marker"); + } +}, { + desc: "Event dispatch on window", + searchFor: function(markers) { + return markers.filter(m => m.name == 'DOMEvent').length >= 2; + }, + setup: function(docShell) { + let doc = content.window.addEventListener("aardvark", function(e) { + console.log("I like ants!"); + }); + + content.window.dispatchEvent(new content.Event("aardvark")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == 'DOMEvent'); + is(markers.length, 1, "Got 1 marker"); + } +}]; + +timelineContentTest(TESTS); diff --git a/docshell/test/browser/browser_timelineMarkers-frame-04.js b/docshell/test/browser/browser_timelineMarkers-frame-04.js new file mode 100644 index 000000000000..efcb00ed3f25 --- /dev/null +++ b/docshell/test/browser/browser_timelineMarkers-frame-04.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that the docShell profile timeline API returns the right +// markers for XMLHttpRequest events. + +let TESTS = [{ + desc: "Event dispatch from XMLHttpRequest", + searchFor: function(markers) { + return markers.filter(m => m.name == "DOMEvent").length >= 5; + }, + setup: function(docShell) { + content.dispatchEvent(new content.Event("dog")); + }, + check: function(markers) { + markers = markers.filter(m => m.name == "DOMEvent"); + // One subtlety here is that we have five events: the event we + // inject in "setup", plus the four state transition events. The + // first state transition is reported synchronously and so should + // show up as a nested marker. + is(markers.length, 5, "Got 5 markers"); + } +}]; + +timelineContentTest(TESTS); diff --git a/docshell/test/browser/frame-head.js b/docshell/test/browser/frame-head.js new file mode 100644 index 000000000000..64a8b36cdd5c --- /dev/null +++ b/docshell/test/browser/frame-head.js @@ -0,0 +1,105 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Functions that are automatically loaded as frame scripts for +// timeline tests. + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; +let { Task } = Cu.import("resource://gre/modules/Task.jsm", {}); +let { Promise } = Cu.import('resource://gre/modules/Promise.jsm', {}); + +// Functions that look like mochitest functions but forward to the +// browser process. + +this.ok = function(value, message) { + sendAsyncMessage("browser:test:ok", { + value: !!value, + message: message}); +} + +this.is = function(v1, v2, message) { + ok(v1 == v2, message); +} + +this.info = function(message) { + sendAsyncMessage("browser:test:info", {message: message}); +} + +this.finish = function() { + sendAsyncMessage("browser:test:finish"); +} + +/* Start a task that runs some timeline tests in the ordinary way. + * + * @param array tests + * The tests to run. This is an array where each element + * is of the form { desc, searchFor, setup, check }. + * + * desc is the test description, a string. + * searchFor is a string or a function + * If a string, then when a marker with this name is + * found, marker-reading is stopped. + * If a function, then the accumulated marker array is + * passed to it, and marker reading stops when it returns + * true. + * setup is a function that takes the docshell as an argument. + * It should start the test. + * check is a function that takes an array of markers + * as an argument and checks the results of the test. + */ +this.timelineContentTest = function(tests) { + Task.spawn(function*() { + let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + + info("Start recording"); + docShell.recordProfileTimelineMarkers = true; + + for (let {desc, searchFor, setup, check} of tests) { + + info("Running test: " + desc); + + info("Flushing the previous markers if any"); + docShell.popProfileTimelineMarkers(); + + info("Running the test setup function"); + let onMarkers = timelineWaitForMarkers(docShell, searchFor); + setup(docShell); + info("Waiting for new markers on the docShell"); + let markers = yield onMarkers; + + info("Running the test check function"); + check(markers); + } + + info("Stop recording"); + docShell.recordProfileTimelineMarkers = false; + finish(); + }); +} + +function timelineWaitForMarkers(docshell, searchFor) { + if (typeof(searchFor) == "string") { + let f = function (markers) { + return markers.some(m => m.name == searchFor); + }; + searchFor = f; + } + + return new Promise(function(resolve, reject) { + let waitIterationCount = 0; + let maxWaitIterationCount = 10; // Wait for 2sec maximum + let markers = []; + + let interval = content.setInterval(() => { + let newMarkers = docshell.popProfileTimelineMarkers(); + markers = [...markers, ...newMarkers]; + if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) { + content.clearInterval(interval); + resolve(markers); + } + waitIterationCount++; + }, 200); + }); +} diff --git a/docshell/test/browser/head.js b/docshell/test/browser/head.js new file mode 100644 index 000000000000..7a22f229edcb --- /dev/null +++ b/docshell/test/browser/head.js @@ -0,0 +1,53 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Helper function for timeline tests. Returns an async task that is + * suitable for use as a particular timeline test. + * @param string frameScriptName + * Base name of the frame script file. + * @param string url + * URL to load. + */ +function makeTimelineTest(frameScriptName, url) { + info("in timelineTest"); + return Task.async(function*() { + info("in in timelineTest"); + waitForExplicitFinish(); + + yield timelineTestOpenUrl(url); + + const here = "chrome://mochitests/content/browser/docshell/test/browser/"; + + let mm = gBrowser.selectedBrowser.messageManager; + mm.loadFrameScript(here + "frame-head.js", false); + mm.loadFrameScript(here + frameScriptName, false); + + // Set up some listeners so that timeline tests running in the + // content process can forward their results to the main process. + mm.addMessageListener("browser:test:ok", function(message) { + ok(message.data.value, message.data.message); + }); + mm.addMessageListener("browser:test:info", function(message) { + info(message.data.message); + }); + mm.addMessageListener("browser:test:finish", function(ignore) { + finish(); + gBrowser.removeCurrentTab(); + }); + }); +} + +/* Open a URL for a timeline test. */ +function timelineTestOpenUrl(url) { + return new Promise(function(resolve, reject) { + window.focus(); + + let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url); + let linkedBrowser = tab.linkedBrowser; + + linkedBrowser.addEventListener("load", function onload() { + linkedBrowser.removeEventListener("load", onload, true); + resolve(tab); + }, true); + }); +} From 45b84ba902e57a5e10edfad6cd4ce15d358b7df3 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 22 Dec 2014 02:53:00 +0100 Subject: [PATCH 15/15] Bug 1071357 - Need yield against checkItem and promiseAsyncUpdates after each importFromFile/exportToFile in test_bookmarks_json.js. r=mak --- .../places/tests/unit/test_bookmarks_json.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/toolkit/components/places/tests/unit/test_bookmarks_json.js b/toolkit/components/places/tests/unit/test_bookmarks_json.js index a1299e612994..9acaedb84d6b 100644 --- a/toolkit/components/places/tests/unit/test_bookmarks_json.js +++ b/toolkit/components/places/tests/unit/test_bookmarks_json.js @@ -78,6 +78,7 @@ add_task(function test_import_bookmarks() { let bookmarksFile = OS.Path.join(do_get_cwd().path, "bookmarks.json"); yield BookmarkJSONUtils.importFromFile(bookmarksFile, true); + yield promiseAsyncUpdates(); yield testImportedBookmarks(); }); @@ -85,19 +86,24 @@ add_task(function test_export_bookmarks() { bookmarksExportedFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.json"); yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile); + yield promiseAsyncUpdates(); }); add_task(function test_import_exported_bookmarks() { remove_all_bookmarks(); yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true); + yield promiseAsyncUpdates(); yield testImportedBookmarks(); }); add_task(function test_import_ontop() { remove_all_bookmarks(); yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true); + yield promiseAsyncUpdates(); yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile); + yield promiseAsyncUpdates(); yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true); + yield promiseAsyncUpdates(); yield testImportedBookmarks(); }); @@ -202,7 +208,9 @@ function checkItem(aExpected, aNode) { folder.containerOpen = true; do_check_eq(folder.childCount, aExpected.children.length); - aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index))); + for (let index = 0; index < aExpected.children.length; index++) { + yield checkItem(aExpected.children[index], folder.getChild(index)); + } folder.containerOpen = false; break;