diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 9f3095bf..633c9e8 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -13,9 +13,7 @@
 
 #include "base/numerics/safe_conversions_impl.h"
 
-// TODO(jschuh): Investigate why these were failing to build for ios.
-#if !defined(__APPLE__) && !defined(__native_client__) && \
-    (defined(__ARMEL__) || defined(__arch64__))
+#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
 #include "base/numerics/safe_conversions_arm_impl.h"
 #define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1)
 #else
@@ -117,7 +115,7 @@
 constexpr Dst saturated_cast(Src value) {
   using SrcType = typename UnderlyingType<Src>::type;
   return !IsCompileTimeConstant(value) &&
-                 SaturateFastAsmOp<Dst, Src>::is_supported &&
+                 SaturateFastAsmOp<Dst, SrcType>::is_supported &&
                  std::is_same<SaturationHandler<Dst>,
                               SaturationDefaultLimits<Dst>>::value
              ? SaturateFastAsmOp<Dst, SrcType>::Do(value)
diff --git a/base/numerics/safe_conversions_arm_impl.h b/base/numerics/safe_conversions_arm_impl.h
index e18bf1ac..0bf47ef 100644
--- a/base/numerics/safe_conversions_arm_impl.h
+++ b/base/numerics/safe_conversions_arm_impl.h
@@ -60,14 +60,15 @@
     if (std::is_signed<Dst>::value) {
       asm("ssat %[dst], %[shift], %[src]"
           : [dst] "=r"(result)
-          : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value));
+          : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value <= 32
+                                            ? IntegerBitsPlusSign<Dst>::value
+                                            : 32));
     } else {
       asm("usat %[dst], %[shift], %[src]"
           : [dst] "=r"(result)
-          :
-          [src] "r"(src), [shift] "n"(std::is_same<uint32_t, Dst>::value
-                                          ? IntegerBitsPlusSign<Dst>::value - 1
-                                          : IntegerBitsPlusSign<Dst>::value));
+          : [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value < 32
+                                            ? IntegerBitsPlusSign<Dst>::value
+                                            : 31));
     }
     return static_cast<Dst>(result);
   }
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 3b2c727..c25ae6c 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -22,8 +22,8 @@
 json_data_file = os.path.join(script_dir, 'win_toolchain.json')
 
 
-# Use MSVS2015 as the default toolchain.
-CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015'
+# Use MSVS2017 as the default toolchain.
+CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2017'
 
 
 def SetEnvironmentAndGetRuntimeDllDirs():
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
index 4e34d936..c802135 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
@@ -7,7 +7,6 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.provider.Browser;
 import android.support.annotation.Nullable;
 import android.support.customtabs.CustomTabsIntent;
@@ -76,8 +75,6 @@
             return;
         }
 
-        final TabDelegate tabDelegate = new TabDelegate(incognito);
-
         // 1. Launch WebAPK if one matches the target URL.
         String webApkPackageName =
                 WebApkValidator.queryWebApkPackage(ContextUtils.getApplicationContext(), url);
@@ -93,8 +90,8 @@
 
         // 2. Launch WebappActivity if one matches the target URL and was opened recently.
         // Otherwise, open the URL in a tab.
-        final WebappDataStorage storage =
-                WebappRegistry.getInstance().getWebappDataStorageForUrl(url);
+        WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorageForUrl(url);
+        TabDelegate tabDelegate = new TabDelegate(incognito);
 
         // Open a new tab if:
         // - We did not find a WebappDataStorage corresponding to this URL.
@@ -112,28 +109,16 @@
                     Tab.INVALID_TAB_ID);
         } else {
             // The URL is within the scope of a recently launched standalone-capable web app
-            // on the home screen, so open it a standalone web app frame. An AsyncTask is
-            // used because WebappDataStorage.createWebappLaunchIntent contains a Bitmap
-            // decode operation and should not be run on the UI thread.
+            // on the home screen, so open it a standalone web app frame.
             //
             // This currently assumes that the only source is notifications; any future use
             // which adds a different source will need to change this.
-            new AsyncTask<Void, Void, Intent>() {
-                @Override
-                protected final Intent doInBackground(Void... nothing) {
-                    return storage.createWebappLaunchIntent();
-                }
-
-                @Override
-                protected final void onPostExecute(Intent intent) {
-                    // Replace the web app URL with the URL from the notification. This is
-                    // within the webapp's scope, so it is valid.
-                    intent.putExtra(ShortcutHelper.EXTRA_URL, url);
-                    intent.putExtra(ShortcutHelper.EXTRA_SOURCE,
-                            ShortcutSource.NOTIFICATION);
-                    tabDelegate.createNewStandaloneFrame(intent);
-                }
-            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            Intent intent = storage.createWebappLaunchIntent();
+            // Replace the web app URL with the URL from the notification. This is within the
+            // webapp's scope, so it is valid.
+            intent.putExtra(ShortcutHelper.EXTRA_URL, url);
+            intent.putExtra(ShortcutHelper.EXTRA_SOURCE, ShortcutSource.NOTIFICATION);
+            tabDelegate.createNewStandaloneFrame(intent);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 1dfd97b..422eea3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -164,11 +164,15 @@
                 // Encoding {@link icon} as a string and computing the mac are expensive.
 
                 Context context = ContextUtils.getApplicationContext();
+
+                // Encode the icon as a base64 string (Launcher drops Bitmaps in the Intent).
+                String encodedIcon = encodeBitmapAsString(icon);
+
                 String nonEmptyScopeUrl =
                         TextUtils.isEmpty(scopeUrl) ? getScopeFromUrl(url) : scopeUrl;
                 Intent shortcutIntent = createWebappShortcutIntent(id,
                         sDelegate.getFullscreenAction(), url, nonEmptyScopeUrl, name, shortName,
-                        icon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor,
+                        encodedIcon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor,
                         backgroundColor, iconUrl.isEmpty());
                 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url));
                 shortcutIntent.putExtra(EXTRA_SOURCE, source);
@@ -339,7 +343,7 @@
      * @param scope           Url scope of the web app.
      * @param name            Name of the web app.
      * @param shortName       Short name of the web app.
-     * @param icon            Icon of the web app.
+     * @param encodedIcon     Base64 encoded icon of the web app.
      * @param version         Version number of the shortcut.
      * @param displayMode     Display mode of the web app.
      * @param orientation     Orientation of the web app.
@@ -350,13 +354,9 @@
      * This method must not be called on the UI thread.
      */
     public static Intent createWebappShortcutIntent(String id, String action, String url,
-            String scope, String name, String shortName, Bitmap icon, int version, int displayMode,
-            int orientation, long themeColor, long backgroundColor, boolean isIconGenerated) {
-        assert !ThreadUtils.runningOnUiThread();
-
-        // Encode the icon as a base64 string (Launcher drops Bitmaps in the Intent).
-        String encodedIcon = encodeBitmapAsString(icon);
-
+            String scope, String name, String shortName, String encodedIcon, int version,
+            int displayMode, int orientation, long themeColor, long backgroundColor,
+            boolean isIconGenerated) {
         // Create an intent as a launcher icon for a full-screen Activity.
         Intent shortcutIntent = new Intent();
         shortcutIntent.setAction(action)
@@ -383,7 +383,6 @@
      * This method must not be called on the UI thread.
      */
     public static Intent createWebappShortcutIntentForTesting(String id, String url) {
-        assert !ThreadUtils.runningOnUiThread();
         return createWebappShortcutIntent(id, null, url, getScopeFromUrl(url), null, null, null,
                 WEBAPP_SHORTCUT_VERSION, WebDisplayMode.STANDALONE, 0, 0, 0, false);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
index 650fcb7..05b469b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -12,7 +12,6 @@
 import android.text.TextUtils;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ShortcutHelper;
@@ -191,12 +190,10 @@
     }
 
     /**
-     * Creates and returns a web app launch intent from the data stored in this object. Must not be
-     * called on the main thread as it requires a potentially expensive image decode.
+     * Creates and returns a web app launch intent from the data stored in this object.
      * @return The web app launch intent.
      */
     public Intent createWebappLaunchIntent() {
-        assert !ThreadUtils.runningOnUiThread();
         // Assume that all of the data is invalid if the version isn't set, so return a null intent.
         int version = mPreferences.getInt(KEY_VERSION, VERSION_INVALID);
         if (version == VERSION_INVALID) return null;
@@ -207,8 +204,8 @@
                 mPreferences.getString(KEY_ACTION, null), mPreferences.getString(KEY_URL, null),
                 mPreferences.getString(KEY_SCOPE, null), mPreferences.getString(KEY_NAME, null),
                 mPreferences.getString(KEY_SHORT_NAME, null),
-                ShortcutHelper.decodeBitmapFromString(mPreferences.getString(KEY_ICON, null)),
-                version, mPreferences.getInt(KEY_DISPLAY_MODE, WebDisplayMode.STANDALONE),
+                mPreferences.getString(KEY_ICON, null), version,
+                mPreferences.getInt(KEY_DISPLAY_MODE, WebDisplayMode.STANDALONE),
                 mPreferences.getInt(KEY_ORIENTATION, ScreenOrientationValues.DEFAULT),
                 mPreferences.getLong(
                         KEY_THEME_COLOR, ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
index 8b7ee07..c3ffbd4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.browsing_data;
 
 import android.content.Intent;
-import android.os.AsyncTask;
 import android.support.test.filters.MediumTest;
 
 import org.junit.Assert;
@@ -72,14 +71,8 @@
     }
 
     private void registerWebapp(final String webappId, final String webappUrl) throws Exception {
-        AsyncTask<Void, Void, Intent> shortcutIntentTask = new AsyncTask<Void, Void, Intent>() {
-            @Override
-            protected Intent doInBackground(Void... nothing) {
-                return ShortcutHelper.createWebappShortcutIntentForTesting(webappId, webappUrl);
-            }
-        };
-
-        final Intent shortcutIntent = shortcutIntentTask.execute().get();
+        Intent shortcutIntent =
+                ShortcutHelper.createWebappShortcutIntentForTesting(webappId, webappUrl);
         TestFetchStorageCallback callback = new TestFetchStorageCallback();
         WebappRegistry.getInstance().register(webappId, callback);
         callback.waitForCallback(0);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
index fcdccab..37f66a6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.preferences.privacy;
 
 import android.content.Intent;
-import android.os.AsyncTask;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
@@ -124,14 +123,7 @@
      */
     @MediumTest
     public void testClearingHistoryClearsWebappScopesAndLaunchTimes() throws Exception {
-        AsyncTask<Void, Void, Intent> shortcutIntentTask = new AsyncTask<Void, Void, Intent>() {
-            @Override
-            protected Intent doInBackground(Void... nothing) {
-                return ShortcutHelper.createWebappShortcutIntentForTesting("id", "url");
-            }
-        };
-        final Intent shortcutIntent = shortcutIntentTask.execute().get();
-
+        Intent shortcutIntent = ShortcutHelper.createWebappShortcutIntentForTesting("id", "url");
         TestFetchStorageCallback callback = new TestFetchStorageCallback();
         WebappRegistry.getInstance().register("first", callback);
         callback.waitForCallback(0);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
index bfdcde5..2d8e454 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -12,7 +12,6 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
-import android.os.AsyncTask;
 
 import org.junit.After;
 import org.junit.Before;
@@ -236,21 +235,15 @@
         final String scope = "scope";
         final String name = "name";
         final String shortName = "shortName";
-        final Bitmap icon = createBitmap();
+        final String encodedIcon = ShortcutHelper.encodeBitmapAsString(createBitmap());
         final int displayMode = WebDisplayMode.STANDALONE;
         final int orientation = 1;
         final long themeColor = 2;
         final long backgroundColor = 3;
         final boolean isIconGenerated = false;
-        AsyncTask<Void, Void, Intent> shortcutIntentTask = new AsyncTask<Void, Void, Intent>() {
-            @Override
-            protected Intent doInBackground(Void... nothing) {
-                return ShortcutHelper.createWebappShortcutIntent(id, action, url, scope, name,
-                        shortName, icon, ShortcutHelper.WEBAPP_SHORTCUT_VERSION, displayMode,
-                        orientation, themeColor, backgroundColor, isIconGenerated);
-            }
-        };
-        Intent shortcutIntent = shortcutIntentTask.execute().get();
+        Intent shortcutIntent = ShortcutHelper.createWebappShortcutIntent(id, action, url, scope,
+                name, shortName, encodedIcon, ShortcutHelper.WEBAPP_SHORTCUT_VERSION, displayMode,
+                orientation, themeColor, backgroundColor, isIconGenerated);
 
         WebappDataStorage storage = WebappDataStorage.open("test");
         storage.updateFromShortcutIntent(shortcutIntent);
@@ -261,8 +254,7 @@
         assertEquals(name, mSharedPreferences.getString(WebappDataStorage.KEY_NAME, null));
         assertEquals(shortName,
                 mSharedPreferences.getString(WebappDataStorage.KEY_SHORT_NAME, null));
-        assertEquals(ShortcutHelper.encodeBitmapAsString(icon),
-                mSharedPreferences.getString(WebappDataStorage.KEY_ICON, null));
+        assertEquals(encodedIcon, mSharedPreferences.getString(WebappDataStorage.KEY_ICON, null));
         assertEquals(ShortcutHelper.WEBAPP_SHORTCUT_VERSION,
                 mSharedPreferences.getInt(WebappDataStorage.KEY_VERSION, 0));
         assertEquals(orientation, mSharedPreferences.getInt(WebappDataStorage.KEY_ORIENTATION, 0));
@@ -308,8 +300,7 @@
         assertEquals(name, mSharedPreferences.getString(WebappDataStorage.KEY_NAME, null));
         assertEquals(shortName,
                 mSharedPreferences.getString(WebappDataStorage.KEY_SHORT_NAME, null));
-        assertEquals(ShortcutHelper.encodeBitmapAsString(icon),
-                mSharedPreferences.getString(WebappDataStorage.KEY_ICON, null));
+        assertEquals(encodedIcon, mSharedPreferences.getString(WebappDataStorage.KEY_ICON, null));
         assertEquals(ShortcutHelper.WEBAPP_SHORTCUT_VERSION,
                 mSharedPreferences.getInt(WebappDataStorage.KEY_VERSION, 0));
         assertEquals(orientation, mSharedPreferences.getInt(WebappDataStorage.KEY_ORIENTATION, 0));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
index 8e23358..f913ea38 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -10,7 +10,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.os.AsyncTask;
 import android.text.TextUtils;
 
 import org.junit.After;
@@ -654,14 +653,8 @@
                 WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet());
     }
 
-    private Intent createShortcutIntent(final String url) throws Exception {
-        AsyncTask<Void, Void, Intent> shortcutIntentTask = new AsyncTask<Void, Void, Intent>() {
-            @Override
-            protected Intent doInBackground(Void... nothing) {
-                return ShortcutHelper.createWebappShortcutIntentForTesting("id", url);
-            }
-        };
-        return shortcutIntentTask.execute().get();
+    private Intent createShortcutIntent(final String url) {
+        return ShortcutHelper.createWebappShortcutIntentForTesting("id", url);
     }
 
     private Intent createWebApkIntent(String webappId, String webApkPackage) {