diff --git a/reviewboard/static/rb/js/views/commentDialogView.js b/reviewboard/static/rb/js/views/commentDialogView.js
index 27bd054cb345a3ee568acad223a5b6ef15bb8cac..51b4c88ca52b43f4ccfeb9d1e9b2ce48ba2cb67c 100644
--- a/reviewboard/static/rb/js/views/commentDialogView.js
+++ b/reviewboard/static/rb/js/views/commentDialogView.js
@@ -504,8 +504,16 @@ RB.CommentDialogView = Backbone.View.extend({
      * and closes the dialog.
      */
     _onCancelClicked: function() {
-        this.model.cancel();
-        this.close();
+        var shouldExit = true;
+
+        if (this.model.get('dirty')) {
+            shouldExit = confirm(gettext('You have unsaved changes, are you sure you want to exit?'));
+        }
+
+        if (shouldExit) {
+            this.model.cancel();
+            this.close();
+        }
     },
 
     /*
diff --git a/reviewboard/static/rb/js/views/tests/commentDialogViewTests.js b/reviewboard/static/rb/js/views/tests/commentDialogViewTests.js
index 087926078dad43aeb8e23c287f97698ce5080d27..e411310d5f05cfeb84d19ad1a5c0200f48898659 100644
--- a/reviewboard/static/rb/js/views/tests/commentDialogViewTests.js
+++ b/reviewboard/static/rb/js/views/tests/commentDialogViewTests.js
@@ -125,6 +125,24 @@ suite('rb/views/CommentDialogView', function() {
                     expect(dlg.close).toHaveBeenCalled();
                 });
 
+                it('Confirms before cancelling unsaved comment', function() {
+                    spyOn(editor, 'cancel');
+                    spyOn(dlg, 'close');
+                    spyOn(window, 'confirm').andReturn(true);
+                    editor.set('dirty', true);
+                    $button.click();
+                    expect(dlg.close).toHaveBeenCalled();
+                });
+
+                it('Cancel close when unsaved comment', function() {
+                    spyOn(editor, 'cancel');
+                    spyOn(dlg, 'close');
+                    spyOn(window, 'confirm').andReturn(false);
+                    editor.set('dirty', true);
+                    $button.click();
+                    expect(dlg.close).not.toHaveBeenCalled();
+                });
+
                 describe('Visibility', function() {
                     it('Shown when canEdit=true', function() {
                         editor.set('canEdit', true);
@@ -724,10 +742,12 @@ suite('rb/views/CommentDialogView', function() {
                     });
 
                     it('If Markdown', function() {
+                        spyOn(window, 'confirm').andReturn(true);
                         setupForRichText(true);
 
                         simulateKeyPress($.ui.keyCode.ESCAPE, false, false);
                         expect(editor.cancel).toHaveBeenCalled();
+                        expect(window.confirm).toHaveBeenCalled();
                         expect(dlg.close).toHaveBeenCalled();
                     });
 
@@ -738,6 +758,26 @@ suite('rb/views/CommentDialogView', function() {
                         expect(editor.cancel).toHaveBeenCalled();
                         expect(dlg.close).toHaveBeenCalled();
                     });
+
+                    it('If unsaved comment', function() {
+                        spyOn(window, 'confirm').andReturn(true);
+                        editor.set('dirty', true);
+
+                        simulateKeyPress($.ui.keyCode.ESCAPE, false, false);
+                        expect(editor.cancel).toHaveBeenCalled();
+                        expect(window.confirm).toHaveBeenCalled();
+                        expect(dlg.close).toHaveBeenCalled();
+                    });
+
+                    it('If unsaved comment, do not close', function() {
+                        spyOn(window, 'confirm').andReturn(false);
+                        editor.set('dirty', true);
+
+                        simulateKeyPress($.ui.keyCode.ESCAPE, false, false);
+                        expect(editor.cancel).not.toHaveBeenCalled();
+                        expect(window.confirm).toHaveBeenCalled();
+                        expect(dlg.close).not.toHaveBeenCalled();
+                    });
                 });
             });
 
