diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee
index 2373385f75..5f690e9a8f 100644
--- a/atom/common/lib/asar.coffee
+++ b/atom/common/lib/asar.coffee
@@ -63,6 +63,15 @@ notFoundError = (asarPath, filePath, callback) ->
     throw error
   process.nextTick -> callback error
 
+# Create a ENOTDIR error.
+notDirError = (callback) ->
+  error = new Error('ENOTDIR, not a directory')
+  error.code = 'ENOTDIR'
+  error.errno = -20
+  unless typeof callback is 'function'
+    throw error
+  process.nextTick -> callback error
+
 # Create invalid archive error.
 invalidArchiveError = (asarPath, callback) ->
   error = new Error("Invalid package #{asarPath}")
@@ -351,6 +360,24 @@ exports.wrapFsWithAsar = (fs) ->
 
     if stats.isDirectory then return 1 else return 0
 
+  # Calling mkdir for directory inside asar archive should throw ENOTDIR
+  # error, but on Windows it throws ENOENT.
+  # This is to work around the recursive looping bug of mkdirp since it is
+  # widely used.
+  if process.platform is 'win32'
+    mkdir = fs.mkdir
+    fs.mkdir = (p, mode, callback) ->
+      callback = mode if typeof mode is 'function'
+      [isAsar, asarPath, filePath] = splitPath p
+      return notDirError callback if isAsar and filePath.length
+      mkdir p, mode, callback
+
+    mkdirSync = fs.mkdirSync
+    fs.mkdirSync = (p, mode) ->
+      [isAsar, asarPath, filePath] = splitPath p
+      notDirError() if isAsar and filePath.length
+      mkdirSync p, mode
+
   overrideAPI fs, 'open'
   overrideAPI child_process, 'execFile'
   overrideAPISync process, 'dlopen', 1
diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee
index 479443292b..7642283cea 100644
--- a/spec/asar-spec.coffee
+++ b/spec/asar-spec.coffee
@@ -374,6 +374,18 @@ describe 'asar package', ->
           assert.equal err.code, 'ENOENT'
           done()
 
+    describe 'fs.mkdir', ->
+      it 'throws error when calling inside asar archive', (done) ->
+        p = path.join fixtures, 'asar', 'a.asar', 'not-exist'
+        fs.mkdir p, (err) ->
+          assert.equal err.code, 'ENOTDIR'
+          done()
+
+    describe 'fs.mkdirSync', ->
+      it 'throws error when calling inside asar archive', ->
+        p = path.join fixtures, 'asar', 'a.asar', 'not-exist'
+        assert.throws (-> fs.mkdirSync p), new RegExp('ENOTDIR')
+
     describe 'child_process.fork', ->
       child_process = require 'child_process'
 
@@ -547,6 +559,13 @@ describe 'asar package', ->
     it 'does not touch global fs object', ->
       assert.notEqual fs.readdir, gfs.readdir
 
+  describe 'mkdirp module', ->
+    mkdirp = require 'mkdirp'
+
+    it 'throws error when calling inside asar archive', ->
+      p = path.join fixtures, 'asar', 'a.asar', 'not-exist'
+      assert.throws (-> mkdirp.sync p), new RegExp('ENOTDIR')
+
   describe 'native-image', ->
     it 'reads image from asar archive', ->
       p = path.join fixtures, 'asar', 'logo.asar', 'logo.png'
diff --git a/spec/package.json b/spec/package.json
index 79e7d954eb..6d49f0da8b 100644
--- a/spec/package.json
+++ b/spec/package.json
@@ -7,6 +7,7 @@
     "basic-auth": "^1.0.0",
     "graceful-fs": "3.0.5",
     "mocha": "2.1.0",
+    "mkdirp": "0.5.1",
     "multiparty": "4.1.2",
     "q": "0.9.7",
     "temp": "0.8.1",
diff --git a/spec/webview-spec.coffee b/spec/webview-spec.coffee
index 1dcf739ec0..4754ea4348 100644
--- a/spec/webview-spec.coffee
+++ b/spec/webview-spec.coffee
@@ -1,6 +1,7 @@
 assert = require 'assert'
 path   = require 'path'
 http   = require 'http'
+url    = require 'url'
 
 describe '<webview> tag', ->
   @timeout 10000
@@ -261,12 +262,12 @@ describe '<webview> tag', ->
     it 'emits when favicon urls are received', (done) ->
       webview.addEventListener 'page-favicon-updated', (e) ->
         assert.equal e.favicons.length, 2
-        url =
+        pageUrl =
           if process.platform is 'win32'
             'file:///C:/favicon.png'
           else
             'file:///favicon.png'
-        assert.equal e.favicons[0], url
+        assert.equal e.favicons[0], pageUrl
         done()
       webview.src = "file://#{fixtures}/pages/a.html"
       document.body.appendChild webview
@@ -281,7 +282,9 @@ describe '<webview> tag', ->
       document.body.appendChild webview
 
   describe 'did-navigate event', ->
-    pageUrl = "file://#{fixtures}/pages/webview-will-navigate.html"
+    p = path.join fixtures, 'pages', 'webview-will-navigate.html'
+    p = p.replace /\\/g, '/'
+    pageUrl = url.format protocol: 'file', slashes: true, pathname: p
 
     it 'emits when a url that leads to outside of the page is clicked', (done) ->
       webview.addEventListener 'did-navigate', (e) ->
@@ -293,7 +296,10 @@ describe '<webview> tag', ->
 
   describe 'did-navigate-in-page event', ->
     it 'emits when an anchor link is clicked', (done) ->
-      pageUrl = "file://#{fixtures}/pages/webview-did-navigate-in-page.html"
+      p = path.join fixtures, 'pages', 'webview-did-navigate-in-page.html'
+      p = p.replace /\\/g, '/'
+      pageUrl = url.format protocol: 'file', slashes: true, pathname: p
+
       webview.addEventListener 'did-navigate-in-page', (e) ->
         assert.equal e.url, "#{pageUrl}#test_content"
         done()
@@ -310,7 +316,10 @@ describe '<webview> tag', ->
       document.body.appendChild webview
 
     it 'emits when window.location.hash is changed', (done) ->
-      pageUrl = "file://#{fixtures}/pages/webview-did-navigate-in-page-with-hash.html"
+      p = path.join fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'
+      p = p.replace /\\/g, '/'
+      pageUrl = url.format protocol: 'file', slashes: true, pathname: p
+
       webview.addEventListener 'did-navigate-in-page', (e) ->
         assert.equal e.url, "#{pageUrl}#test"
         done()