diff --git a/reviewboard/reviews/context.py b/reviewboard/reviews/context.py
index 31deabf9333469dc44f889aed0a9e45fa15247b6..b6a021294000dddb4a0a6f4ffe424e5a2c10c491 100644
--- a/reviewboard/reviews/context.py
+++ b/reviewboard/reviews/context.py
@@ -97,8 +97,9 @@ def make_review_request_context(request, review_request, extra_context={}):
         extra_context['blocks'] = list(review_request.blocks.all())
 
     return dict({
-        'editable': (review_request.status == ReviewRequest.PENDING_REVIEW and
-                     review_request.is_mutable_by(request.user)),
+        'mutable_by_user': review_request.is_mutable_by(request.user),
+        'status_mutable_by_user':
+            review_request.is_status_mutable_by(request.user),
         'review_request': review_request,
         'upload_diff_form': upload_diff_form,
         'upload_screenshot_form': UploadScreenshotForm(),
diff --git a/reviewboard/static/rb/js/models/reviewRequestEditorModel.js b/reviewboard/static/rb/js/models/reviewRequestEditorModel.js
index 9a1b16b81879c5b6fe28d6113048deb44947a9a2..73a07df0c66d5fb4588cbf96d676dada97eec269 100644
--- a/reviewboard/static/rb/js/models/reviewRequestEditorModel.js
+++ b/reviewboard/static/rb/js/models/reviewRequestEditorModel.js
@@ -11,9 +11,12 @@ RB.ReviewRequestEditor = Backbone.Model.extend({
         editCount: 0,
         hasDraft: false,
         fileAttachmentComments: {},
+        mutableByUser: false,
         pendingSaveCount: 0,
         publishing: false,
-        reviewRequest: null
+        reviewRequest: null,
+        statusEditable: false,
+        statusMutableByUser: false
     },
 
     _jsonFieldMap: {
@@ -47,6 +50,9 @@ RB.ReviewRequestEditor = Backbone.Model.extend({
         reviewRequest.draft.on('saved', function() {
             this.trigger('saved');
         }, this);
+
+        this.listenTo(reviewRequest, 'change:state', this._computeEditable);
+        this._computeEditable();
     },
 
     /*
@@ -246,6 +252,25 @@ RB.ReviewRequestEditor = Backbone.Model.extend({
     },
 
     /*
+     * Computes the editable state of the review request and open/close states.
+     *
+     * The review request is editable if the user has edit permissions and it's
+     * not closed.
+     *
+     * The close state and accompanying description is editable if the user
+     * has the ability to close the review request and it's currently closed.
+     */
+    _computeEditable: function() {
+        var state = this.get('reviewRequest').get('state'),
+            pending = (state === RB.ReviewRequest.PENDING);
+
+        this.set({
+            editable: this.get('mutableByUser') && pending,
+            statusEditable: this.get('statusMutableByUser') && !pending
+        });
+    },
+
+    /*
      * Handler for when a FileAttachment or Screenshot is added.
      *
      * Listens for events on the FileAttachment or Screenshot and relays
diff --git a/reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js b/reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
index 644328b6f5c15ae2127b7604056515e238c0f147..0ba46c34ae8b9b9d6a764a8eda49aa80cf96f581 100644
--- a/reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
+++ b/reviewboard/static/rb/js/pages/views/tests/reviewablePageViewTests.js
@@ -16,10 +16,12 @@ describe('pages/views/ReviewablePageView', function() {
             el: $container,
             reviewRequestData: {
                 id: 123,
-                loaded: true
+                loaded: true,
+                state: RB.ReviewRequest.PENDING
             },
             editorData: {
-                editable: true
+                mutableByUser: true,
+                statusMutableByUser: true
             }
         });
 
diff --git a/reviewboard/static/rb/js/views/reviewRequestEditorView.js b/reviewboard/static/rb/js/views/reviewRequestEditorView.js
index 8f9a310489257de6388a61985c37870cf1460731..fe953b81938225ae7576f66474d4bc4a5f606acb 100644
--- a/reviewboard/static/rb/js/views/reviewRequestEditorView.js
+++ b/reviewboard/static/rb/js/views/reviewRequestEditorView.js
@@ -108,6 +108,9 @@ ClosedBannerView = BannerView.extend({
             label: gettext('Reopen for Review')
         }
     ],
+    fieldOptions: {
+        statusField: true
+    },
 
     events: {
         'click #btn-review-request-reopen': '_onReopenClicked'
@@ -131,9 +134,9 @@ DiscardedBannerView = ClosedBannerView.extend({
     id: 'discard-banner',
     title: gettext('This change has been discarded.'),
     describeText: gettext("Describe the reason it's discarded (optional):"),
-    fieldOptions: {
+    fieldOptions: _.defaults({
         closeType: RB.ReviewRequest.CLOSE_DISCARDED
-    }
+    }, ClosedBannerView.prototype.fieldOptions)
 });
 
 
@@ -144,9 +147,9 @@ SubmittedBannerView = ClosedBannerView.extend({
     id: 'submitted-banner',
     title: gettext('This change has been marked as submitted.'),
     describeText: gettext('Describe the submission (optional):'),
-    fieldOptions: {
+    fieldOptions: _.defaults({
         closeType: RB.ReviewRequest.CLOSE_SUBMITTED
-    }
+    }, ClosedBannerView.prototype.fieldOptions)
 });
 
 
@@ -491,13 +494,12 @@ RB.ReviewRequestEditorView = Backbone.View.extend({
                this._importFileAttachmentThumbnail,
                this);
 
-        this.model.on('change:editable', this._onEditableChanged, this);
-
         /*
          * Warn the user if they try to navigate away with unsaved comments.
          */
         window.onbeforeunload = _.bind(function(evt) {
-            if (this.model.get('editable') &&
+            if ((this.model.get('editable') ||
+                 this.model.get('statusEditable')) &&
                 this.model.get('editCount') > 0) {
                 /*
                  * On IE, the text must be set in evt.returnValue.
@@ -802,10 +804,13 @@ RB.ReviewRequestEditorView = Backbone.View.extend({
         var model = this.model,
             el = $el[0],
             id = el.id,
+            editableProp = (fieldOptions.statusField
+                            ? 'statusEditable'
+                            : 'editable'),
             options = {
                 cls: id + '-editor',
                 editIconClass: 'rb-icon rb-icon-edit',
-                enabled: this.model.get('editable'),
+                enabled: this.model.get(editableProp),
                 multiline: el.tagName === 'PRE',
                 showButtons: !$el.hasClass('screenshot-editable'),
                 useEditIconOnly: fieldOptions.useEditIconOnly,
@@ -851,6 +856,13 @@ RB.ReviewRequestEditorView = Backbone.View.extend({
                         this);
                 }, this)
             });
+
+        this.listenTo(
+            this.model,
+            'change:' + editableProp,
+            function(model, editable) {
+                $el.inlineEditor(editable ? 'enable' : 'disable');
+            });
     },
 
     /*
@@ -946,16 +958,6 @@ RB.ReviewRequestEditorView = Backbone.View.extend({
     },
 
     /*
-     * Handler for when the 'editable' property changes.
-     *
-     * Enables or disables all inlineEditors.
-     */
-    _onEditableChanged: function() {
-        this._$box.find('.edit, .editable')
-            .inlineEditor(this.model.get('editable') ? 'enable' : 'disable');
-    },
-
-    /*
      * Handler for when Close -> Discarded is clicked.
      */
     _onCloseDiscardedClicked: function() {
diff --git a/reviewboard/static/rb/js/views/tests/reviewRequestEditorViewTests.js b/reviewboard/static/rb/js/views/tests/reviewRequestEditorViewTests.js
index 287124f17184277141aff2c111651cdc7d72219d..c63bc3a1ab598e3c2c09f23dd30a46aea44195d0 100644
--- a/reviewboard/static/rb/js/views/tests/reviewRequestEditorViewTests.js
+++ b/reviewboard/static/rb/js/views/tests/reviewRequestEditorViewTests.js
@@ -52,7 +52,8 @@ describe('views/ReviewRequestEditorView', function() {
         });
 
         editor = new RB.ReviewRequestEditor({
-            editable: true,
+            mutableByUser: true,
+            statusMutableByUser: true,
             reviewRequest: reviewRequest,
             commentIssueManager: new RB.CommentIssueManager()
         });
@@ -454,6 +455,18 @@ describe('views/ReviewRequestEditorView', function() {
                     expect(reviewRequest.close).toHaveBeenCalled();
                 });
 
+                describe('State when statusEditable', function() {
+                    it('Disabled when false', function() {
+                        editor.set('statusEditable', false);
+                        expect($field.inlineEditor('option', 'enabled')).toBe(false);
+                    });
+
+                    it('Enabled when true', function() {
+                        editor.set('statusEditable', true);
+                        expect($field.inlineEditor('option', 'enabled')).toBe(true);
+                    });
+                });
+
                 describe('Formatting', function() {
                     it('Links', function() {
                         reviewRequest.draft.set('changeDescription',
diff --git a/reviewboard/templates/reviews/reviewable_page_data.js b/reviewboard/templates/reviews/reviewable_page_data.js
index bda132381bb7a998acfccb9ca608e1f78e65a54c..076bf109ed9cca3d330eadfde8ee673ee8fd36de 100644
--- a/reviewboard/templates/reviews/reviewable_page_data.js
+++ b/reviewboard/templates/reviews/reviewable_page_data.js
@@ -33,7 +33,8 @@
             testingDone: "{{review_request_details.testing_done|escapejs}}"
         },
         editorData: {
-            editable: {{editable|yesno:'true,false'}},
+            mutableByUser: {{mutable_by_user|yesno:'true,false'}},
+            statusMutableByUser: {{status_mutable_by_user|yesno:'true,false'}},
             fileAttachmentComments: {
 {% if all_file_attachments %}
 {%  for file_attachment in all_file_attachments %}
