diff --git a/src/Angular.js b/src/Angular.js
index 52e74cbf396c..e745e55498e9 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -1408,8 +1408,12 @@ function bootstrap(element, modules, config) {
     forEach(extraModules, function(module) {
       modules.push(module);
     });
-    doBootstrap();
+    return doBootstrap();
   };
+
+  if (isFunction(angular.resumeDeferredBootstrap)) {
+    angular.resumeDeferredBootstrap();
+  }
 }
 
 /**
diff --git a/src/ngScenario/Application.js b/src/ngScenario/Application.js
index 80dd15742f3b..e7d5bb86c956 100644
--- a/src/ngScenario/Application.js
+++ b/src/ngScenario/Application.js
@@ -68,19 +68,31 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
       try {
         var $window = self.getWindow_();
 
-        if ($window.angular) {
-          // Disable animations
-          $window.angular.resumeBootstrap([['$provide', function($provide) {
-            return ['$animate', function($animate) {
-              $animate.enabled(false);
-            }];
-          }]]);
+        if (!$window.angular) {
+          self.executeAction(loadFn);
+          return;
+        }
+
+        if (!$window.angular.resumeBootstrap) {
+          $window.angular.resumeDeferredBootstrap = resumeDeferredBootstrap;
+        } else {
+          resumeDeferredBootstrap();
         }
 
-        self.executeAction(loadFn);
       } catch (e) {
         errorFn(e);
       }
+
+      function resumeDeferredBootstrap() {
+        // Disable animations
+        var $injector = $window.angular.resumeBootstrap([['$provide', function($provide) {
+          return ['$animate', function($animate) {
+            $animate.enabled(false);
+          }];
+        }]]);
+        self.rootElement = $injector.get('$rootElement')[0];
+        self.executeAction(loadFn);
+      }
     }).attr('src', url);
 
     // for IE compatibility set the name *after* setting the frame url
@@ -105,7 +117,15 @@ angular.scenario.Application.prototype.executeAction = function(action) {
   if (!$window.angular) {
     return action.call(this, $window, _jQuery($window.document));
   }
-  angularInit($window.document, function(element) {
+
+  if (!!this.rootElement) {
+    executeWithElement(this.rootElement);
+  }
+  else {
+    angularInit($window.document, angular.bind(this, executeWithElement));
+  }
+
+  function executeWithElement(element) {
     var $injector = $window.angular.element(element).injector();
     var $element = _jQuery(element);
 
@@ -118,5 +138,5 @@ angular.scenario.Application.prototype.executeAction = function(action) {
         action.call(self, $window, $element);
       });
     });
-  });
+  }
 };
diff --git a/test/AngularSpec.js b/test/AngularSpec.js
index e63789100947..a45ee2c258c9 100644
--- a/test/AngularSpec.js
+++ b/test/AngularSpec.js
@@ -1081,6 +1081,26 @@ describe('angular', function() {
         window.name = originalName;
       });
 
+      it('should provide injector for deferred bootstrap', function() {
+        var injector;
+        window.name = 'NG_DEFER_BOOTSTRAP!';
+
+        injector = angular.bootstrap(element);
+        expect(injector).toBeUndefined();
+
+        injector = angular.resumeBootstrap();
+        expect(injector).toBeDefined();
+      });
+
+      it('should resume deferred bootstrap, if defined', function() {
+        var injector;
+        window.name = 'NG_DEFER_BOOTSTRAP!';
+
+        angular.resumeDeferredBootstrap = noop;
+        var spy = spyOn(angular, "resumeDeferredBootstrap");
+        injector = angular.bootstrap(element);
+        expect(spy).toHaveBeenCalled();
+      });
 
       it('should wait for extra modules', function() {
         window.name = 'NG_DEFER_BOOTSTRAP!';
diff --git a/test/ngScenario/ApplicationSpec.js b/test/ngScenario/ApplicationSpec.js
index b86a4e5eccdc..d120f21a12ce 100644
--- a/test/ngScenario/ApplicationSpec.js
+++ b/test/ngScenario/ApplicationSpec.js
@@ -118,6 +118,75 @@ describe('angular.scenario.Application', function() {
     expect(called).toBeTruthy();
   });
 
+  it('should set rootElement when navigateTo instigates bootstrap', inject(function($injector, $browser) {
+    var called;
+    var testWindow = {
+      document: jqLite('<div class="test-foo"></div>')[0],
+      angular: {
+        element: jqLite,
+        service: {},
+        resumeBootstrap: noop
+      }
+    };
+    jqLite(testWindow.document).data('$injector', $injector);
+    var resumeBootstrapSpy = spyOn(testWindow.angular, 'resumeBootstrap').andReturn($injector);
+
+    var injectorGet = $injector.get;
+    spyOn($injector, 'get').andCallFake(function(name) {
+      switch (name) {
+        case "$rootElement": return jqLite(testWindow.document);
+        default: return injectorGet(name);
+      }
+    });
+
+    app.getWindow_ = function() {
+      return testWindow;
+    };
+    app.navigateTo('http://localhost/', noop);
+    callLoadHandlers(app);
+    expect(app.rootElement).toBe(testWindow.document);
+    expect(resumeBootstrapSpy).toHaveBeenCalled();
+    dealoc(testWindow.document);
+  }));
+
+  it('should set setup resumeDeferredBootstrap if resumeBootstrap is not yet defined', inject(function($injector, $browser) {
+    var called;
+    var testWindow = {
+      document: jqLite('<div class="test-foo"></div>')[0],
+      angular: {
+        element: jqLite,
+        service: {},
+        resumeBootstrap: null
+      }
+    };
+    jqLite(testWindow.document).data('$injector', $injector);
+
+    var injectorGet = $injector.get;
+    var injectorSpy = spyOn($injector, 'get').andCallFake(function(name) {
+      switch (name) {
+        case "$rootElement": return jqLite(testWindow.document);
+        default: return injectorGet(name);
+      }
+    });
+
+    app.getWindow_ = function() {
+      return testWindow;
+    };
+    app.navigateTo('http://localhost/', noop);
+    expect(testWindow.angular.resumeDeferredBootstrap).toBeUndefined();
+    callLoadHandlers(app);
+    expect(testWindow.angular.resumeDeferredBootstrap).toBeDefined();
+    expect(app.rootElement).toBeUndefined;
+    expect(injectorSpy).not.toHaveBeenCalled();
+
+    var resumeBootstrapSpy = spyOn(testWindow.angular, 'resumeBootstrap').andReturn($injector);
+    testWindow.angular.resumeDeferredBootstrap();
+    expect(app.rootElement).toBe(testWindow.document);
+    expect(resumeBootstrapSpy).toHaveBeenCalled();
+    expect(injectorSpy).toHaveBeenCalledWith("$rootElement");
+    dealoc(testWindow.document);
+  }));
+
   it('should wait for pending requests in executeAction', inject(function($injector, $browser) {
     var called, polled;
     var handlers = [];
@@ -144,4 +213,32 @@ describe('angular.scenario.Application', function() {
     handlers[0]();
     dealoc(testWindow.document);
   }));
+
+  it('should allow explicit rootElement', inject(function($injector, $browser) {
+    var called, polled;
+    var handlers = [];
+    var testWindow = {
+      document: jqLite('<div class="test-foo"></div>')[0],
+      angular: {
+        element: jqLite,
+        service: {}
+      }
+    };
+    $browser.notifyWhenNoOutstandingRequests = function(fn) {
+      handlers.push(fn);
+    };
+    app.rootElement = testWindow.document;
+    jqLite(testWindow.document).data('$injector', $injector);
+    app.getWindow_ = function() {
+      return testWindow;
+    };
+    app.executeAction(function($window, $document) {
+      expect($window).toEqual(testWindow);
+      expect($document).toBeDefined();
+      expect($document[0].className).toEqual('test-foo');
+    });
+    expect(handlers.length).toEqual(1);
+    handlers[0]();
+    dealoc(testWindow.document);
+  }));
 });