diff --git a/DEPS b/DEPS
index 083144e3..c33d18f 100644
--- a/DEPS
+++ b/DEPS
@@ -43,7 +43,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'eae618137190cfe34670243e10b5f1d7fe586b2a',
+  'v8_revision': '951fd121057e09553b46c1e067bad9bd4f831c75',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/chrome/VERSION b/chrome/VERSION
index 11036d83..d9d715a 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=49
 MINOR=0
-BUILD=2605
+BUILD=2606
 PATCH=0
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index d501e18..557b200 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2269,8 +2269,21 @@
 
   if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled))
     web_prefs->javascript_enabled = false;
-  if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled))
+
+  // Only allow disabling web security via the command-line flag if the user
+  // has specified a distinct profile directory. This still enables tests to
+  // disable web security by setting the pref directly.
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled)) {
     web_prefs->web_security_enabled = false;
+  } else if (!web_prefs->web_security_enabled &&
+             command_line->HasSwitch(switches::kDisableWebSecurity) &&
+             !command_line->HasSwitch(switches::kUserDataDir)) {
+    LOG(ERROR) << "Web security may only be disabled if '--user-data-dir' is "
+               "also specified.";
+    web_prefs->web_security_enabled = true;
+  }
+
   if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled))
     web_prefs->plugins_enabled = false;
   web_prefs->loads_images_automatically =
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index b9ea7ad..10e9520 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -1689,11 +1689,14 @@
       break; // Nothing to do for DETACH_ABOVE_OR_BELOW.
   }
 
-  // To account for the extra vertical on restored windows that is absent on
-  // maximized windows, add an additional vertical offset extracted from the tab
-  // strip.
-  if (source->GetWidget()->IsMaximized())
-    new_bounds.Offset(0, -source->kNewTabButtonVerticalOffset);
+  // Account for the extra space above the tabstrip on restored windows versus
+  // maximized windows.
+  if (source->GetWidget()->IsMaximized()) {
+    const auto* frame_view = static_cast<BrowserNonClientFrameView*>(
+        source->GetWidget()->non_client_view()->frame_view());
+    new_bounds.Offset(
+        0, frame_view->GetTopInset(false) - frame_view->GetTopInset(true));
+  }
   return new_bounds;
 }
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index a1751b1..0328f7f5 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -123,6 +123,9 @@
 const int kPinnedToNonPinnedOffset = 3;
 #endif
 
+// The vertical offset of the tab strip button.
+const int kNewTabButtonVerticalOffset = 7;
+
 // Returns the size of the new tab button, not including any bounds extension to
 // enlarge the clickable area.
 gfx::Size GetNewTabButtonSize() {
@@ -449,7 +452,7 @@
   if (ui::MaterialDesignController::IsModeMaterial()) {
     SkPath border;
     const float scale = GetWidget()->GetCompositor()->device_scale_factor();
-    GetBorderPath(TabStrip::kNewTabButtonVerticalOffset * scale, scale,
+    GetBorderPath(kNewTabButtonVerticalOffset * scale, scale,
                   tab_strip_->SizeTabButtonToTopOfTabStrip(), &border);
     mask->addPath(border, SkMatrix::MakeScale(1 / scale));
   } else if (tab_strip_->SizeTabButtonToTopOfTabStrip()) {
@@ -461,7 +464,7 @@
     mask->addRect(RectToSkRect(button_bounds));
   } else {
     SkScalar w = SkIntToScalar(width());
-    SkScalar v_offset = SkIntToScalar(TabStrip::kNewTabButtonVerticalOffset);
+    SkScalar v_offset = SkIntToScalar(kNewTabButtonVerticalOffset);
 
     // These values are defined by the shape of the new tab image. Should that
     // image ever change, these values will need to be updated. They're so
@@ -572,8 +575,7 @@
       // no flip.
       x += size.width();
     }
-    canvas->TileImageInt(*background, x,
-                         TabStrip::kNewTabButtonVerticalOffset + offset_y,
+    canvas->TileImageInt(*background, x, kNewTabButtonVerticalOffset + offset_y,
                          x_scale, 1.0f, 0, 0, size.width(), size.height());
 
     // For non-MD, adjust the alpha of the fill to match that of inactive tabs
@@ -659,9 +661,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // TabStrip, public:
 
-// static
-const int TabStrip::kNewTabButtonVerticalOffset = 7;
-
 TabStrip::TabStrip(TabStripController* controller)
     : controller_(controller),
       newtab_button_(NULL),
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index aa09764..76a741c8c 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -58,10 +58,6 @@
                  public views::ViewTargeterDelegate,
                  public TabController {
  public:
-  // The vertical offset of the tab strip button. This offset applies only to
-  // restored windows.
-  static const int kNewTabButtonVerticalOffset;
-
   explicit TabStrip(TabStripController* controller);
   ~TabStrip() override;
 
diff --git a/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc b/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc
index 7b92e33e..7aeb5f1 100644
--- a/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc
+++ b/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc
@@ -300,8 +300,6 @@
 #if !defined(OS_CHROMEOS)
 TEST_F(SyncSetupHandlerFirstSigninTest, DisplayBasicLogin) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Ensure that the user is not signed in before calling |HandleStartSignin()|.
@@ -324,8 +322,6 @@
 
 TEST_F(SyncSetupHandlerTest, ShowSyncSetupWhenNotSignedIn) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   handler_->HandleShowSetupUI(NULL);
@@ -359,8 +355,6 @@
 // it is displaying the spinner to the user.
 TEST_F(SyncSetupHandlerTest, DisplayConfigureWithBackendDisabledAndCancel) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -385,8 +379,6 @@
 TEST_F(SyncSetupHandlerTest,
        DisplayConfigureWithBackendDisabledAndSyncStartupCompleted) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -436,8 +428,6 @@
 TEST_F(SyncSetupHandlerTest,
        DisplayConfigureWithBackendDisabledAndCancelAfterSigninSuccess) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -462,8 +452,6 @@
 TEST_F(SyncSetupHandlerTest,
        DisplayConfigureWithBackendDisabledAndSigninFailed) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -496,8 +484,6 @@
 
 TEST_F(SyncSetupHandlerNonCrosTest, HandleGaiaAuthFailure) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasUnrecoverableError())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
@@ -511,8 +497,6 @@
 // TODO(kochi): We need equivalent tests for ChromeOS.
 TEST_F(SyncSetupHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Open the web UI.
@@ -523,8 +507,6 @@
 
 TEST_F(SyncSetupHandlerNonCrosTest, GaiaErrorInitializingSync) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Open the web UI.
@@ -774,8 +756,6 @@
       SigninErrorControllerFactory::GetForProfile(profile_.get()));
   provider.SetAuthError(kTestUser, error_);
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 930005d3..3be38c6b 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -304,8 +304,6 @@
 #if !defined(OS_CHROMEOS)
 TEST_F(PeopleHandlerFirstSigninTest, DisplayBasicLogin) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Ensure that the user is not signed in before calling |HandleStartSignin()|.
@@ -328,8 +326,6 @@
 
 TEST_F(PeopleHandlerTest, ShowSyncSetupWhenNotSignedIn) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   handler_->HandleShowSetupUI(NULL);
@@ -363,8 +359,6 @@
 // it is displaying the spinner to the user.
 TEST_F(PeopleHandlerTest, DisplayConfigureWithBackendDisabledAndCancel) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -389,8 +383,6 @@
 TEST_F(PeopleHandlerTest,
        DisplayConfigureWithBackendDisabledAndSyncStartupCompleted) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -440,8 +432,6 @@
 TEST_F(PeopleHandlerTest,
        DisplayConfigureWithBackendDisabledAndCancelAfterSigninSuccess) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -466,8 +456,6 @@
 TEST_F(PeopleHandlerTest,
        DisplayConfigureWithBackendDisabledAndSigninFailed) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
@@ -500,8 +488,6 @@
 
 TEST_F(PeopleHandlerNonCrosTest, HandleGaiaAuthFailure) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasUnrecoverableError())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
@@ -515,8 +501,6 @@
 // TODO(kochi): We need equivalent tests for ChromeOS.
 TEST_F(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Open the web UI.
@@ -527,8 +511,6 @@
 
 TEST_F(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync) {
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, HasSyncSetupCompleted())
       .WillRepeatedly(Return(false));
   // Open the web UI.
@@ -778,8 +760,6 @@
       SigninErrorControllerFactory::GetForProfile(profile_.get()));
   provider.SetAuthError(kTestUser, error_);
   EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, IsOAuthRefreshTokenAvailable())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_pss_, IsPassphraseRequired())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 6d73f09c..d5e408a 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-7771.0.0
\ No newline at end of file
+7774.0.0
\ No newline at end of file
diff --git a/components/browser_sync/browser/profile_sync_service.cc b/components/browser_sync/browser/profile_sync_service.cc
index 4dd43afd5..66f572df 100644
--- a/components/browser_sync/browser/profile_sync_service.cc
+++ b/components/browser_sync/browser/profile_sync_service.cc
@@ -253,14 +253,6 @@
   return IsSyncAllowed() && IsSyncRequested() && IsSignedIn();
 }
 
-bool ProfileSyncService::IsOAuthRefreshTokenAvailable() {
-  if (!oauth2_token_service_)
-    return false;
-
-  return oauth2_token_service_->RefreshTokenIsAvailable(
-      signin_->GetAccountIdToUse());
-}
-
 void ProfileSyncService::Initialize() {
   sync_client_->Initialize(this);
 
diff --git a/components/browser_sync/browser/profile_sync_service.h b/components/browser_sync/browser/profile_sync_service.h
index 39b22b4..3ab8909 100644
--- a/components/browser_sync/browser/profile_sync_service.h
+++ b/components/browser_sync/browser/profile_sync_service.h
@@ -344,10 +344,6 @@
   void RegisterAuthNotifications();
   void UnregisterAuthNotifications();
 
-  // Return whether OAuth2 refresh token is loaded and available for the backend
-  // to start up. Virtual to enable mocking in tests.
-  virtual bool IsOAuthRefreshTokenAvailable();
-
   // Returns the SyncableService for syncer::SESSIONS.
   virtual syncer::SyncableService* GetSessionsSyncableService();
 
diff --git a/components/browser_sync/browser/profile_sync_service_mock.h b/components/browser_sync/browser/profile_sync_service_mock.h
index c610b87..b05fec4 100644
--- a/components/browser_sync/browser/profile_sync_service_mock.h
+++ b/components/browser_sync/browser/profile_sync_service_mock.h
@@ -86,7 +86,6 @@
 
   MOCK_CONST_METHOD0(CanSyncStart, bool());
   MOCK_CONST_METHOD0(IsManaged, bool());
-  MOCK_METHOD0(IsOAuthRefreshTokenAvailable, bool());
 
   MOCK_CONST_METHOD0(IsPassphraseRequired, bool());
   MOCK_CONST_METHOD0(IsPassphraseRequiredForDecryption, bool());
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
new file mode 100644
index 0000000..e02e97c
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingDesign.md
@@ -0,0 +1,259 @@
+# Design of V8 bindings
+
+This document explains key concepts in the V8 binding architecture
+except the lifetime management of DOM wrappers.
+See [V8GCController.md](V8GCController.md) to learn the lifetime management.
+
+[TOC]
+
+## Isolate
+
+An isolate is a concept of a thread in V8.
+Isolates and threads are in 1:1 relationship.
+One isolate is associated with the main thread.
+One isolate is associated with one worker thread.
+
+## Context
+
+A context is a concept of a global variable scope in V8.
+Roughly speaking, one window object corresponds to one context.
+For example, `<iframe>` has a window object different from a window object
+of its parent frame. So the context of the `<iframe>` is different from
+the context of the parent frame. Since these contexts create their own
+global variable scopes, global variables and prototype chains of the `<iframe>`
+are isolated from the ones of the parent frame.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var foo = 1234;
+String.prototype.substr =
+    function (position, length) { // Hijacks String.prototype.substr
+        console.log(length);
+        return "hijacked";
+    };
+</script>
+</body></html>
+
+// iframe.html
+<script>
+console.log(foo);  // undefined
+var bar = "aaaa".substr(0, 2);  // Nothing is logged.
+console.log(bar);  // "aa"
+</script>
+```
+
+In summary, each frame has a window object.
+Each window object has a context.
+Each context has its own global variable scope and prototype chains.
+
+## Entered context and current context
+
+A relationship between isolates and contexts is interesting.
+One isolate has to execute JavaScripts in multiple frames,
+each of which has its own context. This means that the context associated
+with the isolate changes over time. In other words, the relationship between
+isolates and contexts is 1:N over the lifetime of the isolate.
+
+Here we have a concept of an entered context and a current context.
+To understand the difference, you need to understand two kinds of
+runtime stacks.
+
+The first stack is a stack of JavaScript functions.
+This stack is managed by V8. When one function calls another function,
+the callee function is pushed onto the stack. When that function returns,
+the function is popped from the stack and the control returns to the caller
+function that is now on the top of the stack. Each function has
+an associated context. We call the context of the function
+that is currently running (i.e., the context of the function that is on the top
+of the stack) a current context.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var iframe = document.querySelector("iframe");
+iframe.onload = function () {
+    iframe.contentWindow.func();
+}
+</script>
+</body></html>
+
+// iframe.html
+<script>
+function func() {
+  ...;
+}
+</script>
+```
+
+In the above example, at the point when func() is running,
+the current context is the context of the `<iframe>`.
+
+There is a second stack that operates on a much coarser granularity.
+This stack is managed by V8 binding (not by V8).
+When V8 binding invokes JavaScript, V8 binding enters a context
+and pushes the context onto the stack.
+The JavaScript starts running on the context. When the JavaScript finishes
+and the control returns back to V8 binding, V8 binding pops the context
+from the stack. Given that the control between V8 binding and V8 can be nested
+(i.e., V8 binding invokes JavaScript, which calls into V8 binding,
+which invokes another JavaScript etc), these contexts form a stack.
+The pushing and popping are done by calling v8::Context::Enter() and
+v8::Context::Exit() (or v8::Context::Scope). We call the most recently entered
+context an entered context.
+
+In the above example, at the point when func() is running,
+the entered context is the context of the main frame
+(not the context of `<iframe>`).
+
+The entered context is a concept to implement the
+[entry settings object](https://html.spec.whatwg.org/multipage/webappapis.html#entry-settings-object)
+of the HTML spec. The current context is a concept to implement the
+[incumbent settings object](https://html.spec.whatwg.org/multipage/webappapis.html#incumbent-settings-object)
+of the HTML spec.
+
+In summary, the entered context is a context from which the current JavaScript
+execution was started. The current context is a context of
+the JavaScript function that is currently running.
+
+## World
+
+A world is a concept to sandbox DOM wrappers among content scripts of
+Chrome extensions. There are three kinds of worlds: a main world,
+an isolated world and a worker world.
+A main world is a world where a normal JavaScript downloaded from the web
+is executed.
+An isolated world is a world where a content script of a Chrome extension.
+An isolate of the main thread has 1 main world and N isolated worlds.
+An isolate of a worker thread has 1 worker world and 0 isolated world.
+[This diagram](https://drive.google.com/file/d/0B1obCOyvTnPKQmJEWkVtOEN2TmM/view?usp=sharing)
+will be helpful to understand the relationship.
+
+All worlds in one isolate share underlying C++ DOM objects,
+but each world has its own DOM wrappers. That way the worlds in one isolate
+can operate on the same C++ DOM object without sharing any DOM wrapper
+among the worlds.
+
+Also each world has its own context.
+This means that each world has its own global variable scope and
+prototype chains.
+
+As a result of the sandboxing, the worlds in one isolate cannot share
+any DOM wrappers or contexts but can share underlying C++ DOM objects.
+The fact that no DOM wrappers or contexts are shared means that no JavaScript
+objects are shared among the worlds. That way we guarantee the security model
+that Chrome extensions doesn't share any JavaScript objects while sharing
+the underlying C++ DOM objects. This sandbox allows the Chrome extensions to run
+untrusted JavaScripts on a shared DOM structure.
+
+(Note: An isolated world is a concept of V8 binding,
+whereas an isolate and a context are a concept of V8.
+V8 does not know what isolated worlds are in an isolate.)
+
+In summary, an isolate of the main thread consists of 1 main world
+and N isolated worlds. An isolate of a worker thread consists of
+1 worker world and 0 isolated world. All worlds in one isolate share the
+underlying C++ DOM objects, but each world has its own DOM wrappers.
+Each world has its own context and thus has its own global variable scope
+and prototype chains.
+
+## A relationship between isolates, contexts, worlds and frames
+
+Let's wrap up the relationship between isolates, contexts, worlds and frames.
+
+* As a requirement of the DOM side, one HTML page has N frames.
+Each frame has its own context.
+
+* As a requirement of the JavaScript side, one isolate has M worlds.
+Each world has its own context.
+
+As a result, when we execute the main thread where N frames and M worlds
+are involved, there exists N * M contexts. In other words, one context is
+created for each pair of (frame, world).
+[This diagram](https://drive.google.com/file/d/0B1obCOyvTnPKSERSMmpRVjVKQWc/view?usp=sharing)
+will be helpful to understand the relationship.
+
+The main thread can have only one current context at one time,
+but the main thread can have the N * M contexts over its lifetime.
+For example, when the main thread is operating on a frame X using a JavaScript
+in a world Y, the current context is set to a context for the pair of (X, Y).
+The current context of the main thread changes over its lifetime.
+
+On the other hand, a worker thread has 0 frame and 1 world.
+Thus a worker thread has only 1 context.
+The current context of the worker thread never changes.
+
+## DOM wrappers and worlds
+
+For compatibility reasons (although this is not speced),
+we need to make sure that the same DOM wrapper is returned to JavaScript
+as long as the underlying C++ DOM object is alive.
+We should not return different DOM wrappers for the same C++ DOM object.
+
+Here is an example:
+
+```html
+var div = document.createElement("div");
+div.foo = 1234;  // expando
+var p = document.createElement("p");
+p.appendChild(div);
+div = null;
+gc();
+console.log(p.firstChild.foo);  // This should be 1234, not undefined
+```
+
+To accomplish the semantics that the same DOM wrapper is returned to JavaScript
+as long as the underlying C++ DOM object is alive, we need a mapping
+from the C++ DOM objects to the DOM wrappers.
+In addition, we need to sandbox DOM wrappers in each world.
+To meet the requirements, we make each world hold a DOM wrapper storage
+that stores a mapping from the C++ DOM objects to the DOM wrappers in that world.
+
+As a result, we have multiple DOM wrapper storages in one isolate.
+The mapping of the main world is written in ScriptWrappable.
+If ScriptWrappable::m_wrapper has a non-empty value, it is a DOM wrapper of
+the C++ DOM object of the main world.
+The mapping of other worlds are written in DOMWrapperMap.
+
+## DOM wrappers and contexts
+
+When you create a new DOM wrapper, you need to choose a correct context
+on which the DOM wrapper is created. If you create a new DOM wrapper in a
+wrong context, you will end up with leaking JavaScript objects to other
+contexts, which is very likely to cause security issues.
+
+Here is an example:
+
+```html
+// main.html
+<html><body>
+<iframe src="iframe.html"></iframe>
+<script>
+var iframe = document.querySelector("iframe");
+iframe;  // The wrapper of the iframe should be created in the context of the main frame.
+iframe.contentDocument;  // The wrapper of the document should be created in the context of the iframe.
+iframe.contentDocument.addEventListener("click",
+    function (event) {  // The wrapper of the event should be created in the context of the iframe.
+        event.target;
+    });
+</script>
+</body></html>
+
+// iframe.html
+<script>
+</script>
+```
+
+To make sure that a DOM wrapper is created in a correct context, you need to
+make sure that the current context must be set to the correct context
+whenever you call toV8(). If you're not sure what context to use,
+ask haraken@chromium.org.
+
diff --git a/third_party/WebKit/Source/wtf/Vector.h b/third_party/WebKit/Source/wtf/Vector.h
index b2f295435..46ada79 100644
--- a/third_party/WebKit/Source/wtf/Vector.h
+++ b/third_party/WebKit/Source/wtf/Vector.h
@@ -127,16 +127,16 @@
 
 template <typename T>
 struct VectorMover<false, T> {
-    static void move(const T* src, const T* srcEnd, T* dst)
+    static void move(T* src, T* srcEnd, T* dst)
     {
         while (src != srcEnd) {
-            new (NotNull, dst) T(*src);
+            new (NotNull, dst) T(std::move(*src));
             src->~T();
             ++dst;
             ++src;
         }
     }
-    static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
+    static void moveOverlapping(T* src, T* srcEnd, T* dst)
     {
         if (src > dst) {
             move(src, srcEnd, dst);
@@ -145,7 +145,7 @@
             while (src != srcEnd) {
                 --srcEnd;
                 --dstEnd;
-                new (NotNull, dstEnd) T(*srcEnd);
+                new (NotNull, dstEnd) T(std::move(*srcEnd));
                 srcEnd->~T();
             }
         }
@@ -267,12 +267,12 @@
         VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
     }
 
-    static void move(const T* src, const T* srcEnd, T* dst)
+    static void move(T* src, T* srcEnd, T* dst)
     {
         VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
     }
 
-    static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
+    static void moveOverlapping(T* src, T* srcEnd, T* dst)
     {
         VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
     }
@@ -745,16 +745,16 @@
     void clear() { shrinkCapacity(0); }
 
     template <typename U> void append(const U*, size_t);
-    template <typename U> void append(const U&);
-    template <typename U> void uncheckedAppend(const U& val);
+    template <typename U> void append(U&&);
+    template <typename U> void uncheckedAppend(U&& val);
     template <typename U, size_t otherCapacity, typename V> void appendVector(const Vector<U, otherCapacity, V>&);
 
     template <typename U> void insert(size_t position, const U*, size_t);
-    template <typename U> void insert(size_t position, const U&);
+    template <typename U> void insert(size_t position, U&&);
     template <typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&);
 
     template <typename U> void prepend(const U*, size_t);
-    template <typename U> void prepend(const U&);
+    template <typename U> void prepend(U&&);
     template <typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&);
 
     void remove(size_t position);
@@ -795,10 +795,15 @@
 
 private:
     void expandCapacity(size_t newMinCapacity);
-    const T* expandCapacity(size_t newMinCapacity, const T*);
+    T* expandCapacity(size_t newMinCapacity, T*);
+    T* expandCapacity(size_t newMinCapacity, const T* data)
+    {
+        return expandCapacity(newMinCapacity, const_cast<T*>(data));
+    }
+
     template <typename U> U* expandCapacity(size_t newMinCapacity, U*);
     void shrinkCapacity(size_t newCapacity);
-    template <typename U> void appendSlowCase(const U&);
+    template <typename U> void appendSlowCase(U&&);
 
     using Base::m_size;
     using Base::buffer;
@@ -978,7 +983,7 @@
 }
 
 template <typename T, size_t inlineCapacity, typename Allocator>
-const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, const T* ptr)
+T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, T* ptr)
 {
     if (ptr < begin() || ptr >= end()) {
         expandCapacity(newMinCapacity);
@@ -1139,31 +1144,31 @@
 
 template <typename T, size_t inlineCapacity, typename Allocator>
 template <typename U>
-ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val)
+ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(U&& val)
 {
     ASSERT(Allocator::isAllocationAllowed());
     if (LIKELY(size() != capacity())) {
         ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-        new (NotNull, end()) T(val);
+        new (NotNull, end()) T(std::forward<U>(val));
         ++m_size;
         return;
     }
 
-    appendSlowCase(val);
+    appendSlowCase(std::forward<U>(val));
 }
 
 template <typename T, size_t inlineCapacity, typename Allocator>
 template <typename U>
-NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val)
+NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(U&& val)
 {
     ASSERT(size() == capacity());
 
-    const U* ptr = &val;
+    typename std::remove_reference<U>::type* ptr = &val;
     ptr = expandCapacity(size() + 1, ptr);
     ASSERT(begin());
 
     ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-    new (NotNull, end()) T(*ptr);
+    new (NotNull, end()) T(std::forward<U>(*ptr));
     ++m_size;
 }
 
@@ -1172,16 +1177,15 @@
 
 template <typename T, size_t inlineCapacity, typename Allocator>
 template <typename U>
-ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U& val)
+ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(U&& val)
 {
 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
     // Vectors in ASAN builds don't have inlineCapacity.
-    append(val);
+    append(std::forward<U>(val));
 #else
     ASSERT(size() < capacity());
     ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-    const U* ptr = &val;
-    new (NotNull, end()) T(*ptr);
+    new (NotNull, end()) T(std::forward<U>(val));
     ++m_size;
 #endif
 }
@@ -1214,11 +1218,11 @@
 
 template <typename T, size_t inlineCapacity, typename Allocator>
 template <typename U>
-inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U& val)
+inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, U&& val)
 {
     ASSERT(Allocator::isAllocationAllowed());
     RELEASE_ASSERT(position <= size());
-    const U* data = &val;
+    typename std::remove_reference<U>::type* data = &val;
     if (size() == capacity()) {
         data = expandCapacity(size() + 1, data);
         ASSERT(begin());
@@ -1226,7 +1230,7 @@
     ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
     T* spot = begin() + position;
     TypeOperations::moveOverlapping(spot, end(), spot + 1);
-    new (NotNull, spot) T(*data);
+    new (NotNull, spot) T(std::forward<U>(*data));
     ++m_size;
 }
 
@@ -1246,9 +1250,9 @@
 
 template <typename T, size_t inlineCapacity, typename Allocator>
 template <typename U>
-inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val)
+inline void Vector<T, inlineCapacity, Allocator>::prepend(U&& val)
 {
-    insert(0, val);
+    insert(0, std::forward<U>(val));
 }
 
 template <typename T, size_t inlineCapacity, typename Allocator>
diff --git a/third_party/WebKit/Source/wtf/VectorTest.cpp b/third_party/WebKit/Source/wtf/VectorTest.cpp
index 2ede057..d06b47b 100644
--- a/third_party/WebKit/Source/wtf/VectorTest.cpp
+++ b/third_party/WebKit/Source/wtf/VectorTest.cpp
@@ -189,7 +189,6 @@
     for (index = 0; index < vector.size(); index++) {
         OwnPtr<DestructCounter>& refCounter = vector[index];
         EXPECT_EQ(index, static_cast<size_t>(refCounter->get()));
-        index++;
     }
     EXPECT_EQ(0, destructNumber);
 
@@ -228,6 +227,71 @@
     EXPECT_EQ(count, static_cast<size_t>(destructNumber));
 }
 
+class MoveOnly {
+public:
+    explicit MoveOnly(int i = 0)
+        : m_i(i)
+    { }
+
+    MoveOnly(MoveOnly&& other)
+        : m_i(other.m_i)
+    {
+        other.m_i = 0;
+    }
+
+    MoveOnly& operator=(MoveOnly&& other)
+    {
+        if (this != &other) {
+            m_i = other.m_i;
+            other.m_i = 0;
+        }
+        return *this;
+    }
+
+    int value() const { return m_i; }
+
+private:
+    WTF_MAKE_NONCOPYABLE(MoveOnly);
+    int m_i;
+};
+
+TEST(VectorTest, MoveOnlyType)
+{
+    WTF::Vector<MoveOnly> vector;
+    vector.append(MoveOnly(1));
+    vector.append(MoveOnly(2));
+    EXPECT_EQ(2u, vector.size());
+
+    ASSERT_EQ(1, vector.first().value());
+    ASSERT_EQ(2, vector.last().value());
+
+    vector.remove(0);
+    EXPECT_EQ(2, vector[0].value());
+    EXPECT_EQ(1u, vector.size());
+
+    MoveOnly moveOnly(std::move(vector[0]));
+    vector.remove(0);
+    ASSERT_EQ(2, moveOnly.value());
+    ASSERT_EQ(0u, vector.size());
+
+    size_t count = vector.capacity() + 1;
+    for (size_t i = 0; i < count; i++)
+        vector.append(MoveOnly(i + 1)); // +1 to distinguish from default-constructed.
+
+    // Reallocation did not affect the vector's content.
+    EXPECT_EQ(count, vector.size());
+    for (size_t i = 0; i < vector.size(); i++)
+        EXPECT_EQ(static_cast<int>(i + 1), vector[i].value());
+
+    WTF::Vector<MoveOnly> otherVector;
+    vector.swap(otherVector);
+    EXPECT_EQ(count, otherVector.size());
+    EXPECT_EQ(0u, vector.size());
+
+    vector = std::move(otherVector);
+    EXPECT_EQ(count, vector.size());
+}
+
 // WrappedInt class will fail if it was memmoved or memcpyed.
 static HashSet<void*> constructedWrappedInts;
 class WrappedInt {
@@ -380,6 +444,21 @@
     compare<WTF::String>();
 }
 
+TEST(VectorTest, AppendFirst)
+{
+    Vector<WTF::String> vector;
+    vector.append("string");
+    // Test passes if it does not crash (reallocation did not make
+    // the input reference stale).
+    size_t limit = vector.capacity() + 1;
+    for (size_t i = 0; i < limit; i++)
+        vector.append(vector.first());
+
+    limit = vector.capacity() + 1;
+    for (size_t i = 0; i < limit; i++)
+        vector.append(const_cast<const WTF::String&>(vector.first()));
+}
+
 } // anonymous namespace
 
 } // namespace WTF