Bug 1244481 - Support intl.uidirection pref in sync sidebar r?eoger draft
authorCarol Ng <cng@mozilla.com>
Thu, 24 May 2018 15:33:08 -0400
changeset 799968 555dec97a7b128d374df582dc2e71292110ffebd
parent 798691 d36cd8bdbc5c0df1d1d7a167f5fedb95c3a3648e
push id111231
push userbmo:cng@mozilla.com
push dateFri, 25 May 2018 17:55:56 +0000
reviewerseoger
bugs1244481
milestone62.0a1
Bug 1244481 - Support intl.uidirection pref in sync sidebar r?eoger MozReview-Commit-ID: DAIZ41abquT
browser/components/syncedtabs/SyncedTabsDeckComponent.js
browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
--- a/browser/components/syncedtabs/SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/SyncedTabsDeckComponent.js
@@ -74,16 +74,20 @@ SyncedTabsDeckComponent.prototype = {
     Services.obs.addObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION);
     Services.obs.addObserver(this, "weave:service:login:change");
     // If the Sync service is not ready, in init() > updatePanel() we will
     // show a blank screen. If tab syncing is disabled, we will not get any other
     // ui-refreshing notifications! We listen to :ready in order to check again
     // if this engine is disabled and refresh the UI one last time.
     Services.obs.addObserver(this, "weave:service:ready");
 
+    // Add intl.uidirection support for HTML sidebar
+    Services.prefs.addObserver("intl.uidirection", this);
+    this.updateDir();
+
     // Go ahead and trigger sync
     this._SyncedTabs.syncTabs()
                     .catch(Cu.reportError);
 
     this._deckView = new this._DeckView(this._window, this.tabListComponent, {
       onConnectDeviceClick: event => this.openConnectDevice(event),
       onSyncPrefClick: event => this.openSyncPrefs(event)
     });
@@ -96,32 +100,38 @@ SyncedTabsDeckComponent.prototype = {
     this.updatePanel();
   },
 
   uninit() {
     Services.obs.removeObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED);
     Services.obs.removeObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION);
     Services.obs.removeObserver(this, "weave:service:login:change");
     Services.obs.removeObserver(this, "weave:service:ready");
+    Services.prefs.removeObserver("intl.uidirection", this);
     this._deckView.destroy();
   },
 
   observe(subject, topic, data) {
     switch (topic) {
       case this._SyncedTabs.TOPIC_TABS_CHANGED:
         this._syncedTabsListStore.getData();
         this.updatePanel();
         break;
       case "weave:service:ready":
         Services.obs.removeObserver(this, "weave:service:ready");
         // Intended fallthrough.
       case FxAccountsCommon.ONLOGIN_NOTIFICATION:
       case "weave:service:login:change":
         this.updatePanel();
         break;
+      case "nsPref:changed":
+        if (data == "intl.uidirection") {
+          this.updateDir();
+        }
+        break;
       default:
         break;
     }
   },
 
   // There's no good way to mock fxAccounts in browser tests where it's already
   // been instantiated, so we have this method for stubbing.
   _getSignedInUser() {
@@ -160,16 +170,28 @@ SyncedTabsDeckComponent.prototype = {
 
   updatePanel() {
     // return promise for tests
     return this.getPanelStatus()
       .then(panelId => this._deckStore.selectPanel(panelId))
       .catch(Cu.reportError);
   },
 
+  updateDir() {
+    // If the HTML document doesn't exist, we can't update the window
+    if (!this._window.document) return;
+
+    let pref = Services.prefs.getIntPref("intl.uidirection");
+    if (pref > 0 || (pref < 0 && Services.locale.isAppLocaleRTL)) {
+      this._window.document.body.dir = "rtl";
+    } else {
+      this._window.document.body.dir = "ltr";
+    }
+  },
+
   openSyncPrefs() {
     this._getChromeWindow(this._window).gSync.openPrefs("tabs-sidebar");
   },
 
   openConnectDevice() {
     this._getChromeWindow(this._window).gSync.openConnectAnotherDevice("tabs-sidebar");
   },
 };
--- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
@@ -89,30 +89,32 @@ add_task(async function testObserver() {
   sinon.stub(SyncedTabs, "syncTabs", () => Promise.resolve());
 
   sinon.spy(deckStore, "on");
   sinon.stub(deckStore, "setPanels");
 
   sinon.stub(listStore, "getData");
 
   let component = new SyncedTabsDeckComponent({
-    mockWindow,
+    window: mockWindow,
     deckStore,
     listStore,
     listComponent,
     SyncedTabs,
     DeckView: ViewMock,
   });
 
   sinon.spy(component, "observe");
   sinon.stub(component, "updatePanel");
+  sinon.stub(component, "updateDir");
 
   component.init();
   SyncedTabs.syncTabs.restore();
   Assert.ok(component.updatePanel.called, "triggers panel update during init");
+  Assert.ok(component.updateDir.called, "triggers UI direction update during init");
 
   Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED);
 
   Assert.ok(component.observe.calledWith(null, SyncedTabs.TOPIC_TABS_CHANGED),
     "component is notified");
 
   Assert.ok(listStore.getData.called, "gets list data");
   Assert.ok(component.updatePanel.calledTwice, "triggers panel update");
@@ -123,16 +125,21 @@ add_task(async function testObserver() {
     "component is notified of login");
   Assert.equal(component.updatePanel.callCount, 3, "triggers panel update again");
 
   Services.obs.notifyObservers(null, "weave:service:login:change");
 
   Assert.ok(component.observe.calledWith(null, "weave:service:login:change"),
     "component is notified of login change");
   Assert.equal(component.updatePanel.callCount, 4, "triggers panel update again");
+
+  Services.prefs.setIntPref("intl.uidirection", 100);
+
+  Assert.ok(component.updateDir.calledTwice, "triggers UI direction update");
+
 });
 
 add_task(async function testPanelStatus() {
   let deckStore = new SyncedTabsDeckStore();
   let listStore = new SyncedTabsListStore();
   let listComponent = {};
   let fxAccounts = {
     getSignedInUser() {}