merge fx-team to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 21 Sep 2015 13:38:22 +0200
changeset 297784 98231abe637676311a0df1e0a5da85c94adce36d
parent 297777 fc686ad7691b0b0654b20fc53bec0dfcd621fb6b (current diff)
parent 297783 adfd7cff5007156394022d56ca7d7c9f84cfba5d (diff)
child 297807 7cd926385096475bda3eb601e0ff109f45c0498a
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge fx-team to mozilla-central a=merge
browser/components/translation/translation.manifest
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -209,20 +209,16 @@ var gFxAccounts = {
     panel.hidden = false;
     panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
   },
 
   showSyncStartedDoorhanger: function () {
     this.showDoorhanger("sync-start-panel");
   },
 
-  showSyncFailedDoorhanger: function () {
-    this.showDoorhanger("sync-error-panel");
-  },
-
   updateUI: function () {
     this.updateAppMenuItem();
     this.updateMigrationNotification();
   },
 
   // Note that updateAppMenuItem() returns a Promise that's only used by tests.
   updateAppMenuItem: function () {
     if (this._migrationInfo) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -444,38 +444,16 @@
           <description id="sync-start-panel-title"
                        value="&syncStartPanel2.heading;"/>
           <description id="sync-start-panel-subtitle"
                        value="&syncStartPanel2.subTitle;"/>
         </vbox>
       </hbox>
     </panel>
 
-    <!-- Sync Error Panel -->
-    <panel id="sync-error-panel" class="sync-panel" type="arrow" hidden="true"
-           noautofocus="true" onclick="this.hidePopup();"
-           flip="slide">
-      <hbox class="sync-panel-outer">
-        <image class="sync-panel-icon"/>
-        <vbox class="sync-panel-inner">
-          <description id="sync-error-panel-title"
-                       value="&syncErrorPanel.heading;"/>
-          <description id="sync-error-panel-subtitle"
-                       value="&syncErrorPanel.subTitle;"/>
-          <hbox class="sync-panel-button-box">
-            <spacer flex="1"/>
-            <button class="sync-panel-button"
-                    label="&syncErrorPanel.signInButton.label;"
-                    accesskey="&syncErrorPanel.signInButton.accesskey;"
-                    onclick="gFxAccounts.openSignInAgainPage();"/>
-          </hbox>
-        </vbox>
-      </hbox>
-    </panel>
-
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
 
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
 
     <tooltip id="back-button-tooltip">
       <label class="tooltip-label" value="&backButton.tooltip;"/>
 #ifdef XP_MACOSX
--- a/browser/components/loop/content/css/panel.css
+++ b/browser/components/loop/content/css/panel.css
@@ -602,99 +602,16 @@ html[dir="rtl"] .room-entry-context-acti
   display: none;
 }
 
 .room-entry-context-item > a > img {
   height: 16px;
   width: 16px;
 }
 
-/* Buttons */
-
-.button-group {
-  display: flex;
-  flex-direction: row;
-  width: 100%;
-  padding-top: 6px;
-}
-
-.button-group > .button {
-  flex: 1;
-  margin: 0 5px;
-  min-height: 3rem;
-  font-size: 1.2rem;
-  line-height: 1rem;
-  font-weight: 300;
-  border-radius: 4px;
-}
-
-.button-group > .button:first-child {
-  -moz-margin-start: 0;
-}
-
-.button-group > .button:last-child {
-  -moz-margin-end: 0;
-}
-
-.button {
-  padding: 2px 5px;
-  background-color: #fbfbfb;
-  color: #333;
-  border-radius: 2px;
-  min-height: 26px;
-  font-size: 1.2rem;
-  line-height: 1.2rem;
-  border: none;
-}
-
-.button:hover {
-  background-color: #ebebeb;
-}
-
-.button:active {
-  background-color: #ccc;
-  color: #fff;
-}
-
-.button.button-accept {
-  background-color: #00a9dc;
-  color: #fff;
-}
-
-.button.button-accept:hover,
-.button.button-accept:hover:active {
-  background-color: #5cccee;
-  color: #fff;
-}
-
-.button.button-cancel {
-  background-color: #ebebeb;
-  border: 0;
-  color: #000;
-  width: 105px; /* based on fixed width of Cancel button from mockup */
-  flex: 0 0 auto;
-}
-
-.button.button-cancel:hover,
-.button.button-cancel:hover:active {
-  background-color: #dcd6d6;
-  color: #000;
-}
-
-.button.button-cancel:disabled {
-  background-color: #ebebeb;
-  color: #c3c3c3;
-}
-
-.button.button-accept:active {
-  background-color: #3aa689;
-  border-color: #3aa689;
-  color: #fff;
-}
-
 .button-close {
   background-color: transparent;
   background-image: url(../shared/img/icons-10x10.svg#close);
   background-repeat: no-repeat;
   background-size: 8px 8px;
   border: none;
   padding: 0;
   height: 8px;
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -714,16 +714,17 @@ loop.conversationViews = (function(mozL1
             useDesktopPaths: true}, 
             React.createElement(loop.shared.views.ConversationToolbar, {
               audio: this.props.audio, 
               dispatcher: this.props.dispatcher, 
               hangup: this.hangup, 
               mozLoop: this.props.mozLoop, 
               publishStream: this.publishStream, 
               settingsMenuItems: settingsMenuItems, 
+              show: true, 
               video: this.props.video})
           )
         )
       );
     }
   });
 
   /**
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -714,16 +714,17 @@ loop.conversationViews = (function(mozL1
             useDesktopPaths={true}>
             <loop.shared.views.ConversationToolbar
               audio={this.props.audio}
               dispatcher={this.props.dispatcher}
               hangup={this.hangup}
               mozLoop={this.props.mozLoop}
               publishStream={this.publishStream}
               settingsMenuItems={settingsMenuItems}
+              show={true}
               video={this.props.video} />
           </sharedViews.MediaLayoutView>
         </div>
       );
     }
   });
 
   /**
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -970,17 +970,17 @@ loop.panel = (function(_, mozL10n) {
         hide: !hostname ||
           !this.props.mozLoop.getLoopPref("contextInConversations.enabled")
       });
 
       return (
         React.createElement("div", {className: "new-room-view"}, 
           React.createElement("div", {className: contextClasses}, 
             React.createElement(Checkbox, {checked: this.state.checked, 
-                      label: mozL10n.get("context_inroom_label"), 
+                      label: mozL10n.get("context_inroom_label2"), 
                       onChange: this.onCheckboxChange}), 
             React.createElement(sharedViews.ContextUrlView, {
               allowClick: false, 
               description: this.state.description, 
               showContextTitle: false, 
               thumbnail: this.state.previewImage, 
               url: this.state.url, 
               useDesktopPaths: true})
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -970,17 +970,17 @@ loop.panel = (function(_, mozL10n) {
         hide: !hostname ||
           !this.props.mozLoop.getLoopPref("contextInConversations.enabled")
       });
 
       return (
         <div className="new-room-view">
           <div className={contextClasses}>
             <Checkbox checked={this.state.checked}
-                      label={mozL10n.get("context_inroom_label")}
+                      label={mozL10n.get("context_inroom_label2")}
                       onChange={this.onCheckboxChange} />
             <sharedViews.ContextUrlView
               allowClick={false}
               description={this.state.description}
               showContextTitle={false}
               thumbnail={this.state.previewImage}
               url={this.state.url}
               useDesktopPaths={true} />
--- a/browser/components/loop/content/js/roomViews.js
+++ b/browser/components/loop/content/js/roomViews.js
@@ -444,35 +444,16 @@ loop.roomViews = (function(mozL10n) {
       }
 
       var mozLoop = this.props.mozLoop;
       mozLoop.openURL(url.location);
 
       mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_CLICK", 1);
     },
 
-    handleCheckboxChange: function(state) {
-      if (state.checked) {
-        // The checkbox was checked, prefill the fields with the values available
-        // in `availableContext`.
-        var context = this.state.availableContext;
-        this.setState({
-          newRoomURL: context.url,
-          newRoomDescription: context.description,
-          newRoomThumbnail: context.previewImage
-        });
-      } else {
-        this.setState({
-          newRoomURL: "",
-          newRoomDescription: "",
-          newRoomThumbnail: ""
-        });
-      }
-    },
-
     handleFormSubmit: function(event) {
       event && event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.UpdateRoomContext({
         roomToken: this.props.roomData.roomToken,
         newRoomName: this.state.newRoomName,
         newRoomURL: this.state.newRoomURL,
         newRoomDescription: this.state.newRoomDescription,
@@ -511,37 +492,23 @@ loop.roomViews = (function(mozL10n) {
 
       var url = this._getURL();
       var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
       var urlDescription = url && url.description || "";
       var location = url && url.location || "";
 
       var cx = React.addons.classSet;
       var availableContext = this.state.availableContext;
-      // The checkbox shows as checked when there's already context data
-      // attached to this room.
-      var checked = !!urlDescription;
-      var checkboxLabel = urlDescription || (availableContext && availableContext.url ?
-        availableContext.description : "");
-
       return (
         React.createElement("div", {className: "room-context"}, 
           React.createElement("p", {className: cx({"error": !!this.props.error,
                             "error-display-area": true})}, 
             mozL10n.get("rooms_change_failed_label")
           ), 
-          React.createElement("div", {className: "room-context-label"}, mozL10n.get("context_inroom_label")), 
-          React.createElement(sharedViews.Checkbox, {
-            additionalClass: cx({ hide: !checkboxLabel }), 
-            checked: checked, 
-            disabled: checked, 
-            label: checkboxLabel, 
-            onChange: this.handleCheckboxChange, 
-            useEllipsis: true, 
-            value: location}), 
+          React.createElement("h2", {className: "room-context-header"}, mozL10n.get("context_inroom_header")), 
           React.createElement("form", {onSubmit: this.handleFormSubmit}, 
             React.createElement("input", {className: "room-context-name", 
               maxLength: this.maxRoomNameLength, 
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: mozL10n.get("context_edit_name_placeholder"), 
               type: "text", 
               valueLink: this.linkState("newRoomName")}), 
             React.createElement("input", {className: "room-context-url", 
@@ -549,26 +516,27 @@ loop.roomViews = (function(mozL10n) {
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: "https://", 
               type: "text", 
               valueLink: this.linkState("newRoomURL")}), 
             React.createElement("textarea", {className: "room-context-comments", 
               onKeyDown: this.handleTextareaKeyDown, 
               placeholder: mozL10n.get("context_edit_comments_placeholder"), 
               rows: "2", type: "text", 
-              valueLink: this.linkState("newRoomDescription")})
-          ), 
-          React.createElement("button", {className: "btn btn-info", 
-                  disabled: this.props.savingContext, 
-                  onClick: this.handleFormSubmit}, 
-            mozL10n.get("context_save_label2")
-          ), 
-          React.createElement("button", {className: "room-context-btn-close", 
-                  onClick: this.handleCloseClick, 
-                  title: mozL10n.get("cancel_button")})
+              valueLink: this.linkState("newRoomDescription")}), 
+            React.createElement(sharedViews.ButtonGroup, null, 
+              React.createElement(sharedViews.Button, {additionalClass: "button-cancel", 
+                caption: mozL10n.get("context_cancel_label"), 
+                onClick: this.handleCloseClick}), 
+              React.createElement(sharedViews.Button, {additionalClass: "button-accept", 
+                caption: mozL10n.get("context_done_label"), 
+                disabled: this.props.savingContext, 
+                onClick: this.handleFormSubmit})
+            )
+          )
         )
       );
     }
   });
 
   /**
    * Desktop room conversation view.
    */
@@ -814,16 +782,17 @@ loop.roomViews = (function(mozL10n) {
                 React.createElement(sharedViews.ConversationToolbar, {
                   audio: {enabled: !this.state.audioMuted, visible: true}, 
                   dispatcher: this.props.dispatcher, 
                   hangup: this.leaveRoom, 
                   mozLoop: this.props.mozLoop, 
                   publishStream: this.publishStream, 
                   screenShare: screenShareData, 
                   settingsMenuItems: settingsMenuItems, 
+                  show: !shouldRenderEditContextView, 
                   video: {enabled: !this.state.videoMuted, visible: true}}), 
                 React.createElement(DesktopRoomInvitationView, {
                   dispatcher: this.props.dispatcher, 
                   error: this.state.error, 
                   mozLoop: this.props.mozLoop, 
                   onAddContextClick: this.handleAddContextClick, 
                   onEditContextClose: this.handleEditContextClose, 
                   roomData: roomData, 
--- a/browser/components/loop/content/js/roomViews.jsx
+++ b/browser/components/loop/content/js/roomViews.jsx
@@ -444,35 +444,16 @@ loop.roomViews = (function(mozL10n) {
       }
 
       var mozLoop = this.props.mozLoop;
       mozLoop.openURL(url.location);
 
       mozLoop.telemetryAddValue("LOOP_ROOM_CONTEXT_CLICK", 1);
     },
 
-    handleCheckboxChange: function(state) {
-      if (state.checked) {
-        // The checkbox was checked, prefill the fields with the values available
-        // in `availableContext`.
-        var context = this.state.availableContext;
-        this.setState({
-          newRoomURL: context.url,
-          newRoomDescription: context.description,
-          newRoomThumbnail: context.previewImage
-        });
-      } else {
-        this.setState({
-          newRoomURL: "",
-          newRoomDescription: "",
-          newRoomThumbnail: ""
-        });
-      }
-    },
-
     handleFormSubmit: function(event) {
       event && event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.UpdateRoomContext({
         roomToken: this.props.roomData.roomToken,
         newRoomName: this.state.newRoomName,
         newRoomURL: this.state.newRoomURL,
         newRoomDescription: this.state.newRoomDescription,
@@ -511,37 +492,23 @@ loop.roomViews = (function(mozL10n) {
 
       var url = this._getURL();
       var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
       var urlDescription = url && url.description || "";
       var location = url && url.location || "";
 
       var cx = React.addons.classSet;
       var availableContext = this.state.availableContext;
-      // The checkbox shows as checked when there's already context data
-      // attached to this room.
-      var checked = !!urlDescription;
-      var checkboxLabel = urlDescription || (availableContext && availableContext.url ?
-        availableContext.description : "");
-
       return (
         <div className="room-context">
           <p className={cx({"error": !!this.props.error,
                             "error-display-area": true})}>
             {mozL10n.get("rooms_change_failed_label")}
           </p>
-          <div className="room-context-label">{mozL10n.get("context_inroom_label")}</div>
-          <sharedViews.Checkbox
-            additionalClass={cx({ hide: !checkboxLabel })}
-            checked={checked}
-            disabled={checked}
-            label={checkboxLabel}
-            onChange={this.handleCheckboxChange}
-            useEllipsis={true}
-            value={location} />
+          <h2 className="room-context-header">{mozL10n.get("context_inroom_header")}</h2>
           <form onSubmit={this.handleFormSubmit}>
             <input className="room-context-name"
               maxLength={this.maxRoomNameLength}
               onKeyDown={this.handleTextareaKeyDown}
               placeholder={mozL10n.get("context_edit_name_placeholder")}
               type="text"
               valueLink={this.linkState("newRoomName")} />
             <input className="room-context-url"
@@ -550,25 +517,26 @@ loop.roomViews = (function(mozL10n) {
               placeholder="https://"
               type="text"
               valueLink={this.linkState("newRoomURL")} />
             <textarea className="room-context-comments"
               onKeyDown={this.handleTextareaKeyDown}
               placeholder={mozL10n.get("context_edit_comments_placeholder")}
               rows="2" type="text"
               valueLink={this.linkState("newRoomDescription")} />
+            <sharedViews.ButtonGroup>
+              <sharedViews.Button additionalClass="button-cancel"
+                caption={mozL10n.get("context_cancel_label")}
+                onClick={this.handleCloseClick} />
+              <sharedViews.Button additionalClass="button-accept"
+                caption={mozL10n.get("context_done_label")}
+                disabled={this.props.savingContext}
+                onClick={this.handleFormSubmit} />
+            </sharedViews.ButtonGroup>
           </form>
-          <button className="btn btn-info"
-                  disabled={this.props.savingContext}
-                  onClick={this.handleFormSubmit}>
-            {mozL10n.get("context_save_label2")}
-          </button>
-          <button className="room-context-btn-close"
-                  onClick={this.handleCloseClick}
-                  title={mozL10n.get("cancel_button")}/>
         </div>
       );
     }
   });
 
   /**
    * Desktop room conversation view.
    */
@@ -814,16 +782,17 @@ loop.roomViews = (function(mozL10n) {
                 <sharedViews.ConversationToolbar
                   audio={{enabled: !this.state.audioMuted, visible: true}}
                   dispatcher={this.props.dispatcher}
                   hangup={this.leaveRoom}
                   mozLoop={this.props.mozLoop}
                   publishStream={this.publishStream}
                   screenShare={screenShareData}
                   settingsMenuItems={settingsMenuItems}
+                  show={!shouldRenderEditContextView}
                   video={{enabled: !this.state.videoMuted, visible: true}} />
                 <DesktopRoomInvitationView
                   dispatcher={this.props.dispatcher}
                   error={this.state.error}
                   mozLoop={this.props.mozLoop}
                   onAddContextClick={this.handleAddContextClick}
                   onEditContextClose={this.handleEditContextClose}
                   roomData={roomData}
--- a/browser/components/loop/content/shared/css/common.css
+++ b/browser/components/loop/content/shared/css/common.css
@@ -70,16 +70,97 @@ p {
 .tc {
   text-align: center;
 }
 
 .full-width {
   width: 100%;
 }
 
+/* Buttons */
+
+.button-group {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  padding-top: 6px;
+}
+
+.button-group > .button {
+  flex: 1;
+  margin: 0 5px;
+  min-height: 3rem;
+  font-size: 1.2rem;
+  line-height: 1rem;
+  font-weight: 300;
+  border-radius: 4px;
+}
+
+.button-group > .button:first-child {
+  -moz-margin-start: 0;
+}
+
+.button-group > .button:last-child {
+  -moz-margin-end: 0;
+}
+
+.button {
+  padding: 2px 5px;
+  background-color: #fbfbfb;
+  color: #333;
+  border-radius: 2px;
+  min-height: 26px;
+  font-size: 1.2rem;
+  line-height: 1.2rem;
+  border: none;
+}
+
+.button:hover {
+  background-color: #ebebeb;
+}
+
+.button:active {
+  background-color: #ccc;
+  color: #fff;
+}
+
+.button.button-accept {
+  background-color: #00a9dc;
+  color: #fff;
+}
+
+.button.button-accept:hover,
+.button.button-accept:hover:active {
+  background-color: #5cccee;
+  color: #fff;
+}
+
+.button.button-cancel {
+  background-color: #ebebeb;
+  border: 0;
+  color: #000;
+}
+
+.button.button-cancel:hover,
+.button.button-cancel:hover:active {
+  background-color: #dcd6d6;
+  color: #000;
+}
+
+.button.button-cancel:disabled {
+  background-color: #ebebeb;
+  color: #c3c3c3;
+}
+
+.button.button-accept:active {
+  background-color: #3aa689;
+  border-color: #3aa689;
+  color: #fff;
+}
+
 /* A reset for all button-appearing elements, with the lowest-common
  * denominator of the needed rules.  Intended to be used as a base class
  * together with .btn-*
  */
 
 .btn {
   display: inline-block;
   margin: 0;
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -910,23 +910,16 @@ html[dir="rtl"] .room-conversation-wrapp
 .room-invitation-content {
   flex: 1 1 auto;
   display: flex;
   flex-flow: column nowrap;
   justify-content: center;
   align-items: center;
 }
 
-.room-invitation-overlay input[type="text"] {
-  display: block;
-  background-color: rgba(0,0,0,.5);
-  border-radius: 3px;
-  padding: .5em;
-}
-
 .room-invitation-overlay .btn-group {
   padding: 0 0 5rem 0;
 }
 
 .room-invitation-addcontext {
   color: #0095dd;
   padding-left: 1.5em;
   margin-bottom: 1em;
@@ -994,20 +987,19 @@ body[platform="win"] .share-service-drop
   background-color: #dbf7ff;
 }
 
 .showing-room-name > .text-chat-entries > .text-chat-scroller > .context-url-view-wrapper {
   padding-top: 0;
 }
 
 .room-context {
-  background: rgba(0,0,0,.8);
+  background: #fff;
   border-top: 2px solid #444;
   border-bottom: 2px solid #444;
-  padding: .5rem;
   position: absolute;
   left: 0;
   bottom: 0;
   width: 100%;
   height: 100%;
   font-size: .9em;
   display: flex;
   flex-flow: column nowrap;
@@ -1044,23 +1036,21 @@ body[platform="win"] .share-service-drop
   text-shadow: 1px 1px 0 rgba(0,0,0,.3);
 }
 
 .room-context > .checkbox-wrapper {
   margin-bottom: .5em;
   width: 100%;
 }
 
-.room-context-label {
-  margin-bottom: 1em;
-}
-
-.room-context-label,
-.room-context > .checkbox-wrapper > label {
-  color: #fff;
+.room-context-header {
+  color: #333;
+  font-size: 1.2rem;
+  font-weight: bold;
+  margin: 1rem auto;
 }
 
 .room-context-comment {
   color: #707070;
 }
 
 .room-context-comment {
   word-wrap: break-word;
@@ -1074,81 +1064,50 @@ body[platform="win"] .share-service-drop
   cursor: pointer;
 }
 
 .room-context-url:hover {
   text-decoration: underline;
 }
 
 .room-context > form {
+  margin-bottom: 1rem;
+  padding: .5rem;
   width: 100%;
 }
 
 .room-context > form > textarea,
 .room-context > form > input[type="text"] {
   display: block;
-  background: rgba(0,0,0,.5);
-  font-family: "Helvetica Neue", Arial, sans;
-  border: 1px solid rgba(255,255,255,.2);
   width: 100%;
-  padding: .5em;
-  border-radius: 3px;
-  resize: none;
-  color: #fff;
+  outline: none;
+  border-radius: 4px;
+  margin: 10px 0;
+  border: 1px solid #c3c3c3;
+  height: 2.6rem;
+  padding: 6px;
+  font-size: 1.1rem;
+  color: #4a4a4a;
+  box-shadow: none;
 }
 
 .room-context > form > textarea {
-  font-size: 1em;
-}
-
-.room-context > form > input:not([disabled]).room-context-url {
-  color: #0095dd;
-}
-
-.room-context > form > input[disabled] {
-  background-color: rgba(255,255,255,.2);
-  color: rgba(255,255,255,.4);
-}
-
-.room-context > form > textarea:not(:last-of-type),
-.room-context > form > input[type="text"] {
-  margin: 0 0 .5em 0;
-}
-
-.room-context > .btn {
-  margin: .5em 0 0;
-  font-size: 1.1em;
-  padding: 0 .5em;
-  align-self: flex-end;
+  font-family: inherit;
+  height: 5.2rem;
+  resize: none;
 }
 
-.room-context-btn-close {
-  position: absolute;
-  right: 8px;
-  /* 8px offset + 2px border-top */
-  top: 10px;
-  width: 8px;
-  height: 8px;
-  background-color: transparent;
-  background-image: url("../img/icons-10x10.svg#close-darkergrey");
-  background-size: 8px 8px;
-  background-repeat: no-repeat;
-  border: 0;
-  padding: 0;
-  cursor: pointer;
+.room-context > form > textarea::-moz-placeholder,
+.room-context > form > input::-moz-placeholder {
+  color: #999;
 }
 
-.room-context-btn-close:hover,
-.room-context-btn-close:hover:active {
-  background-image: url("../img/icons-10x10.svg#close-active");
-}
-
-html[dir="rtl"] .room-context-btn-close {
-  right: auto;
-  left: 8px;
+.room-context > form > textarea:focus,
+.room-context > form > input:focus {
+  border: 0.1rem solid #5cccee;
 }
 
 .media-layout {
   height: 100%;
 }
 
 .standalone-room-wrapper > .media-layout {
   /* 50px is the header, 3em is the footer. */
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -354,16 +354,17 @@ loop.shared.views = (function(_, mozL10n
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       enableHangup: React.PropTypes.bool,
       hangup: React.PropTypes.func.isRequired,
       hangupButtonLabel: React.PropTypes.string,
       mozLoop: React.PropTypes.object,
       publishStream: React.PropTypes.func.isRequired,
       screenShare: React.PropTypes.object,
       settingsMenuItems: React.PropTypes.array,
+      show: React.PropTypes.bool.isRequired,
       video: React.PropTypes.object.isRequired
     },
 
     handleClickHangup: function() {
       this.props.hangup();
     },
 
     handleToggleVideo: function() {
@@ -435,16 +436,20 @@ loop.shared.views = (function(_, mozL10n
       }.bind(this), 6000);
     },
 
     _getHangupButtonLabel: function() {
       return this.props.hangupButtonLabel || mozL10n.get("hangup_button_caption2");
     },
 
     render: function() {
+      if (!this.props.show) {
+        return null;
+      }
+
       var cx = React.addons.classSet;
       var conversationToolbarCssClasses = cx({
         "conversation-toolbar": true,
         "idle": this.state.idle
       });
       var mediaButtonGroupCssClasses = cx({
         "conversation-toolbar-media-btn-group-box": true,
         "hide": (!this.props.video.visible && !this.props.audio.visible)
@@ -793,17 +798,17 @@ loop.shared.views = (function(_, mozL10n
     /**
      * Renders the context title ("Let's talk about") if necessary.
      */
     renderContextTitle: function() {
       if (!this.props.showContextTitle) {
         return null;
       }
 
-      return React.createElement("p", null, mozL10n.get("context_inroom_label"));
+      return React.createElement("p", null, mozL10n.get("context_inroom_label2"));
     },
 
     render: function() {
       var hostname;
 
       try {
         hostname = new URL(this.props.url).hostname;
       } catch (ex) {
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -354,16 +354,17 @@ loop.shared.views = (function(_, mozL10n
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       enableHangup: React.PropTypes.bool,
       hangup: React.PropTypes.func.isRequired,
       hangupButtonLabel: React.PropTypes.string,
       mozLoop: React.PropTypes.object,
       publishStream: React.PropTypes.func.isRequired,
       screenShare: React.PropTypes.object,
       settingsMenuItems: React.PropTypes.array,
+      show: React.PropTypes.bool.isRequired,
       video: React.PropTypes.object.isRequired
     },
 
     handleClickHangup: function() {
       this.props.hangup();
     },
 
     handleToggleVideo: function() {
@@ -435,16 +436,20 @@ loop.shared.views = (function(_, mozL10n
       }.bind(this), 6000);
     },
 
     _getHangupButtonLabel: function() {
       return this.props.hangupButtonLabel || mozL10n.get("hangup_button_caption2");
     },
 
     render: function() {
+      if (!this.props.show) {
+        return null;
+      }
+
       var cx = React.addons.classSet;
       var conversationToolbarCssClasses = cx({
         "conversation-toolbar": true,
         "idle": this.state.idle
       });
       var mediaButtonGroupCssClasses = cx({
         "conversation-toolbar-media-btn-group-box": true,
         "hide": (!this.props.video.visible && !this.props.audio.visible)
@@ -793,17 +798,17 @@ loop.shared.views = (function(_, mozL10n
     /**
      * Renders the context title ("Let's talk about") if necessary.
      */
     renderContextTitle: function() {
       if (!this.props.showContextTitle) {
         return null;
       }
 
-      return <p>{mozL10n.get("context_inroom_label")}</p>;
+      return <p>{mozL10n.get("context_inroom_label2")}</p>;
     },
 
     render: function() {
       var hostname;
 
       try {
         hostname = new URL(this.props.url).hostname;
       } catch (ex) {
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -577,16 +577,17 @@ loop.standaloneRoomViews = (function(moz
             React.createElement(sharedViews.ConversationToolbar, {
               audio: {enabled: !this.state.audioMuted,
                       visible: this._roomIsActive()}, 
               dispatcher: this.props.dispatcher, 
               enableHangup: this._roomIsActive(), 
               hangup: this.leaveRoom, 
               hangupButtonLabel: mozL10n.get("rooms_leave_button_label"), 
               publishStream: this.publishStream, 
+              show: true, 
               video: {enabled: !this.state.videoMuted,
                       visible: this._roomIsActive()}})
           ), 
           React.createElement(StandaloneRoomFooter, {dispatcher: this.props.dispatcher})
         )
       );
     }
   });
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -577,16 +577,17 @@ loop.standaloneRoomViews = (function(moz
             <sharedViews.ConversationToolbar
               audio={{enabled: !this.state.audioMuted,
                       visible: this._roomIsActive()}}
               dispatcher={this.props.dispatcher}
               enableHangup={this._roomIsActive()}
               hangup={this.leaveRoom}
               hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}
               publishStream={this.publishStream}
+              show={true}
               video={{enabled: !this.state.videoMuted,
                       visible: this._roomIsActive()}} />
           </sharedViews.MediaLayoutView>
           <StandaloneRoomFooter dispatcher={this.props.dispatcher} />
         </div>
       );
     }
   });
--- a/browser/components/loop/standalone/content/l10n/en-US/loop.properties
+++ b/browser/components/loop/standalone/content/l10n/en-US/loop.properties
@@ -79,14 +79,14 @@ rooms_read_while_wait_offer=Want somethi
 ## by the name of the conversation and {{clientShortname}} will be
 ## replaced by the brand name.
 standalone_title_with_room_name={{roomName}} — {{clientShortname}}
 status_error=Something went wrong
 
 # Text chat strings
 
 chat_textbox_placeholder=Type here…
-# LOCALIZATION NOTE (context_inroom_label): this string is followed by the
+# LOCALIZATION NOTE (context_inroom_label2): this string is followed by the
 # title/URL of the website you are having a conversation about, displayed on a
 # separate line. If this structure doesn't work for your locale, you might want
 # to consider this as a stand-alone title. See example screenshot:
 # https://bug1084991.bugzilla.mozilla.org/attachment.cgi?id=8614721
-context_inroom_label=Let's talk about:
+context_inroom_label2=Let's Talk About:
--- a/browser/components/loop/test/desktop-local/roomViews_test.js
+++ b/browser/components/loop/test/desktop-local/roomViews_test.js
@@ -703,26 +703,23 @@ describe("loop.roomViews", function () {
         expect(node.querySelector(".room-context")).to.eql(null);
 
         var editButton = node.querySelector(".settings-menu > li.entry-settings-edit");
         React.addons.TestUtils.Simulate.click(editButton);
 
         expect(view.getDOMNode().querySelector(".room-context")).to.not.eql(null);
       });
 
-      it("should hide the form when the edit button is clicked again", function() {
+      it("should not have a settings menu when the edit button is clicked", function() {
         view = mountTestComponent();
 
         var editButton = view.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
         React.addons.TestUtils.Simulate.click(editButton);
 
-        // Click again.
-        React.addons.TestUtils.Simulate.click(editButton);
-
-        expect(view.getDOMNode().querySelector(".room-context")).to.eql(null);
+        expect(view.getDOMNode().querySelector(".settings-menu")).to.eql(null);
       });
     });
   });
 
   describe("SocialShareDropdown", function() {
     var fakeProvider;
 
     beforeEach(function() {
@@ -835,22 +832,22 @@ describe("loop.roomViews", function () {
       it("should not render the component when 'show' is false", function() {
         view = mountTestComponent({
           show: false
         });
 
         expect(view.getDOMNode()).to.eql(null);
       });
 
-      it("should close the view when the close button is clicked", function() {
+      it("should close the view when the cancel button is clicked", function() {
         view = mountTestComponent({
           roomData: { roomContextUrls: [fakeContextURL] }
         });
 
-        var closeBtn = view.getDOMNode().querySelector(".room-context-btn-close");
+        var closeBtn = view.getDOMNode().querySelector(".button-cancel");
         React.addons.TestUtils.Simulate.click(closeBtn);
         expect(view.getDOMNode()).to.eql(null);
       });
 
       it("should render the view correctly", function() {
         var roomName = "Hello, is it me you're looking for?";
         view = mountTestComponent({
           roomData: {
@@ -861,45 +858,16 @@ describe("loop.roomViews", function () {
 
         var node = view.getDOMNode();
         expect(node.querySelector("form")).to.not.eql(null);
         // Check the contents of the form fields.
         expect(node.querySelector(".room-context-name").value).to.eql(roomName);
         expect(node.querySelector(".room-context-url").value).to.eql(fakeContextURL.location);
         expect(node.querySelector(".room-context-comments").value).to.eql(fakeContextURL.description);
       });
-
-      it("should show the checkbox as disabled when context is already set", function() {
-        view = mountTestComponent({
-          roomData: {
-            roomToken: "fakeToken",
-            roomName: "fakeName",
-            roomContextUrls: [fakeContextURL]
-          }
-        });
-
-        var checkbox = view.getDOMNode().querySelector(".checkbox");
-        expect(checkbox.classList.contains("disabled")).to.eql(true);
-      });
-
-      it("should hide the checkbox when no context data is stored or available", function() {
-        view = mountTestComponent({
-          roomData: {
-            roomToken: "fakeToken",
-            roomName: "Hello, is it me you're looking for?"
-          }
-        });
-
-        // First check if availableContext is set correctly.
-        expect(view.state.availableContext).to.not.eql(null);
-        expect(view.state.availableContext.previewImage).to.eql(favicon);
-
-        var node = view.getDOMNode();
-        expect(node.querySelector(".checkbox-wrapper").classList.contains("hide")).to.eql(true);
-      });
     });
 
     describe("Update Room", function() {
       var roomNameBox;
 
       beforeEach(function() {
         view = mountTestComponent({
           editMode: true,
@@ -914,17 +882,17 @@ describe("loop.roomViews", function () {
       });
 
       it("should dispatch a UpdateRoomContext action when the save button is clicked",
         function() {
           React.addons.TestUtils.Simulate.change(roomNameBox, { target: {
             value: "reallyFake"
           }});
 
-          React.addons.TestUtils.Simulate.click(view.getDOMNode().querySelector(".btn-info"));
+          React.addons.TestUtils.Simulate.click(view.getDOMNode().querySelector(".button-accept"));
 
           sinon.assert.calledOnce(dispatcher.dispatch);
           sinon.assert.calledWithExactly(dispatcher.dispatch,
             new sharedActions.UpdateRoomContext({
               roomToken: "fakeToken",
               newRoomName: "reallyFake",
               newRoomDescription: fakeContextURL.description,
               newRoomURL: fakeContextURL.location,
@@ -950,67 +918,28 @@ describe("loop.roomViews", function () {
               newRoomThumbnail: fakeContextURL.thumbnail
             }));
         });
 
       it("should close the edit form when context was saved successfully", function(done) {
         view.setProps({ savingContext: true }, function() {
           var node = view.getDOMNode();
           // The button should show up as disabled.
-          expect(node.querySelector(".btn-info").hasAttribute("disabled")).to.eql(true);
+          expect(node.querySelector(".button-accept").hasAttribute("disabled")).to.eql(true);
 
           // Now simulate a successful save.
           view.setProps({ savingContext: false }, function() {
             // The 'show flag should be updated.
             expect(view.state.show).to.eql(false);
             done();
           });
         });
       });
     });
 
-    describe("#handleCheckboxChange", function() {
-      var node, checkbox;
-
-      beforeEach(function() {
-        fakeMozLoop.getSelectedTabMetadata = sinon.stub().callsArgWith(0, {
-          favicon: fakeContextURL.thumbnail,
-          title: fakeContextURL.description,
-          url: fakeContextURL.location
-        });
-        view = mountTestComponent({
-          roomData: {
-            roomToken: "fakeToken",
-            roomName: "fakeName"
-          }
-        });
-
-        node = view.getDOMNode();
-        checkbox = node.querySelector(".checkbox");
-      });
-
-      it("should prefill the form with available context data when clicked", function() {
-        React.addons.TestUtils.Simulate.click(checkbox);
-
-        expect(node.querySelector(".room-context-name").value).to.eql("fakeName");
-        expect(node.querySelector(".room-context-url").value).to.eql(fakeContextURL.location);
-        expect(node.querySelector(".room-context-comments").value).to.eql(fakeContextURL.description);
-      });
-
-      it("should undo prefill when clicking the checkbox again", function() {
-        React.addons.TestUtils.Simulate.click(checkbox);
-        // Twice.
-        React.addons.TestUtils.Simulate.click(checkbox);
-
-        expect(node.querySelector(".room-context-name").value).to.eql("fakeName");
-        expect(node.querySelector(".room-context-url").value).to.eql("");
-        expect(node.querySelector(".room-context-comments").value).to.eql("");
-      });
-    });
-
     describe("#handleContextClick", function() {
       var fakeEvent;
 
       beforeEach(function() {
         fakeEvent = {
           preventDefault: sinon.stub(),
           stopPropagation: sinon.stub()
         };
--- a/browser/components/loop/test/shared/views_test.js
+++ b/browser/components/loop/test/shared/views_test.js
@@ -424,32 +424,43 @@ describe("loop.shared.views", function()
   });
 
   describe("ConversationToolbar", function() {
     var clock, hangup, publishStream;
 
     function mountTestComponent(props) {
       props = _.extend({
         dispatcher: dispatcher,
-        mozLoop: {}
+        mozLoop: {},
+        show: true
       }, props || {});
       return TestUtils.renderIntoDocument(
         React.createElement(sharedViews.ConversationToolbar, props));
     }
 
     beforeEach(function() {
       hangup = sandbox.stub();
       publishStream = sandbox.stub();
       clock = sinon.useFakeTimers();
     });
 
     afterEach(function() {
       clock.restore();
     });
 
+    it("should not render the component when 'show' is false", function() {
+      var comp = mountTestComponent({
+        hangup: hangup,
+        publishStream: publishStream,
+        show: false
+      });
+
+      expect(comp.getDOMNode()).to.eql(null);
+    });
+
     it("should start no idle", function() {
       var comp = mountTestComponent({
         hangupButtonLabel: "foo",
         hangup: hangup,
         publishStream: publishStream
       });
       expect(comp.getDOMNode().classList.contains("idle")).eql(false);
     });
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -1113,44 +1113,47 @@
                              width: 300}, 
                 React.createElement("div", {className: "fx-embedded"}, 
                   React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true}, 
                                        dispatcher: dispatcher, 
                                        hangup: noop, 
                                        publishStream: noop, 
                                        screenShare: { state: SCREEN_SHARE_STATES.INACTIVE, visible: true}, 
                                        settingsMenuItems: [{ id: "feedback" }], 
+                                       show: true, 
                                        video: { enabled: true, visible: true}})
                 )
               ), 
               React.createElement(FramedExample, {dashed: true, 
                              height: 56, 
                              summary: "Video muted, Screen share pending", 
                              width: 300}, 
                 React.createElement("div", {className: "fx-embedded"}, 
                   React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true}, 
                                        dispatcher: dispatcher, 
                                        hangup: noop, 
                                        publishStream: noop, 
                                        screenShare: { state: SCREEN_SHARE_STATES.PENDING, visible: true}, 
                                        settingsMenuItems: [{ id: "feedback" }], 
+                                       show: true, 
                                        video: { enabled: false, visible: true}})
                 )
               ), 
               React.createElement(FramedExample, {dashed: true, 
                              height: 56, 
                              summary: "Audio muted, Screen share active", 
                              width: 300}, 
                 React.createElement("div", {className: "fx-embedded"}, 
                   React.createElement(ConversationToolbar, {audio: { enabled: false, visible: true}, 
                                        dispatcher: dispatcher, 
                                        hangup: noop, 
                                        publishStream: noop, 
                                        screenShare: { state: SCREEN_SHARE_STATES.ACTIVE, visible: true}, 
                                        settingsMenuItems: [{ id: "feedback" }], 
+                                       show: true, 
                                        video: { enabled: true, visible: true}})
                 )
               )
             )
           ), 
 
           React.createElement(Section, {name: "PendingConversationView (Desktop)"}, 
             React.createElement(FramedExample, {dashed: true, 
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -1113,44 +1113,47 @@
                              width={300}>
                 <div className="fx-embedded">
                   <ConversationToolbar audio={{ enabled: true, visible: true }}
                                        dispatcher={dispatcher}
                                        hangup={noop}
                                        publishStream={noop}
                                        screenShare={{ state: SCREEN_SHARE_STATES.INACTIVE, visible: true }}
                                        settingsMenuItems={[{ id: "feedback" }]}
+                                       show={true}
                                        video={{ enabled: true, visible: true }} />
                 </div>
               </FramedExample>
               <FramedExample dashed={true}
                              height={56}
                              summary="Video muted, Screen share pending"
                              width={300}>
                 <div className="fx-embedded">
                   <ConversationToolbar audio={{ enabled: true, visible: true }}
                                        dispatcher={dispatcher}
                                        hangup={noop}
                                        publishStream={noop}
                                        screenShare={{ state: SCREEN_SHARE_STATES.PENDING, visible: true }}
                                        settingsMenuItems={[{ id: "feedback" }]}
+                                       show={true}
                                        video={{ enabled: false, visible: true }} />
                 </div>
               </FramedExample>
               <FramedExample dashed={true}
                              height={56}
                              summary="Audio muted, Screen share active"
                              width={300}>
                 <div className="fx-embedded">
                   <ConversationToolbar audio={{ enabled: false, visible: true }}
                                        dispatcher={dispatcher}
                                        hangup={noop}
                                        publishStream={noop}
                                        screenShare={{ state: SCREEN_SHARE_STATES.ACTIVE, visible: true }}
                                        settingsMenuItems={[{ id: "feedback" }]}
+                                       show={true}
                                        video={{ enabled: true, visible: true }} />
                 </div>
               </FramedExample>
             </div>
           </Section>
 
           <Section name="PendingConversationView (Desktop)">
             <FramedExample dashed={true}
--- a/browser/components/preferences/in-content/security.xul
+++ b/browser/components/preferences/in-content/security.xul
@@ -65,21 +65,21 @@
               label="&blockWebForgeries.label;"
               accesskey="&blockWebForgeries.accesskey;"
               preference="browser.safebrowsing.enabled" />
   </vbox>
 </groupbox>
 
 <!-- Passwords -->
 <groupbox id="passwordsGroup" orient="vertical" data-category="paneSecurity" hidden="true">
-  <caption><label>&passwords.label;</label></caption>
+  <caption><label>&logins.label;</label></caption>
 
   <hbox id="savePasswordsBox">
     <checkbox id="savePasswords"
-              label="&rememberPasswords.label;" accesskey="&rememberPasswords.accesskey;"
+              label="&rememberLogins.label;" accesskey="&rememberLogins.accesskey;"
               preference="signon.rememberSignons"
               onsyncfrompreference="return gSecurityPane.readSavePasswords();"/>
     <spacer flex="1"/>
     <button id="passwordExceptions"
             label="&passwordExceptions.label;"
             accesskey="&passwordExceptions.accesskey;"
             preference="pref.privacy.disable_button.view_passwords_exceptions"/>
   </hbox>
@@ -98,14 +98,14 @@
         </hbox>
         <button id="changeMasterPassword"
                 label="&changeMasterPassword.label;"
                 accesskey="&changeMasterPassword.accesskey;"/>
       </row>
       <row id="showPasswordRow">
         <hbox id="showPasswordsBox"/>
         <button id="showPasswords"
-                label="&savedPasswords.label;" accesskey="&savedPasswords.accesskey;"
+                label="&savedLogins.label;" accesskey="&savedLogins.accesskey;"
                 preference="pref.privacy.disable_button.view_passwords"/>
       </row>
     </rows>
   </grid>
 </groupbox>
--- a/browser/components/translation/moz.build
+++ b/browser/components/translation/moz.build
@@ -17,12 +17,8 @@ JAR_MANIFESTS += ['jar.mn']
 
 BROWSER_CHROME_MANIFESTS += [
     'test/browser.ini'
 ]
 
 XPCSHELL_TESTS_MANIFESTS += [
     'test/unit/xpcshell.ini'
 ]
-
-EXTRA_PP_COMPONENTS += [
-    'translation.manifest',
-]
deleted file mode 100644
--- a/browser/components/translation/translation.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-#ifdef MOZ_SERVICES_HEALTHREPORT
-category healthreport-js-provider-default TranslationProvider resource:///modules/translation/Translation.jsm
-#endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -381,17 +381,16 @@
 @RESPATH@/browser/components/nsSetDefaultBrowser.manifest
 @RESPATH@/browser/components/nsSetDefaultBrowser.js
 @RESPATH@/browser/components/devtools-clhandler.manifest
 @RESPATH@/browser/components/devtools-clhandler.js
 @RESPATH@/browser/components/webideCli.js
 @RESPATH@/browser/components/webideComponents.manifest
 @RESPATH@/browser/components/Experiments.manifest
 @RESPATH@/browser/components/ExperimentsService.js
-@RESPATH@/browser/components/translation.manifest
 @RESPATH@/components/Downloads.manifest
 @RESPATH@/components/DownloadLegacy.js
 @RESPATH@/components/BrowserPageThumbs.manifest
 @RESPATH@/components/crashmonitor.manifest
 @RESPATH@/components/nsCrashMonitor.js
 @RESPATH@/components/SiteSpecificUserAgent.js
 @RESPATH@/components/SiteSpecificUserAgent.manifest
 @RESPATH@/components/toolkitsearch.manifest
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -110,20 +110,16 @@ These should match what Safari and other
 <!ENTITY showAllTabsCmd.accesskey "A">
 
 <!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
 <!ENTITY fxaSignedIn.tooltip "Open &syncBrand.shortName.label; preferences">
 <!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
 <!ENTITY fxaUnverified.label "Verify Your Account">
 <!ENTITY syncStartPanel2.heading "&syncBrand.shortName.label; enabled">
 <!ENTITY syncStartPanel2.subTitle "&brandShortName; will begin syncing momentarily.">
-<!ENTITY syncErrorPanel.heading "Cannot connect to &syncBrand.shortName.label;">
-<!ENTITY syncErrorPanel.subTitle "Please sign in to resume syncing.">
-<!ENTITY syncErrorPanel.signInButton.label "Sign In">
-<!ENTITY syncErrorPanel.signInButton.accesskey "S">
 
 
 <!ENTITY fullScreenMinimize.tooltip "Minimize">
 <!ENTITY fullScreenRestore.tooltip "Restore">
 <!ENTITY fullScreenClose.tooltip "Close">
 <!ENTITY fullScreenAutohide.label "Hide Toolbars">
 <!ENTITY fullScreenAutohide.accesskey "H">
 <!ENTITY fullScreenExit.label "Exit Full Screen Mode">
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -26,16 +26,25 @@ sign_in_again_button=Sign In
 sign_in_again_use_as_guest_button2=Use {{clientSuperShortname}} as a Guest
 
 first_time_experience_button_label=Get Started
 ## LOCALIZATION_NOTE(first_time_experience_subheading): Message inviting the
 ## user to create his or her first conversation.
 first_time_experience_subheading=Join the conversation
 
 invite_header_text=Invite someone to join you.
+invite_header_text2=Invite a friend to join you
+invite_facebook_button=share on Facebook
+invite_facebook_triggered=shared!
+invite_contacts_button=share with contacts
+invite_contacts_triggered=shared!
+invite_copy_button=copy link
+invite_copy_triggered=copied!
+invite_email_button=email link
+invite_email_triggered=emailed!
 
 # Status text
 display_name_guest=Guest
 display_name_dnd_status=Do Not Disturb
 display_name_available_status=Available
 
 # Error bars
 ## LOCALIZATION NOTE(unable_retrieve_url,session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):
@@ -338,31 +347,36 @@ rooms_signout_alert=Open conversations w
 infobar_screenshare_browser_message=Users in your conversation will now be able to see the contents of any tab you click on.
 infobar_button_gotit_label=Got it!
 infobar_button_gotit_accesskey=G
 infobar_menuitem_dontshowagain_label=Don't show this again
 infobar_menuitem_dontshowagain_accesskey=D
 
 # Context in conversation strings
 
-# LOCALIZATION NOTE (context_inroom_label): this string is followed by the
-# title/URL of the website you are having a conversation about, displayed on a
+# LOCALIZATION NOTE (context_inroom_header): this string is displayed in the
+# conversation window when the user edits context. It is a header to the edit
+# section.
+context_inroom_header=Let's Talk About…
+# LOCALIZATION NOTE (context_inroom_label2): this string is followed by the
+# title and domain of the website you are having a conversation about, displayed on a
 # separate line. If this structure doesn't work for your locale, you might want
 # to consider this as a stand-alone title. See example screenshot:
 # https://bug1115342.bugzilla.mozilla.org/attachment.cgi?id=8563677
-context_inroom_label=Let's talk about:
+context_inroom_label2=Let's Talk About:
 ## LOCALIZATION_NOTE (context_edit_activate_label): {{title}} will be replaced
 ## by the title of the active tab, also known as the title of an HTML document.
 ## The quotes around the title are intentional.
 context_edit_activate_label=Talk about "{{title}}"
 context_edit_name_placeholder=Conversation Name
 context_edit_comments_placeholder=Comments
 context_add_some_label=Add some context
 context_show_tooltip=Show Context
-context_save_label2=Save
+context_cancel_label=Cancel
+context_done_label=Done
 context_link_modified=This link was modified.
 context_learn_more_link_label=Learn more.
 conversation_settings_menu_edit_context=Edit Context
 conversation_settings_menu_hide_context=Hide Context
 
 
 # Text chat strings
 
--- a/browser/locales/en-US/chrome/browser/preferences/security.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/security.dtd
@@ -19,22 +19,22 @@
 
 <!ENTITY  blockWebForgeries.label     "Block reported web forgeries">
 <!ENTITY  blockWebForgeries.accesskey "B">
 
 <!ENTITY  addonExceptions.label         "Exceptions…">
 <!ENTITY  addonExceptions.accesskey     "E">
 
 
-<!ENTITY  passwords.label               "Passwords">
+<!ENTITY  logins.label                  "Logins">
 
-<!ENTITY  rememberPasswords.label       "Remember passwords for sites">
-<!ENTITY  rememberPasswords.accesskey   "R">
+<!ENTITY  rememberLogins.label          "Remember logins for sites">
+<!ENTITY  rememberLogins.accesskey      "R">
 <!ENTITY  passwordExceptions.label      "Exceptions…">
 <!ENTITY  passwordExceptions.accesskey  "x">
 
 <!ENTITY  useMasterPassword.label        "Use a master password">
 <!ENTITY  useMasterPassword.accesskey    "U">
 <!ENTITY  changeMasterPassword.label     "Change Master Password…">
 <!ENTITY  changeMasterPassword.accesskey "M">
 
-<!ENTITY  savedPasswords.label            "Saved Passwords…">
-<!ENTITY  savedPasswords.accesskey        "P">
+<!ENTITY  savedLogins.label              "Saved Logins…">
+<!ENTITY  savedLogins.accesskey          "L">
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1720,25 +1720,23 @@ toolbarbutton.chevron > .toolbarbutton-i
   width: 0;
   padding-left: 10px;
 }
 
 .sync-panel-button-box {
   margin-top: 1em;
 }
 
-#sync-error-panel-title,
 #sync-start-panel-title {
   font-size: 120%;
   font-weight: bold;
   margin-bottom: 5px;
 }
 
-#sync-start-panel-subtitle,
-#sync-error-panel-subtitle {
+#sync-start-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
 
 .statuspanel-label {
   margin: 0;
   padding: 2px 4px;
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3270,25 +3270,23 @@ notification[value="loop-sharing-notific
 .sync-panel-button:hover:active {
   @hudButtonPressed@
 }
 
 .sync-panel-button:-moz-focusring {
   @hudButtonFocused@
 }
 
-#sync-error-panel-title,
 #sync-start-panel-title {
   font-size: 120%;
   font-weight: bold;
   margin-bottom: 5px;
 }
 
-#sync-start-panel-subtitle,
-#sync-error-panel-subtitle {
+#sync-start-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
 
 .statuspanel-label {
   margin: 0;
   padding: 2px 4px;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2468,25 +2468,23 @@ notification[value="loop-sharing-notific
   width: 0;
   padding-left: 10px;
 }
 
 .sync-panel-button-box {
   margin-top: 1em;
 }
 
-#sync-error-panel-title,
 #sync-start-panel-title {
   font-size: 120%;
   font-weight: bold;
   margin-bottom: 5px;
 }
 
-#sync-start-panel-subtitle,
-#sync-error-panel-subtitle {
+#sync-start-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
 
 .statuspanel-label {
   margin: 0;
   padding: 2px 4px;
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -11,17 +11,17 @@ var dateFormatter = new Intl.DateTimeFor
 var dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
                              { day: "numeric", month: "short", year: "numeric",
                                hour: "numeric", minute: "numeric" });
 
 function SignonsStartup() {
   kSignonBundle = document.getElementById("signonBundle");
   document.getElementById("togglePasswords").label = kSignonBundle.getString("showPasswords");
   document.getElementById("togglePasswords").accessKey = kSignonBundle.getString("showPasswordsAccessKey");
-  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll");
+  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsDescriptionAll");
 
   let treecols = document.getElementsByTagName("treecols")[0];
   treecols.addEventListener("click", HandleTreeColumnClick.bind(null, SignonColumnSort));
 
   LoadSignons();
 
   // filter the table if requested by caller
   if (window.arguments &&
@@ -309,17 +309,17 @@ function SignonClearFilter() {
       var range = signonsTreeView._lastSelectedRanges[i];
       signonsTreeView.selection.rangedSelect(range.min, range.max, true);
     }
   } else {
     signonsTreeView.selection.select(0);
   }
   signonsTreeView._lastSelectedRanges = [];
 
-  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll");
+  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsDescriptionAll");
 }
 
 function FocusFilterBox() {
   var filterBox = document.getElementById("filter");
   if (filterBox.getAttribute("focused") != "true")
     filterBox.focus();
 }
 
@@ -379,17 +379,17 @@ function _filterPasswords()
   // Set up the filtered display
   signonsTreeView.rowCount = signonsTreeView._filterSet.length;
   signonsTree.treeBoxObject.rowCountChanged(0, signonsTreeView.rowCount);
 
   // if the view is not empty then select the first item
   if (signonsTreeView.rowCount > 0)
     signonsTreeView.selection.select(0);
 
-  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielFiltered");
+  document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsDescriptionFiltered");
 }
 
 function CopyPassword() {
   // Don't copy passwords if we aren't already showing the passwords & a master
   // password hasn't been entered.
   if (!showingPasswords && !masterPasswordLogin())
     return;
   // Copy selected signon's password to clipboard
--- a/toolkit/components/passwordmgr/content/passwordManager.xul
+++ b/toolkit/components/passwordmgr/content/passwordManager.xul
@@ -8,17 +8,17 @@
 
 <!DOCTYPE dialog SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd" >
 
 <window id="SignonViewerDialog"
         windowtype="Toolkit:PasswordManager"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="Startup(); SignonsStartup();"
         onunload="Shutdown();"
-        title="&savedPasswords.title;"
+        title="&savedLogins.title;"
         persist="width height screenX screenY">
 
   <script type="application/javascript" src="chrome://passwordmgr/content/passwordManagerCommon.js"/>
   <script type="application/javascript" src="chrome://passwordmgr/content/passwordManager.js"/>
 
   <stringbundle id="signonBundle"
                 src="chrome://passwordmgr/locale/passwordmgr.properties"/>
 
--- a/toolkit/components/passwordmgr/content/passwordManagerExceptions.xul
+++ b/toolkit/components/passwordmgr/content/passwordManagerExceptions.xul
@@ -10,25 +10,25 @@
 
 <prefwindow id="SignonViewerExceptionDialog"
             windowtype="Toolkit:PasswordManagerExceptions"
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
             buttons="accept"
             buttonlabelaccept="&closebutton.label;"
             onload="Startup(); RejectsStartup();"
             onunload="Shutdown();"
-            title="&savedPasswordsExceptions.title;"
+            title="&savedLoginsExceptions.title;"
             persist="width height screenX screenY">
 
   <prefpane id="SignonViewerDialogPane" flex="1">
     <script type="application/javascript" src="chrome://passwordmgr/content/passwordManagerCommon.js"/>
     <script type="application/javascript" src="chrome://passwordmgr/content/passwordManagerExceptions.js"/>
 
     <vbox id="rejectedsites" flex="1">
-        <description control="rejectsTree">&loginsSpielExceptions.label;</description>
+        <description control="rejectsTree">&savedLoginsExceptions.desc;</description>
         <separator class="thin"/>
         <tree id="rejectsTree" flex="1" style="height: 10em;" hidecolumnpicker="true"
               onkeypress="HandleRejectKeyPress(event)"
               onselect="RejectSelected();">
           <treecols>
             <treecol id="rejectCol" label="&treehead.site.label;" flex="5"
                      data-field-name="host" sortDirection="ascending"/>
           </treecols>
--- a/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
+++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
@@ -1,19 +1,19 @@
 <!-- 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/. -->
 
-<!ENTITY      savedPasswords.title            "Saved Passwords">
-<!ENTITY      savedPasswordsExceptions.title  "Exceptions - Saved Passwords">
+<!ENTITY      savedLogins.title               "Saved Logins">
+<!ENTITY      savedLoginsExceptions.title     "Exceptions - Saved Logins">
+<!ENTITY      savedLoginsExceptions.desc      "Logins for the following sites will not be saved:">
+
 <!ENTITY      closebutton.label               "Close">
 <!ENTITY      closebutton.accesskey           "C">
 
-<!ENTITY      loginsSpielExceptions.label     "Passwords for the following sites will not be saved:">
-
 <!ENTITY      treehead.site.label             "Site">
 <!ENTITY      treehead.username.label         "Username">
 <!ENTITY      treehead.password.label         "Password">
 <!ENTITY      treehead.timeCreated.label         "First Used">
 <!ENTITY      treehead.timeLastUsed.label        "Last Used">
 <!ENTITY      treehead.timePasswordChanged.label "Last Changed">
 <!ENTITY      treehead.timesUsed.label           "Times Used">
 
--- a/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties
+++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties
@@ -51,18 +51,18 @@ hidePasswords=Hide Passwords
 hidePasswordsAccessKey=P
 showPasswords=Show Passwords
 showPasswordsAccessKey=P
 noMasterPasswordPrompt=Are you sure you wish to show your passwords?
 removeAllPasswordsPrompt=Are you sure you wish to remove all passwords?
 removeAllPasswordsTitle=Remove all passwords
 removeLoginPrompt=Are you sure you wish to remove this login?
 removeLoginTitle=Remove login
-loginsSpielAll=Passwords for the following sites are stored on your computer:
-loginsSpielFiltered=The following passwords match your search:
+loginsDescriptionAll=Logins for the following sites are stored on your computer:
+loginsDescriptionFiltered=The following logins match your search:
 # LOCALIZATION NOTE (loginHostAge):
 # This is used to show the context menu login items with their age.
 # 1st string is the username for the login, 2nd is the login's age.
 loginHostAge=%1$S (%2$S)
 # LOCALIZATION NOTE (noUsername):
 # String is used on the context menu when a login doesn't have a username.
 noUsername=No username
 duplicateLoginTitle=Login already exists