diff --git a/DEPS b/DEPS index 8d7cd348..337aaa3 100644 --- a/DEPS +++ b/DEPS
@@ -39,11 +39,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'bf90520f63415f539cd5792a18efbd79cb86be0a', + 'skia_revision': '0a3cac8a90e4aed24555815a43fafd53aed009ee', # 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': '8ec2f9cfc4a1852fdcb5b1965637c258bc22ba66', + 'v8_revision': 'cdecc17136765f53f60814cb559306f029309e32', # 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. @@ -59,7 +59,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '1f439a7a3b7c44235ecdac9a411add8fb62b0d83', + 'pdfium_revision': 'a398ca611d1925182ff6a4e8b2b43c277c364dc0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -87,7 +87,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '719fce7fa0c1f11cf05d5c20cdfa6648e8a35611', + 'nacl_revision': 'f84c2ab61585743268db990ee54d097426c309f0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling dEQP # and whatever else without interference from each other. @@ -148,7 +148,7 @@ Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf', 'src/tools/grit': - Var('chromium_git') + '/external/grit-i18n.git' + '@' + 'f6d8c4ca636a187f4e3e38f41f650040c4e189cb', # from svn revision 199 + Var('chromium_git') + '/external/grit-i18n.git' + '@' + '4983981a20ff2f1c68a91994cff1eded5b2c494d', # from svn revision 200 'src/tools/gyp': Var('chromium_git') + '/external/gyp.git' + '@' + '01528c7244837168a1c80f06ff60fa5a9793c824',
diff --git a/android_webview/android_webview_shell.gyp b/android_webview/android_webview_shell.gyp index 8704b92..89b7785 100644 --- a/android_webview/android_webview_shell.gyp +++ b/android_webview/android_webview_shell.gyp
@@ -4,26 +4,72 @@ { 'targets': [ { - 'target_name': 'android_webview_shell_apk', + 'target_name': 'system_webview_shell_apk', + 'type': 'none', + 'variables': { + 'apk_name': 'SystemWebViewShell', + 'java_in_dir': 'tools/WebViewShell', + 'resource_dir': 'tools/WebViewShell/res', + 'android_manifest_path': 'tools/WebViewShell/AndroidManifest.xml', # for lint + }, + 'includes': [ + '../build/java_apk.gypi', + ], + }, + { + # android_webview_apk creates a .jar as a side effect. Any java + # targets that need that .jar in their classpath should depend on this + # target. For more details see the content_shell_apk_java target. + 'target_name': 'system_webview_shell_apk_java', + 'type': 'none', + 'dependencies': [ + 'system_webview_shell_apk', + ], + 'includes': [ '../build/apk_fake_jar.gypi' ], + }, + { + 'target_name': 'system_webview_shell_page_cycler_apk', 'type': 'none', 'dependencies': [ '../base/base.gyp:base_java_test_support', + '../content/content_shell_and_tests.gyp:content_java_test_support', '../testing/android/on_device_instrumentation.gyp:broker_java', '../testing/android/on_device_instrumentation.gyp:require_driver_apk', + 'system_webview_shell_apk_java', ], 'variables': { - 'apk_name': 'AndroidWebViewShell', - 'java_in_dir': 'tools/WebViewShell', - 'resource_dir': 'tools/WebViewShell/res', + 'apk_name': 'SystemWebViewShellPageCycler', + 'java_in_dir': '../android_webview/tools/PageCycler', 'is_test_apk': 1, 'test_type': 'instrumentation', - 'isolate_file': 'android_webview_shell_test_apk.isolate', - 'android_manifest_path': 'tools/WebViewShell/AndroidManifest.xml', # for lint + 'android_manifest_path': '../android_webview/tools/PageCycler/AndroidManifest.xml', }, 'includes': [ '../build/java_apk.gypi', '../build/android/test_runner.gypi', ], }, + { + 'target_name': 'system_webview_shell_layout_test_apk', + 'type': 'none', + 'dependencies': [ + '../base/base.gyp:base_java_test_support', + '../testing/android/on_device_instrumentation.gyp:broker_java', + '../testing/android/on_device_instrumentation.gyp:require_driver_apk', + 'system_webview_shell_apk_java', + ], + 'variables': { + 'apk_name': 'SystemWebViewShellLayoutTest', + 'java_in_dir': '../android_webview/tools/WebViewShellTest', + 'is_test_apk': 1, + 'test_type': 'instrumentation', + 'isolate_file': 'android_webview_shell_test_apk.isolate', + 'android_manifest_path': '../android_webview/tools/WebViewShellTest/AndroidManifest.xml', + }, + 'includes': [ + '../build/java_apk.gypi', + '../build/android/test_runner.gypi', + ] + }, ], }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 7962c18d..1a0acbf 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -25,7 +25,6 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Base64; -import android.util.Log; import android.util.Pair; import android.view.KeyEvent; import android.view.MotionEvent; @@ -43,6 +42,7 @@ import org.chromium.android_webview.permission.AwGeolocationCallback; import org.chromium.android_webview.permission.AwPermissionRequest; import org.chromium.base.LocaleUtils; +import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; @@ -95,6 +95,8 @@ PostMessageSender.PostMessageSenderDelegate { private static final String TAG = "AwContents"; private static final boolean TRACE = false; + private static final int NO_WARN = 0; + private static final int WARN = 1; private static final String WEB_ARCHIVE_EXTENSION = ".mht"; @@ -559,12 +561,13 @@ @Override public void scrollNativeTo(int x, int y) { - if (!isDestroyed()) nativeScrollTo(mNativeAwContents, x, y); + if (!isDestroyed(NO_WARN)) nativeScrollTo(mNativeAwContents, x, y); } @Override public void smoothScroll(int targetX, int targetY, long durationMs) { - if (!isDestroyed()) nativeSmoothScroll(mNativeAwContents, targetX, targetY, durationMs); + if (!isDestroyed(NO_WARN)) nativeSmoothScroll( + mNativeAwContents, targetX, targetY, durationMs); } @Override @@ -616,7 +619,7 @@ private class AwComponentCallbacks implements ComponentCallbacks2 { @Override public void onTrimMemory(final int level) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; boolean visibleRectEmpty = getGlobalVisibleRect().isEmpty(); final boolean visible = mIsViewVisible && mIsWindowVisible && !visibleRectEmpty; nativeTrimMemory(mNativeAwContents, level, visible); @@ -700,7 +703,7 @@ @Override public void onGestureZoomSupportChanged( boolean supportsDoubleTapZoom, boolean supportsMultiTouchZoom) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; mContentViewCore.updateDoubleTapSupport(supportsDoubleTapZoom); mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoom); } @@ -749,7 +752,7 @@ */ View enterFullScreen() { assert !isFullScreen(); - if (isDestroyed()) return null; + if (isDestroyed(NO_WARN)) return null; // Detach to tear down the GL functor if this is still associated with the old // container view. It will be recreated during the next call to onDraw attached to @@ -779,7 +782,7 @@ * Called when the app has requested to exit fullscreen. */ void requestExitFullscreen() { - if (!isDestroyed()) mContentViewCore.getWebContents().exitFullscreen(); + if (!isDestroyed(NO_WARN)) mContentViewCore.getWebContents().exitFullscreen(); } /** @@ -787,7 +790,7 @@ * in the WebView. */ void exitFullScreen() { - if (!isFullScreen() || isDestroyed()) { + if (!isFullScreen() || isDestroyed(NO_WARN)) { // exitFullScreen() can be called without a prior call to enterFullScreen() if a // "misbehave" app overrides onShowCustomView but does not add the custom view to // the window. Exiting avoids a crash. @@ -981,6 +984,7 @@ * provide the AwContents to host the pop up content. */ public void supplyContentsForPopup(AwContents newContents) { + assert !isDestroyed(NO_WARN); long popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents); if (popupNativeAwContents == 0) { Log.w(TAG, "Popup WebView bind failed: no pending content."); @@ -1054,7 +1058,7 @@ */ public void destroy() { if (TRACE) Log.d(TAG, "destroy"); - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; // Remove pending messages mContentsClient.getCallbackHelper().removeCallbacksAndMessages(); @@ -1067,6 +1071,7 @@ // If we are attached, we have to call native detach to clean up // hardware resources. if (mIsAttachedToWindow) { + Log.w(TAG, "WebView.destroy() called while WebView is still attached to window."); nativeOnDetachedFromWindow(mNativeAwContents); } mIsDestroyed = true; @@ -1103,12 +1108,24 @@ assert mNativeAwContents == 0; } - private boolean isDestroyed() { + /** + * Returns whether this instance of WebView is flagged as destroyed. + * If {@link WARN} is passed as a parameter, the method also issues a warning + * log message and dumps stack, as embedders are advised not to call any + * methods on destroyed WebViews. + * + * @param warnIfDestroyed use {@link WARN} if the check is done from a method + * that is called via public WebView API, and {@link NO_WARN} otherwise. + * @return whether this instance of WebView is flagged as destroyed. + */ + private boolean isDestroyed(int warnIfDestroyed) { if (!mIsDestroyed) { assert mContentViewCore != null; assert mWebContents != null; assert mNavigationController != null; assert mNativeAwContents != 0; + } else if (warnIfDestroyed == WARN) { + Log.w(TAG, "Application attempted to call on a destroyed WebView", new Throwable()); } return mIsDestroyed; } @@ -1134,7 +1151,7 @@ } public AwPdfExporter getPdfExporter() { - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; if (mAwPdfExporter == null) { mAwPdfExporter = new AwPdfExporter(mContainerView); nativeCreatePdfExporter(mNativeAwContents, mAwPdfExporter); @@ -1167,7 +1184,7 @@ * to ensure backwards compatible behavior. */ public void disableJavascriptInterfacesInspection() { - if (!isDestroyed()) mContentViewCore.setAllowJavascriptInterfacesInspection(false); + if (!isDestroyed(WARN)) mContentViewCore.setAllowJavascriptInterfacesInspection(false); } /** @@ -1182,7 +1199,7 @@ public long getAwDrawGLViewContext() { // Only called during early construction, so client should not have had a chance to // call destroy yet. - assert !isDestroyed(); + assert !isDestroyed(NO_WARN); // Using the native pointer as the returned viewContext. This is matched by the // reinterpret_cast back to BrowserViewRenderer pointer in the native DrawGLFunction. @@ -1222,16 +1239,18 @@ } public int getContentHeightCss() { + if (isDestroyed(WARN)) return 0; return (int) Math.ceil(mContentHeightDip); } public int getContentWidthCss() { + if (isDestroyed(WARN)) return 0; return (int) Math.ceil(mContentWidthDip); } public Picture capturePicture() { if (TRACE) Log.d(TAG, "capturePicture"); - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; return new AwPicture(nativeCapturePicture(mNativeAwContents, mScrollOffsetManager.computeHorizontalScrollRange(), mScrollOffsetManager.computeVerticalScrollRange())); @@ -1239,7 +1258,7 @@ public void clearView() { if (TRACE) Log.d(TAG, "clearView"); - if (!isDestroyed()) nativeClearView(mNativeAwContents); + if (!isDestroyed(WARN)) nativeClearView(mNativeAwContents); } /** @@ -1249,7 +1268,7 @@ */ public void enableOnNewPicture(boolean enabled, boolean invalidationOnly) { if (TRACE) Log.d(TAG, "enableOnNewPicture=" + enabled); - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; if (invalidationOnly) { mPictureListenerContentProvider = null; } else if (enabled && mPictureListenerContentProvider == null) { @@ -1265,28 +1284,30 @@ public void findAllAsync(String searchString) { if (TRACE) Log.d(TAG, "findAllAsync"); - if (!isDestroyed()) nativeFindAllAsync(mNativeAwContents, searchString); + if (!isDestroyed(WARN)) nativeFindAllAsync(mNativeAwContents, searchString); } public void findNext(boolean forward) { if (TRACE) Log.d(TAG, "findNext"); - if (!isDestroyed()) nativeFindNext(mNativeAwContents, forward); + if (!isDestroyed(WARN)) nativeFindNext(mNativeAwContents, forward); } public void clearMatches() { if (TRACE) Log.d(TAG, "clearMatches"); - if (!isDestroyed()) nativeClearMatches(mNativeAwContents); + if (!isDestroyed(WARN)) nativeClearMatches(mNativeAwContents); } /** * @return load progress of the WebContents. */ public int getMostRecentProgress() { + if (isDestroyed(WARN)) return 0; // WebContentsDelegateAndroid conveniently caches the most recent notified value for us. return mWebContentsDelegate.getMostRecentProgress(); } public Bitmap getFavicon() { + if (isDestroyed(WARN)) return null; return mFavicon; } @@ -1297,7 +1318,7 @@ ThreadUtils.runOnUiThread(new Runnable() { @Override public void run() { - if (!isDestroyed()) nativeAddVisitedLinks(mNativeAwContents, value); + if (!isDestroyed(NO_WARN)) nativeAddVisitedLinks(mNativeAwContents, value); } }); } @@ -1310,6 +1331,7 @@ */ public void loadUrl(String url, Map<String, String> additionalHttpHeaders) { if (TRACE) Log.d(TAG, "loadUrl(extra headers)=" + url); + if (isDestroyed(WARN)) return; // TODO: We may actually want to do some sanity checks here (like filter about://chrome). // For backwards compatibility, apps targeting less than K will have JS URLs evaluated @@ -1333,6 +1355,7 @@ */ public void loadUrl(String url) { if (TRACE) Log.d(TAG, "loadUrl=" + url); + if (isDestroyed(WARN)) return; // Early out to match old WebView implementation if (url == null) { return; @@ -1345,6 +1368,7 @@ */ public void postUrl(String url, byte[] postData) { if (TRACE) Log.d(TAG, "postUrl=" + url); + if (isDestroyed(WARN)) return; LoadUrlParams params = LoadUrlParams.createLoadHttpPostParams(url, postData); Map<String, String> headers = new HashMap<String, String>(); headers.put("Content-Type", "application/x-www-form-urlencoded"); @@ -1387,7 +1411,7 @@ public void loadDataWithBaseURL( String baseUrl, String data, String mimeType, String encoding, String historyUrl) { if (TRACE) Log.d(TAG, "loadDataWithBaseURL=" + baseUrl); - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; data = fixupData(data); mimeType = fixupMimeType(mimeType); @@ -1428,9 +1452,8 @@ * * @param params Parameters for this load. */ + @VisibleForTesting public void loadUrl(LoadUrlParams params) { - if (isDestroyed()) return; - if (params.getLoadUrlType() == LoadURLType.DATA && !params.isBaseUrlDataScheme()) { // This allows data URLs with a non-data base URL access to file:///android_asset/ and // file:///android_res/ URLs. If AwSettings.getAllowFileAccess permits, it will also @@ -1496,7 +1519,7 @@ * @return The URL of the current page or null if it's empty. */ public String getUrl() { - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; String url = mWebContents.getUrl(); if (url == null || url.trim().isEmpty()) return null; return url; @@ -1509,7 +1532,7 @@ * @return The URL of the current page or null if it's empty. */ public String getLastCommittedUrl() { - if (isDestroyed()) return null; + if (isDestroyed(NO_WARN)) return null; String url = mWebContents.getLastCommittedUrl(); if (url == null || url.trim().isEmpty()) return null; return url; @@ -1521,7 +1544,7 @@ public void setBackgroundColor(int color) { mBaseBackgroundColor = color; - if (!isDestroyed()) nativeSetBackgroundColor(mNativeAwContents, color); + if (!isDestroyed(WARN)) nativeSetBackgroundColor(mNativeAwContents, color); } /** @@ -1535,7 +1558,7 @@ // Do not ask the ContentViewCore for the background color, as it will always // report white prior to initial navigation or post destruction, whereas we want // to use the client supplied base value in those cases. - if (isDestroyed() || !mContentsClient.isCachedRendererBackgroundColorValid()) { + if (isDestroyed(NO_WARN) || !mContentsClient.isCachedRendererBackgroundColorValid()) { return mBaseBackgroundColor; } return mContentsClient.getCachedRendererBackgroundColor(); @@ -1631,6 +1654,7 @@ * @see android.webkit.WebView#requestChildRectangleOnScreen(View, Rect, boolean) */ public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { + if (isDestroyed(WARN)) return false; return mScrollOffsetManager.requestChildRectangleOnScreen( child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY(), rect, immediate); @@ -1683,7 +1707,7 @@ */ public void stopLoading() { if (TRACE) Log.d(TAG, "stopLoading"); - if (!isDestroyed()) mWebContents.stop(); + if (!isDestroyed(WARN)) mWebContents.stop(); } /** @@ -1691,14 +1715,14 @@ */ public void reload() { if (TRACE) Log.d(TAG, "reload"); - if (!isDestroyed()) mNavigationController.reload(true); + if (!isDestroyed(WARN)) mNavigationController.reload(true); } /** * @see android.webkit.WebView#canGoBack() */ public boolean canGoBack() { - return isDestroyed() ? false : mNavigationController.canGoBack(); + return isDestroyed(WARN) ? false : mNavigationController.canGoBack(); } /** @@ -1706,14 +1730,14 @@ */ public void goBack() { if (TRACE) Log.d(TAG, "goBack"); - if (!isDestroyed()) mNavigationController.goBack(); + if (!isDestroyed(WARN)) mNavigationController.goBack(); } /** * @see android.webkit.WebView#canGoForward() */ public boolean canGoForward() { - return isDestroyed() ? false : mNavigationController.canGoForward(); + return isDestroyed(WARN) ? false : mNavigationController.canGoForward(); } /** @@ -1721,14 +1745,14 @@ */ public void goForward() { if (TRACE) Log.d(TAG, "goForward"); - if (!isDestroyed()) mNavigationController.goForward(); + if (!isDestroyed(WARN)) mNavigationController.goForward(); } /** * @see android.webkit.WebView#canGoBackOrForward(int) */ public boolean canGoBackOrForward(int steps) { - return isDestroyed() ? false : mNavigationController.canGoToOffset(steps); + return isDestroyed(WARN) ? false : mNavigationController.canGoToOffset(steps); } /** @@ -1736,7 +1760,7 @@ */ public void goBackOrForward(int steps) { if (TRACE) Log.d(TAG, "goBackOrForwad=" + steps); - if (!isDestroyed()) mNavigationController.goToOffset(steps); + if (!isDestroyed(WARN)) mNavigationController.goToOffset(steps); } /** @@ -1744,7 +1768,7 @@ */ public void pauseTimers() { if (TRACE) Log.d(TAG, "pauseTimers"); - if (!isDestroyed()) ContentViewStatics.setWebKitSharedTimersSuspended(true); + if (!isDestroyed(WARN)) ContentViewStatics.setWebKitSharedTimersSuspended(true); } /** @@ -1752,7 +1776,7 @@ */ public void resumeTimers() { if (TRACE) Log.d(TAG, "resumeTimers"); - if (!isDestroyed()) ContentViewStatics.setWebKitSharedTimersSuspended(false); + if (!isDestroyed(WARN)) ContentViewStatics.setWebKitSharedTimersSuspended(false); } /** @@ -1760,7 +1784,7 @@ */ public void onPause() { if (TRACE) Log.d(TAG, "onPause"); - if (mIsPaused || isDestroyed()) return; + if (mIsPaused || isDestroyed(NO_WARN)) return; mIsPaused = true; nativeSetIsPaused(mNativeAwContents, mIsPaused); updateContentViewCoreVisibility(); @@ -1771,7 +1795,7 @@ */ public void onResume() { if (TRACE) Log.d(TAG, "onResume"); - if (!mIsPaused || isDestroyed()) return; + if (!mIsPaused || isDestroyed(NO_WARN)) return; mIsPaused = false; nativeSetIsPaused(mNativeAwContents, mIsPaused); updateContentViewCoreVisibility(); @@ -1781,7 +1805,7 @@ * @see android.webkit.WebView#isPaused() */ public boolean isPaused() { - return mIsPaused; + return isDestroyed(WARN) ? false : mIsPaused; } /** @@ -1813,11 +1837,11 @@ */ public void clearCache(boolean includeDiskFiles) { if (TRACE) Log.d(TAG, "clearCache"); - if (!isDestroyed()) nativeClearCache(mNativeAwContents, includeDiskFiles); + if (!isDestroyed(WARN)) nativeClearCache(mNativeAwContents, includeDiskFiles); } public void documentHasImages(Message message) { - if (!isDestroyed()) nativeDocumentHasImages(mNativeAwContents, message); + if (!isDestroyed(WARN)) nativeDocumentHasImages(mNativeAwContents, message); } public void saveWebArchive( @@ -1843,7 +1867,7 @@ } public String getOriginalUrl() { - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; NavigationHistory history = mNavigationController.getNavigationHistory(); int currentIndex = history.getCurrentEntryIndex(); if (currentIndex >= 0 && currentIndex < history.getEntryCount()) { @@ -1856,14 +1880,14 @@ * @see ContentViewCore#getNavigationHistory() */ public NavigationHistory getNavigationHistory() { - return isDestroyed() ? null : mNavigationController.getNavigationHistory(); + return isDestroyed(WARN) ? null : mNavigationController.getNavigationHistory(); } /** * @see android.webkit.WebView#getTitle() */ public String getTitle() { - return isDestroyed() ? null : mWebContents.getTitle(); + return isDestroyed(WARN) ? null : mWebContents.getTitle(); } /** @@ -1871,7 +1895,7 @@ */ public void clearHistory() { if (TRACE) Log.d(TAG, "clearHistory"); - if (!isDestroyed()) mNavigationController.clearHistory(); + if (!isDestroyed(WARN)) mNavigationController.clearHistory(); } public String[] getHttpAuthUsernamePassword(String host, String realm) { @@ -1882,6 +1906,7 @@ public void setHttpAuthUsernamePassword(String host, String realm, String username, String password) { if (TRACE) Log.d(TAG, "setHttpAuthUsernamePassword=" + host); + if (isDestroyed(WARN)) return; mBrowserContext.getHttpAuthDatabase(mContext) .setHttpAuthUsernamePassword(host, realm, username, password); } @@ -1890,7 +1915,7 @@ * @see android.webkit.WebView#getCertificate() */ public SslCertificate getCertificate() { - return isDestroyed() ? null + return isDestroyed(WARN) ? null : SslUtil.getCertificateFromDerBytes(nativeGetCertificate(mNativeAwContents)); } @@ -1899,7 +1924,7 @@ */ public void clearSslPreferences() { if (TRACE) Log.d(TAG, "clearSslPreferences"); - if (!isDestroyed()) mNavigationController.clearSslPreferences(); + if (!isDestroyed(WARN)) mNavigationController.clearSslPreferences(); } /** @@ -1910,7 +1935,7 @@ */ public HitTestData getLastHitTestResult() { if (TRACE) Log.d(TAG, "getLastHitTestResult"); - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; nativeUpdateLastHitTestData(mNativeAwContents); return mPossiblyStaleHitTestData; } @@ -1920,7 +1945,7 @@ */ public void requestFocusNodeHref(Message msg) { if (TRACE) Log.d(TAG, "requestFocusNodeHref"); - if (msg == null || isDestroyed()) return; + if (msg == null || isDestroyed(WARN)) return; nativeUpdateLastHitTestData(mNativeAwContents); Bundle data = msg.getData(); @@ -1940,7 +1965,7 @@ */ public void requestImageRef(Message msg) { if (TRACE) Log.d(TAG, "requestImageRef"); - if (msg == null || isDestroyed()) return; + if (msg == null || isDestroyed(WARN)) return; nativeUpdateLastHitTestData(mNativeAwContents); Bundle data = msg.getData(); @@ -1961,6 +1986,7 @@ * the screen density factor. See CTS WebViewTest.testSetInitialScale. */ public float getScale() { + if (isDestroyed(WARN)) return 1; return (float) (mPageScaleFactor * mDIPScale); } @@ -1969,6 +1995,7 @@ */ public void flingScroll(int velocityX, int velocityY) { if (TRACE) Log.d(TAG, "flingScroll"); + if (isDestroyed(WARN)) return; mContentViewCore.flingViewport(SystemClock.uptimeMillis(), -velocityX, -velocityY); } @@ -1977,6 +2004,7 @@ */ public boolean pageUp(boolean top) { if (TRACE) Log.d(TAG, "pageUp"); + if (isDestroyed(WARN)) return false; return mScrollOffsetManager.pageUp(top); } @@ -1985,6 +2013,7 @@ */ public boolean pageDown(boolean bottom) { if (TRACE) Log.d(TAG, "pageDown"); + if (isDestroyed(WARN)) return false; return mScrollOffsetManager.pageDown(bottom); } @@ -1994,6 +2023,7 @@ // This method uses the term 'zoom' for legacy reasons, but relates // to what chrome calls the 'page scale factor'. public boolean canZoomIn() { + if (isDestroyed(WARN)) return false; final float zoomInExtent = mMaxPageScaleFactor - mPageScaleFactor; return zoomInExtent > ZOOM_CONTROLS_EPSILON; } @@ -2004,6 +2034,7 @@ // This method uses the term 'zoom' for legacy reasons, but relates // to what chrome calls the 'page scale factor'. public boolean canZoomOut() { + if (isDestroyed(WARN)) return false; final float zoomOutExtent = mPageScaleFactor - mMinPageScaleFactor; return zoomOutExtent > ZOOM_CONTROLS_EPSILON; } @@ -2040,7 +2071,7 @@ // This method uses the term 'zoom' for legacy reasons, but relates // to what chrome calls the 'page scale factor'. public void zoomBy(float delta) { - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; if (delta < 0.01f || delta > 100.0f) { throw new IllegalStateException("zoom delta value outside [0.01, 100] range."); } @@ -2052,14 +2083,14 @@ */ public void invokeZoomPicker() { if (TRACE) Log.d(TAG, "invokeZoomPicker"); - if (!isDestroyed()) mContentViewCore.invokeZoomPicker(); + if (!isDestroyed(WARN)) mContentViewCore.invokeZoomPicker(); } /** * @see android.webkit.WebView#preauthorizePermission(Uri, long) */ public void preauthorizePermission(Uri origin, long resources) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; nativePreauthorizePermission(mNativeAwContents, origin.toString(), resources); } @@ -2068,7 +2099,7 @@ */ public void evaluateJavaScript(String script, final ValueCallback<String> callback) { if (TRACE) Log.d(TAG, "evaluateJavascript=" + script); - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; JavaScriptCallback jsCallback = null; if (callback != null) { jsCallback = new JavaScriptCallback() { @@ -2084,7 +2115,7 @@ public void evaluateJavaScriptForTests(String script, final ValueCallback<String> callback) { if (TRACE) Log.d(TAG, "evaluateJavascriptForTests=" + script); - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; JavaScriptCallback jsCallback = null; if (callback != null) { jsCallback = new JavaScriptCallback() { @@ -2110,7 +2141,7 @@ */ public void postMessageToFrame(String frameName, String message, String targetOrigin, AwMessagePort[] sentPorts) { - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; if (mPostMessageSender == null) { AwMessagePortService service = mBrowserContext.getMessagePortService(); mPostMessageSender = new PostMessageSender(this, service); @@ -2135,7 +2166,7 @@ public void postMessageToWeb(String frameName, String message, String targetOrigin, int[] sentPortIds) { if (TRACE) Log.d(TAG, "postMessageToWeb. TargetOrigin=" + targetOrigin); - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; nativePostMessageToFrame(mNativeAwContents, frameName, message, targetOrigin, sentPortIds); } @@ -2145,19 +2176,19 @@ */ public AwMessagePort[] createMessageChannel() { if (TRACE) Log.d(TAG, "createMessageChannel"); - if (isDestroyed()) return null; + if (isDestroyed(WARN)) return null; AwMessagePort[] ports = mBrowserContext.getMessagePortService().createMessageChannel(); nativeCreateMessageChannel(mNativeAwContents, ports); return ports; } public boolean hasAccessedInitialDocument() { - if (isDestroyed()) return false; + if (isDestroyed(NO_WARN)) return false; return mWebContents.hasAccessedInitialDocument(); } public void requestAccessibilitySnapshot(AccessibilitySnapshotCallback callback) { - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; if (!mWebContentsObserver.didEverCommitNavigation()) { callback.onAccessibilitySnapshot(null); return; @@ -2187,7 +2218,7 @@ * @see android.view.View#onGenericMotionEvent() */ public boolean onGenericMotionEvent(MotionEvent event) { - return isDestroyed() ? false : mContentViewCore.onGenericMotionEvent(event); + return isDestroyed(NO_WARN) ? false : mContentViewCore.onGenericMotionEvent(event); } /** @@ -2266,7 +2297,7 @@ private void setViewVisibilityInternal(boolean visible) { mIsViewVisible = visible; - if (!isDestroyed()) nativeSetViewVisibility(mNativeAwContents, mIsViewVisible); + if (!isDestroyed(NO_WARN)) nativeSetViewVisibility(mNativeAwContents, mIsViewVisible); updateContentViewCoreVisibility(); } @@ -2274,12 +2305,12 @@ mInvalidateRootViewOnNextDraw |= Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP && visible && !mIsWindowVisible; mIsWindowVisible = visible; - if (!isDestroyed()) nativeSetWindowVisibility(mNativeAwContents, mIsWindowVisible); + if (!isDestroyed(NO_WARN)) nativeSetWindowVisibility(mNativeAwContents, mIsWindowVisible); updateContentViewCoreVisibility(); } private void updateContentViewCoreVisibility() { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; boolean contentViewCoreVisible = nativeIsVisible(mNativeAwContents); if (contentViewCoreVisible && !mIsContentViewCoreVisible) { @@ -2301,7 +2332,7 @@ */ public boolean saveState(Bundle outState) { if (TRACE) Log.d(TAG, "saveState"); - if (isDestroyed() || outState == null) return false; + if (isDestroyed(WARN) || outState == null) return false; byte[] state = nativeGetOpaqueState(mNativeAwContents); if (state == null) return false; @@ -2317,7 +2348,7 @@ */ public boolean restoreState(Bundle inState) { if (TRACE) Log.d(TAG, "restoreState"); - if (isDestroyed() || inState == null) return false; + if (isDestroyed(WARN) || inState == null) return false; byte[] state = inState.getByteArray(SAVE_RESTORE_STATE_KEY); if (state == null) return false; @@ -2339,7 +2370,7 @@ @SuppressLint("NewApi") // JavascriptInterface requires API level 17. public void addJavascriptInterface(Object object, String name) { if (TRACE) Log.d(TAG, "addJavascriptInterface=" + name); - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; Class<? extends Annotation> requiredAnnotation = null; if (mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) { requiredAnnotation = JavascriptInterface.class; @@ -2352,7 +2383,7 @@ */ public void removeJavascriptInterface(String interfaceName) { if (TRACE) Log.d(TAG, "removeJavascriptInterface=" + interfaceName); - if (!isDestroyed()) mContentViewCore.removeJavascriptInterface(interfaceName); + if (!isDestroyed(WARN)) mContentViewCore.removeJavascriptInterface(interfaceName); } /** @@ -2362,7 +2393,7 @@ * @return The AccessibilityNodeProvider, if available, or null otherwise. */ public AccessibilityNodeProvider getAccessibilityNodeProvider() { - return isDestroyed() ? null : mContentViewCore.getAccessibilityNodeProvider(); + return isDestroyed(WARN) ? null : mContentViewCore.getAccessibilityNodeProvider(); } /** @@ -2380,14 +2411,14 @@ } public boolean supportsAccessibilityAction(int action) { - return isDestroyed() ? false : mContentViewCore.supportsAccessibilityAction(action); + return isDestroyed(WARN) ? false : mContentViewCore.supportsAccessibilityAction(action); } /** * @see android.webkit.WebView#performAccessibilityAction(int, Bundle) */ public boolean performAccessibilityAction(int action, Bundle arguments) { - return isDestroyed() ? false + return isDestroyed(WARN) ? false : mContentViewCore.performAccessibilityAction(action, arguments); } @@ -2403,7 +2434,7 @@ public void setNetworkAvailable(boolean networkUp) { if (TRACE) Log.d(TAG, "setNetworkAvailable=" + networkUp); - if (!isDestroyed()) nativeSetJsOnlineProperty(mNativeAwContents, networkUp); + if (!isDestroyed(WARN)) nativeSetJsOnlineProperty(mNativeAwContents, networkUp); } /** @@ -2425,7 +2456,7 @@ */ public void insertVisualStateCallback(long requestId, VisualStateCallback callback) { if (TRACE) Log.d(TAG, "insertVisualStateCallback"); - if (isDestroyed()) throw new IllegalStateException( + if (isDestroyed(NO_WARN)) throw new IllegalStateException( "insertVisualStateCallback cannot be called after the WebView has been destroyed"); nativeInsertVisualStateCallback(mNativeAwContents, requestId, callback); } @@ -2473,13 +2504,13 @@ } public void invokeGeolocationCallback(boolean value, String requestingFrame) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; nativeInvokeGeolocationCallback(mNativeAwContents, value, requestingFrame); } @CalledByNative private void onGeolocationPermissionsShowPrompt(String origin) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; AwGeolocationPermissions permissions = mBrowserContext.getGeolocationPermissions(); // Reject if geoloaction is disabled, or the origin has a retained deny if (!mSettings.getGeolocationEnabled()) { @@ -2665,7 +2696,7 @@ } private void saveWebArchiveInternal(String path, final ValueCallback<String> callback) { - if (path == null || isDestroyed()) { + if (path == null || isDestroyed(WARN)) { ThreadUtils.runOnUiThread(new Runnable() { @Override public void run() { @@ -2713,12 +2744,12 @@ @Override public void extractSmartClipData(int x, int y, int width, int height) { - if (!isDestroyed()) mContentViewCore.extractSmartClipData(x, y, width, height); + if (!isDestroyed(WARN)) mContentViewCore.extractSmartClipData(x, y, width, height); } @Override public void setSmartClipResultHandler(final Handler resultHandler) { - if (isDestroyed()) return; + if (isDestroyed(WARN)) return; if (resultHandler == null) { mContentViewCore.setSmartClipDataListener(null); @@ -2747,7 +2778,7 @@ protected void insertVisualStateCallbackIfNotDestroyed( long requestId, VisualStateCallback callback) { if (TRACE) Log.d(TAG, "insertVisualStateCallbackIfNotDestroyed"); - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; nativeInsertVisualStateCallback(mNativeAwContents, requestId, callback); } @@ -2764,7 +2795,7 @@ @Override public void onDraw(Canvas canvas) { - if (isDestroyed()) { + if (isDestroyed(NO_WARN)) { TraceEvent.instant("EarlyOut_destroyed"); canvas.drawColor(getEffectiveBackgroundColor()); return; @@ -2811,7 +2842,7 @@ @Override public void requestFocus() { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; if (!mContainerView.isInTouchMode() && mSettings.shouldFocusFirstNode()) { nativeFocusFirstNode(mNativeAwContents); } @@ -2832,17 +2863,17 @@ @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return isDestroyed() ? null : mContentViewCore.onCreateInputConnection(outAttrs); + return isDestroyed(NO_WARN) ? null : mContentViewCore.onCreateInputConnection(outAttrs); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - return isDestroyed() ? false : mContentViewCore.onKeyUp(keyCode, event); + return isDestroyed(NO_WARN) ? false : mContentViewCore.onKeyUp(keyCode, event); } @Override public boolean dispatchKeyEvent(KeyEvent event) { - if (isDestroyed()) return false; + if (isDestroyed(NO_WARN)) return false; if (isDpadEvent(event)) { mSettings.setSpatialNavigationEnabled(true); } @@ -2865,7 +2896,7 @@ @Override public boolean onTouchEvent(MotionEvent event) { - if (isDestroyed()) return false; + if (isDestroyed(NO_WARN)) return false; if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { mSettings.setSpatialNavigationEnabled(false); } @@ -2898,22 +2929,22 @@ @Override public boolean onHoverEvent(MotionEvent event) { - return isDestroyed() ? false : mContentViewCore.onHoverEvent(event); + return isDestroyed(NO_WARN) ? false : mContentViewCore.onHoverEvent(event); } @Override public boolean onGenericMotionEvent(MotionEvent event) { - return isDestroyed() ? false : mContentViewCore.onGenericMotionEvent(event); + return isDestroyed(NO_WARN) ? false : mContentViewCore.onGenericMotionEvent(event); } @Override public void onConfigurationChanged(Configuration newConfig) { - if (!isDestroyed()) mContentViewCore.onConfigurationChanged(newConfig); + if (!isDestroyed(NO_WARN)) mContentViewCore.onConfigurationChanged(newConfig); } @Override public void onAttachedToWindow() { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; if (mIsAttachedToWindow) { Log.w(TAG, "onAttachedToWindow called when already attached. Ignoring"); return; @@ -2934,7 +2965,7 @@ @Override public void onDetachedFromWindow() { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; if (!mIsAttachedToWindow) { Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring"); return; @@ -2956,21 +2987,21 @@ @Override public void onWindowFocusChanged(boolean hasWindowFocus) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; mWindowFocused = hasWindowFocus; mContentViewCore.onWindowFocusChanged(hasWindowFocus); } @Override public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; mContainerViewFocused = focused; mContentViewCore.onFocusChanged(focused); } @Override public void onSizeChanged(int w, int h, int ow, int oh) { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; mScrollOffsetManager.setContainerViewSize(w, h); // The AwLayoutSizer needs to go first so that if we're in // fixedLayoutSize mode the update @@ -3048,7 +3079,7 @@ @Override public void computeScroll() { - if (isDestroyed()) return; + if (isDestroyed(NO_WARN)) return; nativeOnComputeScroll(mNativeAwContents, AnimationUtils.currentAnimationTimeMillis()); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index af65580..1a165d0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -38,7 +38,6 @@ import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content_public.browser.AccessibilitySnapshotCallback; import org.chromium.content_public.browser.AccessibilitySnapshotNode; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.net.test.util.TestWebServer; import java.io.InputStream; @@ -124,7 +123,7 @@ // we fail gracefully and do not crash when APIs are invoked after destruction. // Due to the large number of APIs we only test a representative selection here. awContents.clearHistory(); - awContents.loadUrl(new LoadUrlParams("http://www.google.com")); + awContents.loadUrl("http://www.google.com"); awContents.findAllAsync("search"); assertNull(awContents.getUrl()); assertFalse(awContents.canGoBack());
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java index f4eaa682..ebdcc36 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -189,8 +189,7 @@ } @Override public void run() { - awContents.loadUrl(LoadUrlParams.createLoadHttpPostParams(url, - mPostData)); + awContents.postUrl(url, mPostData); } } getInstrumentation().runOnMainSync(new PostUrl(postData)); @@ -235,8 +234,7 @@ getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { - awContents.loadUrl(LoadUrlParams.createLoadDataParams( - data, mimeType, isBase64Encoded)); + awContents.loadData(data, mimeType, isBase64Encoded ? "base64" : null); } }); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java index 9f8f629..438b0d3 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
@@ -19,7 +19,6 @@ import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.HistoryUtils; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.net.test.util.TestWebServer; import java.util.ArrayList; @@ -95,9 +94,7 @@ runTestOnUiThread(new Runnable() { @Override public void run() { - LoadUrlParams params = new LoadUrlParams(url); - params.setExtraHeaders(extraHeaders); - awContents.loadUrl(params); + awContents.loadUrl(url, extraHeaders); } }); onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
diff --git a/android_webview/android_webview_shell_test_apk.isolate b/android_webview/system_webview_shell_test_apk.isolate similarity index 100% rename from android_webview/android_webview_shell_test_apk.isolate rename to android_webview/system_webview_shell_test_apk.isolate
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java index 489424e..ecfca186 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
@@ -42,7 +42,6 @@ import org.chromium.base.Log; import org.chromium.base.TraceEvent; import org.chromium.content.app.ContentApplication; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.WebContents; @@ -106,7 +105,7 @@ startupUrl = INITIAL_URL; } - mAwTestContainerView.getAwContents().loadUrl(new LoadUrlParams(startupUrl)); + mAwTestContainerView.getAwContents().loadUrl(startupUrl); AwContents.setShouldDownloadFavicons(); mUrlTextView.setText(startupUrl); @@ -226,7 +225,7 @@ } catch (URISyntaxException e) { // Ignore syntax errors. } - mAwTestContainerView.getAwContents().loadUrl(new LoadUrlParams(url)); + mAwTestContainerView.getAwContents().loadUrl(url); mUrlTextView.clearFocus(); setKeyboardVisibilityForUrl(false); mAwTestContainerView.requestFocus();
diff --git a/android_webview/tools/PageCycler/AndroidManifest.xml b/android_webview/tools/PageCycler/AndroidManifest.xml new file mode 100644 index 0000000..241be5d --- /dev/null +++ b/android_webview/tools/PageCycler/AndroidManifest.xml
@@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright 2015 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. +--> + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.webview_shell.page_cycler" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" /> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.READ_LOGS"/> + + <application android:hardwareAccelerated="false"> + <uses-library android:name="android.test.runner" /> + <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" + android:exported="true"/> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="org.chromium.webview_shell" + android:label="Page cycler for org.chromium.webview_shell" /> +</manifest>
diff --git a/android_webview/tools/PageCycler/DEPS b/android_webview/tools/PageCycler/DEPS new file mode 100644 index 0000000..d8dc2b07 --- /dev/null +++ b/android_webview/tools/PageCycler/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+content/public/test/android/javatests", +]
diff --git a/android_webview/tools/PageCycler/src/org/chromium/webview_shell/page_cycler/PageCyclerTest.java b/android_webview/tools/PageCycler/src/org/chromium/webview_shell/page_cycler/PageCyclerTest.java new file mode 100644 index 0000000..bc29b7b7e --- /dev/null +++ b/android_webview/tools/PageCycler/src/org/chromium/webview_shell/page_cycler/PageCyclerTest.java
@@ -0,0 +1,163 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.webview_shell.page_cycler; + +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import org.chromium.base.test.util.Restriction; +import org.chromium.content.browser.test.util.CallbackHelper; +import org.chromium.webview_shell.PageCyclerTestActivity; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * Tests running on bots with internet connection to load popular urls, + * making sure webview doesn't crash + */ +public class PageCyclerTest + extends ActivityInstrumentationTestCase2<PageCyclerTestActivity> { + + private static final long TIMEOUT_IN_SECS = 20; + + private PageCyclerTestActivity mTestActivity; + + public PageCyclerTest() { + super(PageCyclerTestActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestActivity = getActivity(); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitGoogleCom() throws Throwable { + //TODO(yolandyan@): verify the page + visitUrlSync("http://google.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitFacebookCom() throws Throwable { + visitUrlSync("http://facebook.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitWikipediaOrg() throws Throwable { + visitUrlSync("http://wikipedia.org"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitAmazonCom() throws Throwable { + visitUrlSync("http://amazon.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitYoutubeCom() throws Throwable { + visitUrlSync("http://youtube.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitYahooCom() throws Throwable { + visitUrlSync("http://yahoo.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitEbayCom() throws Throwable { + visitUrlSync("http://ebay.com"); + } + + @LargeTest + @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + public void testVisitRedditCom() throws Throwable { + visitUrlSync("http://reddit.com"); + } + + private static class PageCyclerWebViewClient extends WebViewClient { + private final CallbackHelper mPageFinishedCallback; + private final CallbackHelper mErrorCallback; + + public PageCyclerWebViewClient() { + super(); + mPageFinishedCallback = new CallbackHelper(); + mErrorCallback = new CallbackHelper(); + } + + public CallbackHelper getPageFinishedCallback() { + return mPageFinishedCallback; + } + + public CallbackHelper getErrorCallback() { + return mErrorCallback; + } + + @Override + public void onPageFinished(WebView view, String url) { + mPageFinishedCallback.notifyCalled(); + } + + // TODO(yolandyan@): create helper class to manage network error + @Override + public void onReceivedError(WebView webview, int code, String description, + String failingUrl) { + mErrorCallback.notifyCalled(); + } + } + + private void visitUrlSync(final String url) throws Throwable { + final PageCyclerWebViewClient pageCyclerWebViewClient = new PageCyclerWebViewClient(); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + final WebView view = mTestActivity.getWebView(); + WebSettings settings = view.getSettings(); + settings.setJavaScriptEnabled(true); + view.setWebViewClient(pageCyclerWebViewClient); + } + }); + CallbackHelper pageFinishedCallback = pageCyclerWebViewClient.getPageFinishedCallback(); + CallbackHelper errorCallback = pageCyclerWebViewClient.getErrorCallback(); + loadUrlSync(url, pageFinishedCallback, errorCallback); + } + + private void loadUrlSync(final String url, final CallbackHelper pageFinishedCallback, + final CallbackHelper errorCallback) throws InterruptedException { + boolean timeout = false; + int pageFinishedCount = pageFinishedCallback.getCallCount(); + int errorCount = errorCallback.getCallCount(); + loadUrlAsync(url); + try { + pageFinishedCallback.waitForCallback(pageFinishedCount, pageFinishedCount + 1, + TIMEOUT_IN_SECS, TimeUnit.SECONDS); + } catch (TimeoutException ex) { + timeout = true; + } + assertEquals(String.format("Network error while accessing %s", url), errorCount, + errorCallback.getCallCount()); + assertFalse(String.format("Timeout error while accessing %s", url), timeout); + } + + private void loadUrlAsync(final String url) { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + WebView view = mTestActivity.getWebView(); + view.loadUrl(url); + } + }); + } +}
diff --git a/android_webview/tools/WebViewShell/AndroidManifest.xml b/android_webview/tools/WebViewShell/AndroidManifest.xml index 6223d823..deec550 100644 --- a/android_webview/tools/WebViewShell/AndroidManifest.xml +++ b/android_webview/tools/WebViewShell/AndroidManifest.xml
@@ -28,30 +28,30 @@ android:label="@string/app_name" android:theme="@android:style/Theme.Light" > <activity - android:name=".TelemetryActivity" + android:name="org.chromium.webview_shell.TelemetryActivity" android:label="@string/title_activity_telemetry" android:exported="true"> </activity> <activity - android:name=".TelemetryMemoryPressureActivity" + android:name="org.chromium.webview_shell.TelemetryMemoryPressureActivity" android:launchMode="singleTask" android:label="@string/title_activity_telemetry" android:exported="true"> </activity> <activity - android:name=".JankActivity" + android:name="org.chromium.webview_shell.JankActivity" android:label="@string/title_activity_jank" android:noHistory="true" android:exported="true"> </activity> <activity - android:name=".StartupTimeActivity" + android:name="org.chromium.webview_shell.StartupTimeActivity" android:label="@string/title_activity_startup_time" android:noHistory="true" android:exported="true"> </activity> <activity - android:name=".WebViewBrowserActivity" + android:name="org.chromium.webview_shell.WebViewBrowserActivity" android:label="@string/title_activity_browser" android:exported="true"> <intent-filter> @@ -80,17 +80,19 @@ </intent-filter> </activity> <activity - android:name=".WebViewLayoutTestActivity" + android:name="org.chromium.webview_shell.WebViewLayoutTestActivity" android:label="@string/title_activity_layout_test" android:exported="true"> </activity> <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" android:exported="true"/> + <activity + android:name="org.chromium.webview_shell.PageCyclerTestActivity" + android:label="@string/title_activity_page_cycler" + android:exported="true"> + </activity> + <uses-library android:name="android.test.runner" /> </application> - - <instrumentation android:name="org.chromium.webview_shell.WebViewLayoutTestRunner" - android:targetPackage="org.chromium.webview_shell" - android:label="Tests for org.chromium.webview_shell" /> </manifest>
diff --git a/android_webview/tools/WebViewShell/res/values/strings.xml b/android_webview/tools/WebViewShell/res/values/strings.xml index b8058ea..3c394e1 100644 --- a/android_webview/tools/WebViewShell/res/values/strings.xml +++ b/android_webview/tools/WebViewShell/res/values/strings.xml
@@ -11,6 +11,7 @@ <string name="title_activity_startup_time">WebView Startup Time Tester</string> <string name="title_activity_browser">WebView Browser Tester</string> <string name="title_activity_layout_test">WebView Layout Test</string> + <string name="title_activity_page_cycler">WebView Page Cycler Test</string> <string name="menu_about">About WebView</string> <string name="load_url">Load URL</string> </resources>
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/PageCyclerTestActivity.java b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/PageCyclerTestActivity.java new file mode 100644 index 0000000..632c1e9c --- /dev/null +++ b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/PageCyclerTestActivity.java
@@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.webview_shell; + +import android.app.Activity; +import android.os.Bundle; +import android.webkit.WebView; + +/** + * This activity is used for loading urls using webview on Appurify bots to make sure the + * webview doesn't crash. + */ +public class PageCyclerTestActivity extends Activity { + + private WebView mWebView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_webview); + mWebView = (WebView) findViewById(R.id.webview); + } + + public WebView getWebView() { + return mWebView; + } +} \ No newline at end of file
diff --git a/android_webview/tools/WebViewShell/test/run_tests.sh b/android_webview/tools/WebViewShell/test/run_tests.sh index 516a3f7..9cf316b 100755 --- a/android_webview/tools/WebViewShell/test/run_tests.sh +++ b/android_webview/tools/WebViewShell/test/run_tests.sh
@@ -11,7 +11,7 @@ $TESTRUNNER instrumentation \ --test-apk AndroidWebViewShell \ -f 'WebViewLayoutTest*' \ - --isolate-file-path android_webview/android_webview_shell_test_apk.isolate + --isolate-file-path android_webview/system_webview_shell_test_apk.isolate if [ "$1" = "rebaseline" ]; then adb shell am instrument -w -e mode rebaseline -e class \
diff --git a/android_webview/tools/WebViewShellTest/AndroidManifest.xml b/android_webview/tools/WebViewShellTest/AndroidManifest.xml new file mode 100644 index 0000000..00ebd4c5 --- /dev/null +++ b/android_webview/tools/WebViewShellTest/AndroidManifest.xml
@@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright 2015 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. +--> + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.webview_shell.test" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" /> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.CAMERA"/> + <uses-permission android:name="android.permission.RECORD_AUDIO"/> + <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + + <application android:hardwareAccelerated="false"> + <uses-library android:name="android.test.runner" /> + <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" + android:exported="true"/> + </application> + + <instrumentation android:name="org.chromium.webview_shell.test.WebViewLayoutTestRunner" + android:targetPackage="org.chromium.webview_shell" + android:label="Layout tests for org.chromium.webview_shell" /> +</manifest>
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java b/android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTest.java similarity index 98% rename from android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java rename to android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTest.java index 4d84446..8285679 100644 --- a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java +++ b/android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.webview_shell; +package org.chromium.webview_shell.test; import android.os.Environment; import android.test.ActivityInstrumentationTestCase2; @@ -11,6 +11,7 @@ import junit.framework.ComparisonFailure; import org.chromium.base.Log; +import org.chromium.webview_shell.WebViewLayoutTestActivity; import java.io.BufferedReader; import java.io.File;
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java b/android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTestRunner.java similarity index 96% rename from android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java rename to android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTestRunner.java index 147c3e5..44b745f 100644 --- a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java +++ b/android_webview/tools/WebViewShellTest/src/org/chromium/webview_shell/test/WebViewLayoutTestRunner.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.webview_shell; +package org.chromium.webview_shell.test; import android.os.Bundle; import android.test.AndroidTestRunner;
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc index 80121b2..203ab940 100644 --- a/base/profiler/native_stack_sampler_win.cc +++ b/base/profiler/native_stack_sampler_win.cc
@@ -77,6 +77,7 @@ return basic_info.Teb; } +#if defined(_WIN64) // If the value at |pointer| points to the original stack, rewrite it to point // to the corresponding location in the copied stack. void RewritePointerIfInOriginalStack(uintptr_t top, uintptr_t bottom, @@ -87,6 +88,7 @@ static_cast<unsigned char*>(stack_copy) + (value - bottom)); } } +#endif // Rewrites possible pointers to locations within the stack to point to the // corresponding locations in the copy, and rewrites the non-volatile registers
diff --git a/base/sync_socket_unittest.cc b/base/sync_socket_unittest.cc index ff9b8bc8..7c8c97cb 100644 --- a/base/sync_socket_unittest.cc +++ b/base/sync_socket_unittest.cc
@@ -3,10 +3,6 @@ // found in the LICENSE file. #include "base/basictypes.h" -// TODO(ellyjones): Remove once http://crbug.com/523296 is fixed. -#if defined(OS_IOS) && !TARGET_IPHONE_SIMULATOR -#include "base/ios/ios_util.h" -#endif #include "base/sync_socket.h" #include "base/threading/simple_thread.h" #include "base/time/time.h" @@ -118,11 +114,6 @@ } TEST(CancelableSyncSocket, CancelReceiveShutdown) { -// TODO(ellyjones): This test fails on iOS 7 devices. http://crbug.com/523296 -#if defined(OS_IOS) && !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS8OrLater()) - return; -#endif base::CancelableSyncSocket socket_a, socket_b; ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&socket_a, &socket_b));
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc index 1e05e68..0fee10d 100644 --- a/base/trace_event/trace_event_etw_export_win.cc +++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -85,7 +85,8 @@ "v8", // 0x400 "disabled-by-default-cc.debug", // 0x800 "disabled-by-default-cc.debug.picture", // 0x1000 - "disabled-by-default-toplevel.flow"}; // 0x2000 + "disabled-by-default-toplevel.flow", // 0x2000 + "startup"}; // 0x4000 const char kOtherEventsGroupName[] = "__OTHER_EVENTS"; // 0x2000000000000000 const char kDisabledOtherEventsGroupName[] = "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000
diff --git a/blimp/docs/container.md b/blimp/docs/container.md index 0150e2a8..e34a547 100644 --- a/blimp/docs/container.md +++ b/blimp/docs/container.md
@@ -5,8 +5,7 @@ The steps are: -1. Bundle the engine and its dependencies using -[`bundle-engine.py`](../tools/bundle-engine.py). +1. Bundle the engine and its dependencies. 1. Build a Docker image. @@ -32,16 +31,9 @@ ## Bundle Engine -Assuming the current directory is `src/` and you've already built the engine, -you can bundle it into a tarfile by running: +The `blimp/engine:bundle_blimp_engine` build target will bundle the engine and +its dependencies into a tarfile, which can be used to build a Docker image. -```bash -./blimp/tools/bundle-engine.py \ - --build-dir ./out-linux/Debug \ - --dockerfile ./blimp/engine/Dockerfile \ - --target blimp/engine:blimp_engine \ - --output ./out-linux/Debug/blimp_engine_deps.tar -``` ## Build Docker Image
diff --git a/blimp/engine/BUILD.gn b/blimp/engine/BUILD.gn index ecc1f61..1be9204 100644 --- a/blimp/engine/BUILD.gn +++ b/blimp/engine/BUILD.gn
@@ -56,11 +56,42 @@ ] } - # A stand-in for the Blimp Engine so we can get the Docker packaging working. group("blimp_engine") { data_deps = [ ":blimp_engine_app", ":pak", ] } + + # Builds and bundles the engine into a tarball that can be used to build a + # Docker image. + action("bundle_blimp_engine") { + script = "//blimp/tools/bundle-engine.py" + + # These form the arguments to the script. + build_dir = rebase_path(root_out_dir) + dockerfile = rebase_path("//blimp/engine/Dockerfile") + target = "//blimp/engine:blimp_engine" + bundle = "$root_out_dir/blimp_engine_bundle.tar" + + deps = [ + target, + ] + inputs = [ + dockerfile, + ] + outputs = [ + bundle, + ] + args = [ + "--build-dir", + build_dir, + "--dockerfile", + dockerfile, + "--target", + target, + "--output", + rebase_path(bundle), + ] + } }
diff --git a/breakpad/README.chromium b/breakpad/README.chromium index 8852412..bab0a12 100644 --- a/breakpad/README.chromium +++ b/breakpad/README.chromium
@@ -1,6 +1,6 @@ Name: Breakpad, An open-source multi-platform crash reporting system Short Name: breakpad -URL: http://code.google.com/p/google-breakpad/ +URL: https://chromium.googlesource.com/breakpad/breakpad License: New BSD, Apple PSL 2.0 and Apache 2.0 Security Critical: no
diff --git a/build/all.gyp b/build/all.gyp index dde5e32..df38f99 100644 --- a/build/all.gyp +++ b/build/all.gyp
@@ -85,7 +85,7 @@ 'dependencies': [ '../android_webview/android_webview.gyp:android_webview_apk', '../android_webview/android_webview.gyp:system_webview_apk', - '../android_webview/android_webview_shell.gyp:android_webview_shell_apk', + '../android_webview/android_webview_shell.gyp:system_webview_shell_apk', '../chrome/android/chrome_apk.gyp:chrome_public_apk', '../chrome/android/chrome_apk.gyp:chrome_sync_shell_apk', '../remoting/remoting.gyp:remoting_apk', @@ -870,6 +870,8 @@ # Unit test bundles packaged as an apk. '../android_webview/android_webview.gyp:android_webview_test_apk', '../android_webview/android_webview.gyp:android_webview_unittests_apk', + '../android_webview/android_webview_shell.gyp:system_webview_shell_layout_test_apk', + '../android_webview/android_webview_shell.gyp:system_webview_shell_page_cycler_apk', '../chrome/android/chrome_apk.gyp:chrome_public_test_apk', '../chrome/android/chrome_apk.gyp:chrome_sync_shell_test_apk', '../chrome/chrome.gyp:chrome_junit_tests',
diff --git a/build/android/devil/android/device_utils.py b/build/android/devil/android/device_utils.py index e9d1693..85472e78 100644 --- a/build/android/devil/android/device_utils.py +++ b/build/android/devil/android/device_utils.py
@@ -68,6 +68,7 @@ 'android.permission.ACCESS_NETWORK_STATE', 'android.permission.BLUETOOTH', 'android.permission.BLUETOOTH_ADMIN', + 'android.permission.DOWNLOAD_WITHOUT_NOTIFICATION', 'android.permission.INTERNET', 'android.permission.MANAGE_ACCOUNTS', 'android.permission.MODIFY_AUDIO_SETTINGS', @@ -625,6 +626,10 @@ apks_to_install, partial=partial, reinstall=reinstall) else: self.adb.Install(base_apk, reinstall=reinstall) + if (permissions is None + and self.build_version_sdk >= version_codes.MARSHMALLOW): + permissions = apk_helper.ApkHelper(base_apk).GetPermissions() + self.GrantPermissions(package_name, permissions) # Upon success, we know the device checksums, but not their paths. if host_checksums is not None: self._cache['package_apk_checksums'][package_name] = host_checksums @@ -633,11 +638,6 @@ # consistent, we explicitly terminate it when skipping the install. self.ForceStop(package_name) - if (permissions is None - and self.build_version_sdk >= version_codes.MARSHMALLOW): - permissions = apk_helper.ApkHelper(base_apk).GetPermissions() - self.GrantPermissions(package_name, permissions) - @decorators.WithTimeoutAndRetriesFromInstance() def Uninstall(self, package_name, keep_data=False, timeout=None, retries=None): @@ -1139,9 +1139,8 @@ sums = md5sum.CalculateDeviceMd5Sums(specific_device_paths, self) - if self._enable_device_files_cache: - cache_entry = [ignore_other_files, sums] - self._cache['device_path_checksums'][device_path] = cache_entry + cache_entry = [ignore_other_files, sums] + self._cache['device_path_checksums'][device_path] = cache_entry return dict(sums) host_checksums, device_checksums = reraiser_thread.RunAsync(( @@ -1173,8 +1172,6 @@ to_delete = device_checksums.keys() def cache_commit_func(): - if not self._enable_device_files_cache: - return new_sums = {posixpath.join(device_path, path[len(host_path) + 1:]): val for path, val in host_checksums.iteritems()} cache_entry = [ignore_other_files, new_sums]
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 2ab568f..1410d19 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -32,8 +32,12 @@ default=[]) parser.add_argument('--android-abi', help='Android architecture to use for native libraries') + parser.add_argument('--create-placeholder-lib', + action='store_true', + help='Whether to add a dummy library file') options = parser.parse_args(args) - if options.native_libs_dir and not options.android_abi: + if not options.android_abi and (options.native_libs_dir or + options.create_placeholder_lib): raise Exception('Must specify --android-abi with --native-libs-dir') return options @@ -68,6 +72,10 @@ for path in native_libs: basename = os.path.basename(path) apk.write(path, 'lib/%s/%s' % (options.android_abi, basename)) + if options.create_placeholder_lib: + # Make it non-empty so that its checksum is non-zero and is not + # ignored by md5_check. + apk.writestr('lib/%s/libplaceholder.so' % options.android_abi, ':-)') if options.dex_file: apk.write(options.dex_file, 'classes.dex') @@ -80,6 +88,7 @@ on_stale_md5, options, input_paths=input_paths, + input_strings=[options.create_placeholder_lib, options.android_abi], output_paths=[options.output_apk])
diff --git a/build/common.gypi b/build/common.gypi index f5743e21..ea6da8e 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -3118,9 +3118,6 @@ ['chromium_code==0', { 'variables': { 'clang_warning_flags': [ - # TODO(thakis): Move this suppression into individual third-party - # libraries as required. http://crbug.com/505316. - '-Wno-unused-function', # Lots of third-party libraries have unused variables. Instead of # suppressing them individually, we just blanket suppress them here. '-Wno-unused-variable',
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index ca71105..19318a7 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -479,6 +479,7 @@ # resource_packaged_apk_path: Path to .ap_ to use. # output_apk_path: Output path for the generated .apk. # native_libs_dir: Directory containing native libraries. +# create_placeholder_lib: Whether to add a dummy lib to the apk. template("package_apk") { action(target_name) { forward_variables_from(invoker, @@ -487,6 +488,9 @@ "public_deps", "testonly", ]) + _create_placeholder_lib = defined(invoker.create_placeholder_lib) && + invoker.create_placeholder_lib + script = "//build/android/gyp/apkbuilder.py" depfile = "$target_gen_dir/$target_name.d" data_deps = [ @@ -519,13 +523,16 @@ _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir) args += [ "--dex-file=$_rebased_dex_path" ] } + if (defined(invoker.native_libs_dir) || _create_placeholder_lib) { + args += [ "--android-abi=$android_app_abi" ] + } if (defined(invoker.native_libs_dir)) { _rebased_native_libs_dir = rebase_path(invoker.native_libs_dir, root_build_dir) - args += [ - "--native-libs-dir=$_rebased_native_libs_dir/$android_app_abi", - "--android-abi=$android_app_abi", - ] + args += [ "--native-libs-dir=$_rebased_native_libs_dir/$android_app_abi" ] + } + if (_create_placeholder_lib) { + args += [ "--create-placeholder-lib" ] } } } @@ -813,7 +820,11 @@ get_label_info(_dex_target, "target_gen_dir") + "/bootstrap.dex" } - # TODO(agrieve): Add a placeholder .so for http://crbug.com/384638 + # http://crbug.com/384638 + if (defined(invoker.native_libs_dir)) { + create_placeholder_lib = true + } + output_apk_path = _incremental_packaged_apk_path resource_packaged_apk_path = _incremental_resource_packaged_apk_path }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 6c52844..1d0a1f7 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1221,7 +1221,7 @@ # The dependency that makes the chromium linker, if any is needed. _chromium_linker_dep = [] - if (defined(invoker.native_libs)) { + if (defined(invoker.native_libs) && invoker.native_libs != []) { _use_chromium_linker = false if (defined(invoker.use_chromium_linker)) { _use_chromium_linker =
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index d039845..7c2e3802 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -50,20 +50,20 @@ use_gold = is_linux && current_cpu == "x64" # When we are going to use gold we need to find it. - if (use_gold) { - gold_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", - root_build_dir) - } else { - gold_path = "" - } + # This is initialized below, after use_gold might have been overridden. + gold_path = false # use_debug_fission: whether to use split DWARF debug info # files. This can reduce link time significantly, but is incompatible # with some utilities such as icecc and ccache. Requires gold and # gcc >= 4.8 or clang. # http://gcc.gnu.org/wiki/DebugFission - use_debug_fission = is_debug && !is_win && use_gold && - linux_use_bundled_binutils && !use_ccache + # + # This is a placeholder value indicating that the code below should set + # the default. This is necessary to delay the evaluation of the default + # value expression until after its input values such as use_gold have + # been set, e.g. by a toolchain_args() block. + use_debug_fission = "default" if (is_win) { # Whether the VS xtree header has been patched to disable warning 4702. If @@ -73,6 +73,21 @@ } } +# Apply the default logic for these values if they were not set explicitly. +if (gold_path == false) { + if (use_gold) { + gold_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", + root_build_dir) + } else { + gold_path = "" + } +} + +if (use_debug_fission == "default") { + use_debug_fission = is_debug && !is_win && use_gold && + linux_use_bundled_binutils && !use_ccache +} + # default_include_dirs --------------------------------------------------------- # # This is a separate config so that third_party code (which would not use the @@ -116,6 +131,12 @@ configs += [ "//build/config/mac:compiler" ] } + # See the definitions below. + configs += [ + ":compiler_cpu_abi", + ":compiler_codegen", + ] + # In general, Windows is totally different, but all the other builds share # some common GCC configuration. if (!is_win) { @@ -198,124 +219,6 @@ } } - # CPU architecture. We may or may not be doing a cross compile now, so for - # simplicity we always explicitly set the architecture. - if (current_cpu == "x64") { - cflags += [ - "-m64", - "-march=x86-64", - ] - ldflags += [ "-m64" ] - } else if (current_cpu == "x86") { - cflags += [ "-m32" ] - ldflags += [ "-m32" ] - if (is_clang) { - cflags += [ - # Else building libyuv gives clang's register allocator issues, - # see llvm.org/PR15798 / crbug.com/233709 - "-momit-leaf-frame-pointer", - - # Align the stack on 16-byte boundaries, http://crbug.com/418554. - "-mstack-alignment=16", - "-mstackrealign", - ] - } - } else if (current_cpu == "arm") { - if (is_clang && !is_android && !is_nacl) { - cflags += [ - "-target", - "arm-linux-gnueabihf", - ] - ldflags += [ - "-target", - "arm-linux-gnueabihf", - ] - - # We need to disable clang's builtin assembler as it can't - # handle several asm files, crbug.com/124610 - cflags += [ "-no-integrated-as" ] - } - if (!is_nacl) { - cflags += [ - "-march=$arm_arch", - "-mfloat-abi=$arm_float_abi", - ] - if (arm_use_thumb) { - cflags += [ "-mthumb" ] - if (is_android && !is_clang) { - # Clang doesn't support this option. - cflags += [ "-mthumb-interwork" ] - } - } - } - if (arm_tune != "") { - cflags += [ "-mtune=$arm_tune" ] - } - if (!is_clang) { - # Clang doesn't support these flags. - cflags += [ - # The tree-sra optimization (scalar replacement for - # aggregates enabling subsequent optimizations) leads to - # invalid code generation when using the Android NDK's - # compiler (r5-r7). This can be verified using - # webkit_unit_tests' WTF.Checked_int8_t test. - "-fno-tree-sra", - - # The following option is disabled to improve binary - # size and performance in gcc 4.9. - "-fno-caller-saves", - ] - } - } else if (current_cpu == "mipsel") { - if (mips_arch_variant == "r6") { - cflags += [ - "-mips32r6", - "-Wa,-mips32r6", - ] - if (is_android) { - ldflags += [ - "-mips32r6", - "-Wl,-melf32ltsmip", - ] - } - } else if (mips_arch_variant == "r2") { - cflags += [ - "-mips32r2", - "-Wa,-mips32r2", - ] - if (mips_float_abi == "hard" && mips_fpu_mode != "") { - cflags += [ "-m$mips_fpu_mode" ] - } - } else if (mips_arch_variant == "r1") { - cflags += [ - "-mips32", - "-Wa,-mips32", - ] - } - - if (mips_dsp_rev == 1) { - cflags += [ "-mdsp" ] - } else if (mips_dsp_rev == 2) { - cflags += [ "-mdspr2" ] - } - - cflags += [ "-m${mips_float_abi}-float" ] - } else if (current_cpu == "mips64el") { - if (mips_arch_variant == "r6") { - cflags += [ - "-mips64r6", - "-Wa,-mips64r6", - ] - ldflags += [ "-mips64r6" ] - } else if (mips_arch_variant == "r2") { - cflags += [ - "-mips64r2", - "-Wa,-mips64r2", - ] - ldflags += [ "-mips64r2" ] - } - } - defines += [ "_FILE_OFFSET_BITS=64" ] if (!is_android) { @@ -431,6 +334,155 @@ } } +# This provides the basic options to select the target CPU and ABI. +# It is factored out of "compiler" so that special cases can use this +# without using everything that "compiler" brings in. Options that +# tweak code generation for a particular CPU do not belong here! +# See "compiler_codegen", below. +config("compiler_cpu_abi") { + cflags = [] + ldflags = [] + + if (is_posix && !(is_mac || is_ios)) { + # CPU architecture. We may or may not be doing a cross compile now, so for + # simplicity we always explicitly set the architecture. + if (current_cpu == "x64") { + cflags += [ + "-m64", + "-march=x86-64", + ] + ldflags += [ "-m64" ] + } else if (current_cpu == "x86") { + cflags += [ "-m32" ] + ldflags += [ "-m32" ] + } else if (current_cpu == "arm") { + if (is_clang && !is_android && !is_nacl) { + cflags += [ + "-target", + "arm-linux-gnueabihf", + ] + ldflags += [ + "-target", + "arm-linux-gnueabihf", + ] + } + if (!is_nacl) { + cflags += [ + "-march=$arm_arch", + "-mfloat-abi=$arm_float_abi", + ] + if (arm_use_thumb) { + cflags += [ "-mthumb" ] + if (is_android && !is_clang) { + # Clang doesn't support this option. + cflags += [ "-mthumb-interwork" ] + } + } + } + if (arm_tune != "") { + cflags += [ "-mtune=$arm_tune" ] + } + } else if (current_cpu == "mipsel") { + if (mips_arch_variant == "r6") { + cflags += [ + "-mips32r6", + "-Wa,-mips32r6", + ] + if (is_android) { + ldflags += [ + "-mips32r6", + "-Wl,-melf32ltsmip", + ] + } + } else if (mips_arch_variant == "r2") { + cflags += [ + "-mips32r2", + "-Wa,-mips32r2", + ] + if (mips_float_abi == "hard" && mips_fpu_mode != "") { + cflags += [ "-m$mips_fpu_mode" ] + } + } else if (mips_arch_variant == "r1") { + cflags += [ + "-mips32", + "-Wa,-mips32", + ] + } + + if (mips_dsp_rev == 1) { + cflags += [ "-mdsp" ] + } else if (mips_dsp_rev == 2) { + cflags += [ "-mdspr2" ] + } + + cflags += [ "-m${mips_float_abi}-float" ] + } else if (current_cpu == "mips64el") { + if (mips_arch_variant == "r6") { + cflags += [ + "-mips64r6", + "-Wa,-mips64r6", + ] + ldflags += [ "-mips64r6" ] + } else if (mips_arch_variant == "r2") { + cflags += [ + "-mips64r2", + "-Wa,-mips64r2", + ] + ldflags += [ "-mips64r2" ] + } + } + } + + asmflags = cflags +} + +# This provides options to tweak code generation that are necessary +# for particular Chromium code or for working around particular +# compiler bugs (or the combination of the two). +config("compiler_codegen") { + cflags = [] + + if (is_posix && !is_mac && !is_ios && !is_nacl) { + if (current_cpu == "x86") { + if (is_clang) { + cflags += [ + # Else building libyuv gives clang's register allocator issues, + # see llvm.org/PR15798 / crbug.com/233709 + "-momit-leaf-frame-pointer", + + # Align the stack on 16-byte boundaries, http://crbug.com/418554. + "-mstack-alignment=16", + "-mstackrealign", + ] + } + } else if (current_cpu == "arm") { + if (is_clang) { + if (!is_android) { + # We need to disable clang's builtin assembler as it can't + # handle several asm files, crbug.com/124610 + cflags += [ "-no-integrated-as" ] + } + } else { + # Clang doesn't support these flags. + cflags += [ + # The tree-sra optimization (scalar replacement for + # aggregates enabling subsequent optimizations) leads to + # invalid code generation when using the Android NDK's + # compiler (r5-r7). This can be verified using + # webkit_unit_tests' WTF.Checked_int8_t test. + "-fno-tree-sra", + + # The following option is disabled to improve binary + # size and performance in gcc 4.9. + "-fno-caller-saves", + ] + } + } + } + + asmflags = cflags +} + config("compiler_arm_fpu") { if (current_cpu == "arm" && !is_ios && !is_nacl) { cflags = [ "-mfpu=$arm_fpu" ] @@ -776,10 +828,6 @@ if (is_clang) { cflags += [ - # TODO(thakis): Move this suppression into individual third-party - # libraries as required. http://crbug.com/505316. - "-Wno-unused-function", - # Lots of third-party libraries have unused variables. Instead of # suppressing them individually, we just blanket suppress them here. "-Wno-unused-variable",
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index 00e5107..d9169e4 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -57,7 +57,6 @@ IDR_POLICY_JS IDR_PREF_HASH_SEED_BIN IDR_PRINTER_FAVICON -IDR_SAD_FAVICON IDR_SAD_TAB IDR_SIGNIN_INTERNALS_INDEX_HTML IDR_SIGNIN_INTERNALS_INDEX_JS
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index 065f132..191971d 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -246,11 +246,6 @@ "race:SkFontConfigInterface::GetSingletonDirectInterface\n" "race:FcStrStaticName\n" -// http://crbug.com/372807 -"deadlock:net::X509Certificate::CreateCertificateListFromBytes\n" -"deadlock:net::X509Certificate::CreateFromBytes\n" -"deadlock:net::SSLClientSocketNSS::Core::DoHandshakeLoop\n" - // http://crbug.com/374135 "race:media::AlsaWrapper::PcmWritei\n"
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni index 042a836..48099ea2 100644 --- a/build/toolchain/gcc_toolchain.gni +++ b/build/toolchain/gcc_toolchain.gni
@@ -81,6 +81,9 @@ # - use_goma # Override the global use_goma setting, useful to opt-out of goma in a # particular toolchain by setting use_gome = false in it. +# - use_gold +# Override the global use_gold setting, useful if the particular +# toolchain has a custom link step that is not actually using Gold. template("gcc_toolchain") { toolchain(target_name) { assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") @@ -344,6 +347,7 @@ "is_clang", "is_component_build", "is_nacl_glibc", + "use_gold", ]) if (defined(invoker.clear_sanitizers) && invoker.clear_sanitizers) { @@ -360,3 +364,42 @@ forward_variables_from(invoker, [ "deps" ]) } } + +# This is a shorthand for gcc_toolchain instances based on the +# Chromium-built version of Clang. Only the toolchain_cpu and +# toolchain_os variables need to be specified by the invoker, and +# optionally toolprefix if it's a cross-compile case. Note that for +# a cross-compile case this toolchain requires a config to pass the +# appropriate -target option, or else it will actually just be doing +# a native compile. The invoker can optionally override use_gold too. +template("clang_toolchain") { + assert(defined(invoker.toolchain_cpu), + "clang_toolchain() must specify a \"toolchain_cpu\"") + assert(defined(invoker.toolchain_os), + "clang_toolchain() must specify a \"toolchain_os\"") + if (defined(invoker.toolprefix)) { + toolprefix = invoker.toolprefix + } else { + toolprefix = "" + } + + gcc_toolchain(target_name) { + prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", + root_build_dir) + cc = "$prefix/clang" + cxx = "$prefix/clang++" + ld = cxx + is_clang = true + + readelf = "${toolprefix}readelf" + ar = "${toolprefix}ar" + nm = "${toolprefix}nm" + + forward_variables_from(invoker, + [ + "toolchain_cpu", + "toolchain_os", + "use_gold", + ]) + } +}
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn index 2e24938..7bd9cbc1 100644 --- a/build/toolchain/linux/BUILD.gn +++ b/build/toolchain/linux/BUILD.gn
@@ -5,22 +5,10 @@ import("//build/config/sysroot.gni") import("//build/toolchain/gcc_toolchain.gni") -gcc_toolchain("clang_arm") { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - cc = "$prefix/clang" - cxx = "$prefix/clang++" - - toolprefix = "arm-linux-gnueabihf-" - readelf = "${toolprefix}readelf" - ar = "${toolprefix}ar" - ld = cxx - readelf = "${toolprefix}readelf" - nm = "${toolprefix}nm" - +clang_toolchain("clang_arm") { toolchain_cpu = "arm" toolchain_os = "linux" - is_clang = true + toolprefix = "arm-linux-gnueabihf-" } gcc_toolchain("arm") { @@ -39,19 +27,9 @@ is_clang = false } -gcc_toolchain("clang_x86") { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - cc = "$prefix/clang" - cxx = "$prefix/clang++" - readelf = "readelf" - nm = "nm" - ar = "ar" - ld = cxx - +clang_toolchain("clang_x86") { toolchain_cpu = "x86" toolchain_os = "linux" - is_clang = true } gcc_toolchain("x86") { @@ -68,20 +46,9 @@ is_clang = false } -gcc_toolchain("clang_x64") { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - cc = "$prefix/clang" - cxx = "$prefix/clang++" - - readelf = "readelf" - nm = "nm" - ar = "ar" - ld = cxx - +clang_toolchain("clang_x64") { toolchain_cpu = "x64" toolchain_os = "linux" - is_clang = true } gcc_toolchain("x64") {
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc index 902a73d..d7c6cda 100644 --- a/cc/layers/io_surface_layer_impl.cc +++ b/cc/layers/io_surface_layer_impl.cc
@@ -79,14 +79,9 @@ IOSurfaceDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>(); - quad->SetNew(shared_quad_state, - quad_rect, - opaque_rect, - visible_quad_rect, - io_surface_size_, - io_surface_resource_id_, - IOSurfaceDrawQuad::FLIPPED, - false); + quad->SetNew(shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, + io_surface_size_, io_surface_resource_id_, + IOSurfaceDrawQuad::FLIPPED); ValidateQuadResources(quad); }
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 404d479..e8642194 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -177,7 +177,6 @@ nearest_neighbor_); if (!valid_texture_copy_) { quad->set_resource_size_in_pixels(texture_mailbox_.size_in_pixels()); - quad->set_allow_overlay(texture_mailbox_.allow_overlay()); } ValidateQuadResources(quad); }
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 3313aa5..d6aa570 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -128,7 +128,7 @@ external_resources.read_lock_fences_enabled); frame_resources_.push_back(FrameResource( resource_id, external_resources.mailboxes[i].size_in_pixels(), - external_resources.mailboxes[i].allow_overlay())); + external_resources.mailboxes[i].is_overlay_candidate())); } return true; @@ -313,7 +313,6 @@ stream_video_quad->SetNew( shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, frame_resources_[0].id, frame_resources_[0].size_in_pixels, - frame_resources_[0].allow_overlay, scale * provider_client_impl_->StreamTextureMatrix()); ValidateQuadResources(stream_video_quad); break; @@ -327,8 +326,7 @@ io_surface_quad->SetNew(shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, visible_rect.size(), frame_resources_[0].id, - IOSurfaceDrawQuad::UNFLIPPED, - frame_resources_[0].allow_overlay); + IOSurfaceDrawQuad::UNFLIPPED); ValidateQuadResources(io_surface_quad); break; }
diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h index 6fab7f5..127700b 100644 --- a/cc/layers/video_layer_impl.h +++ b/cc/layers/video_layer_impl.h
@@ -63,13 +63,15 @@ scoped_ptr<VideoResourceUpdater> updater_; VideoFrameExternalResources::ResourceType frame_resource_type_; struct FrameResource { - FrameResource(ResourceId id, gfx::Size size_in_pixels, bool allow_overlay) + FrameResource(ResourceId id, + gfx::Size size_in_pixels, + bool is_overlay_candidate) : id(id), size_in_pixels(size_in_pixels), - allow_overlay(allow_overlay) {} + is_overlay_candidate(is_overlay_candidate) {} ResourceId id; gfx::Size size_in_pixels; - bool allow_overlay; + bool is_overlay_candidate; }; std::vector<FrameResource> frame_resources_;
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index f9815183..1be41e92 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc
@@ -239,8 +239,8 @@ // If we have any copy requests, we can't remove any quads for overlays, // otherwise the framebuffer will be missing the overlay contents. if (root_render_pass->copy_requests.empty()) { - overlay_processor_->ProcessForOverlays(render_passes_in_draw_order, - &frame.overlay_list); + overlay_processor_->ProcessForOverlays( + resource_provider_, render_passes_in_draw_order, &frame.overlay_list); } for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) {
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index c2fae69..7e35ad4 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc
@@ -2007,8 +2007,9 @@ public: Strategy() {} ~Strategy() override {} - MOCK_METHOD2(Attempt, - bool(RenderPassList* render_passes, + MOCK_METHOD3(Attempt, + bool(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidates)); }; @@ -2065,7 +2066,8 @@ unsigned sync_point = 0; TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); + TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, + gfx::Size(256, 256), true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( @@ -2082,14 +2084,13 @@ premultiplied_alpha, gfx::PointF(0, 0), gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor); - overlay_quad->set_allow_overlay(true); // DirectRenderer::DrawFrame calls into OverlayProcessor::ProcessForOverlays. // Attempt will be called for each strategy in OverlayProcessor. We have // added a fake strategy, so checking for Attempt calls checks if there was // any attempt to overlay, which there shouldn't be. We can't use the quad // list because the render pass is cleaned up by DrawFrame. - EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(0); + EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(0); renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect, viewport_rect, false); Mock::VerifyAndClearExpectations(processor->strategy_); @@ -2106,7 +2107,7 @@ gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor); - EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(1); + EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(1); renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect, viewport_rect, false); } @@ -2195,7 +2196,8 @@ unsigned sync_point = 29; TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); + TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, + gfx::Size(256, 256), true); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( @@ -2216,7 +2218,6 @@ viewport_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, flipped, nearest_neighbor); - overlay_quad->set_allow_overlay(true); // Verify that overlay_quad actually gets turned into an overlay, and even // though it's not drawn, that its sync point is waited on.
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc index 4e6a36b..658f153 100644 --- a/cc/output/overlay_candidate.cc +++ b/cc/output/overlay_candidate.cc
@@ -12,6 +12,8 @@ #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/stream_video_draw_quad.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/quads/tile_draw_quad.h" +#include "cc/resources/resource_provider.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/vector3d_f.h" @@ -178,7 +180,8 @@ OverlayCandidate::~OverlayCandidate() {} // static -bool OverlayCandidate::FromDrawQuad(const DrawQuad* quad, +bool OverlayCandidate::FromDrawQuad(ResourceProvider* resource_provider, + const DrawQuad* quad, OverlayCandidate* candidate) { if (quad->needs_blending || quad->shared_quad_state->opacity != 1.f || quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) @@ -196,13 +199,15 @@ switch (quad->material) { case DrawQuad::TEXTURE_CONTENT: - return FromTextureQuad(TextureDrawQuad::MaterialCast(quad), candidate); + return FromTextureQuad(resource_provider, + TextureDrawQuad::MaterialCast(quad), candidate); case DrawQuad::STREAM_VIDEO_CONTENT: - return FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad), + return FromStreamVideoQuad(resource_provider, + StreamVideoDrawQuad::MaterialCast(quad), candidate); case DrawQuad::IO_SURFACE_CONTENT: - return FromIOSurfaceQuad(IOSurfaceDrawQuad::MaterialCast(quad), - candidate); + return FromIOSurfaceQuad( + resource_provider, IOSurfaceDrawQuad::MaterialCast(quad), candidate); default: break; } @@ -223,9 +228,10 @@ } // static -bool OverlayCandidate::FromTextureQuad(const TextureDrawQuad* quad, +bool OverlayCandidate::FromTextureQuad(ResourceProvider* resource_provider, + const TextureDrawQuad* quad, OverlayCandidate* candidate) { - if (!quad->allow_overlay()) + if (!resource_provider->IsOverlayCandidate(quad->resource_id())) return false; gfx::OverlayTransform overlay_transform = GetOverlayTransform( quad->shared_quad_state->quad_to_target_transform, quad->y_flipped); @@ -241,9 +247,10 @@ } // static -bool OverlayCandidate::FromStreamVideoQuad(const StreamVideoDrawQuad* quad, +bool OverlayCandidate::FromStreamVideoQuad(ResourceProvider* resource_provider, + const StreamVideoDrawQuad* quad, OverlayCandidate* candidate) { - if (!quad->allow_overlay()) + if (!resource_provider->IsOverlayCandidate(quad->resource_id())) return false; gfx::OverlayTransform overlay_transform = GetOverlayTransform( quad->shared_quad_state->quad_to_target_transform, false); @@ -286,9 +293,10 @@ } // static -bool OverlayCandidate::FromIOSurfaceQuad(const IOSurfaceDrawQuad* quad, +bool OverlayCandidate::FromIOSurfaceQuad(ResourceProvider* resource_provider, + const IOSurfaceDrawQuad* quad, OverlayCandidate* candidate) { - if (!quad->allow_overlay) + if (!resource_provider->IsOverlayCandidate(quad->io_surface_resource_id())) return false; gfx::OverlayTransform overlay_transform = GetOverlayTransform( quad->shared_quad_state->quad_to_target_transform, false);
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h index 2584d9b0..aa42ba11 100644 --- a/cc/output/overlay_candidate.h +++ b/cc/output/overlay_candidate.h
@@ -25,12 +25,15 @@ class IOSurfaceDrawQuad; class StreamVideoDrawQuad; class TextureDrawQuad; +class ResourceProvider; class CC_EXPORT OverlayCandidate { public: // Returns true and fills in |candidate| if |draw_quad| is of a known quad // type and contains an overlayable resource. - static bool FromDrawQuad(const DrawQuad* quad, OverlayCandidate* candidate); + static bool FromDrawQuad(ResourceProvider* resource_provider, + const DrawQuad* quad, + OverlayCandidate* candidate); // Returns true if |quad| will not block quads underneath from becoming // an overlay. static bool IsInvisibleQuad(const DrawQuad* quad); @@ -69,11 +72,14 @@ bool overlay_handled; private: - static bool FromTextureQuad(const TextureDrawQuad* quad, + static bool FromTextureQuad(ResourceProvider* resource_provider, + const TextureDrawQuad* quad, OverlayCandidate* candidate); - static bool FromStreamVideoQuad(const StreamVideoDrawQuad* quad, + static bool FromStreamVideoQuad(ResourceProvider* resource_provider, + const StreamVideoDrawQuad* quad, OverlayCandidate* candidate); - static bool FromIOSurfaceQuad(const IOSurfaceDrawQuad* quad, + static bool FromIOSurfaceQuad(ResourceProvider* resource_provider, + const IOSurfaceDrawQuad* quad, OverlayCandidate* candidate); };
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc index 789fc13..69368a1 100644 --- a/cc/output/overlay_processor.cc +++ b/cc/output/overlay_processor.cc
@@ -25,10 +25,11 @@ OverlayProcessor::~OverlayProcessor() {} -void OverlayProcessor::ProcessForOverlays(RenderPassList* render_passes, +void OverlayProcessor::ProcessForOverlays(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidates) { for (auto strategy : strategies_) { - if (strategy->Attempt(render_passes, candidates)) + if (strategy->Attempt(resource_provider, render_passes, candidates)) return; } }
diff --git a/cc/output/overlay_processor.h b/cc/output/overlay_processor.h index d4e1369..48ffe6b 100644 --- a/cc/output/overlay_processor.h +++ b/cc/output/overlay_processor.h
@@ -24,7 +24,8 @@ // current set of render passes. Returns true if the strategy was successful // and adds any additional passes necessary to represent overlays to // |render_passes|. - virtual bool Attempt(RenderPassList* render_passes, + virtual bool Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidates) = 0; }; typedef ScopedPtrVector<Strategy> StrategyList; @@ -34,7 +35,8 @@ // Virtual to allow testing different strategies. virtual void Initialize(); - void ProcessForOverlays(RenderPassList* render_passes, + void ProcessForOverlays(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidates); protected:
diff --git a/cc/output/overlay_strategy_all_or_nothing.cc b/cc/output/overlay_strategy_all_or_nothing.cc index 3550d4f5..40c58cd0 100644 --- a/cc/output/overlay_strategy_all_or_nothing.cc +++ b/cc/output/overlay_strategy_all_or_nothing.cc
@@ -17,7 +17,8 @@ OverlayStrategyAllOrNothing::~OverlayStrategyAllOrNothing() {} -bool OverlayStrategyAllOrNothing::Attempt(RenderPassList* render_passes, +bool OverlayStrategyAllOrNothing::Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidates) { QuadList& quad_list = render_passes->back()->quad_list; OverlayCandidateList new_candidates; @@ -25,7 +26,7 @@ for (const DrawQuad* quad : quad_list) { OverlayCandidate candidate; - if (!OverlayCandidate::FromDrawQuad(quad, &candidate)) + if (!OverlayCandidate::FromDrawQuad(resource_provider, quad, &candidate)) return false; candidate.plane_z_order = next_z_order--; new_candidates.push_back(candidate);
diff --git a/cc/output/overlay_strategy_all_or_nothing.h b/cc/output/overlay_strategy_all_or_nothing.h index 3262fce..94d88f03 100644 --- a/cc/output/overlay_strategy_all_or_nothing.h +++ b/cc/output/overlay_strategy_all_or_nothing.h
@@ -20,7 +20,8 @@ OverlayCandidateValidator* capability_checker); ~OverlayStrategyAllOrNothing() override; - bool Attempt(RenderPassList* render_passes, + bool Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) override; private:
diff --git a/cc/output/overlay_strategy_sandwich.cc b/cc/output/overlay_strategy_sandwich.cc index 515afa5..79279adb 100644 --- a/cc/output/overlay_strategy_sandwich.cc +++ b/cc/output/overlay_strategy_sandwich.cc
@@ -40,12 +40,13 @@ OverlayStrategySandwich::~OverlayStrategySandwich() {} -bool OverlayStrategySandwich::Attempt(RenderPassList* render_passes, +bool OverlayStrategySandwich::Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) { QuadList& quad_list = render_passes->back()->quad_list; for (auto it = quad_list.begin(); it != quad_list.end();) { OverlayCandidate candidate; - if (OverlayCandidate::FromDrawQuad(*it, &candidate)) + if (OverlayCandidate::FromDrawQuad(resource_provider, *it, &candidate)) it = TryOverlay(render_passes->back(), candidate_list, candidate, it); else ++it;
diff --git a/cc/output/overlay_strategy_sandwich.h b/cc/output/overlay_strategy_sandwich.h index afab8e6..076ea9de 100644 --- a/cc/output/overlay_strategy_sandwich.h +++ b/cc/output/overlay_strategy_sandwich.h
@@ -21,7 +21,8 @@ OverlayCandidateValidator* capability_checker); ~OverlayStrategySandwich() override; - bool Attempt(RenderPassList* render_passes, + bool Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) override; private:
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc index d08da5cd..ca254b2 100644 --- a/cc/output/overlay_strategy_single_on_top.cc +++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -18,12 +18,13 @@ OverlayStrategySingleOnTop::~OverlayStrategySingleOnTop() {} -bool OverlayStrategySingleOnTop::Attempt(RenderPassList* render_passes, +bool OverlayStrategySingleOnTop::Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) { - QuadList& quad_list = render_passes->back()->quad_list; - for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { + QuadList* quad_list = &render_passes->back()->quad_list; + for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { OverlayCandidate candidate; - if (OverlayCandidate::FromDrawQuad(*it, &candidate) && + if (OverlayCandidate::FromDrawQuad(resource_provider, *it, &candidate) && TryOverlay(quad_list, candidate_list, candidate, it)) { return true; } @@ -33,12 +34,12 @@ } bool OverlayStrategySingleOnTop::TryOverlay( - QuadList& quad_list, + QuadList* quad_list, OverlayCandidateList* candidate_list, const OverlayCandidate& candidate, QuadList::Iterator candidate_iterator) { // Check that no prior quads overlap it. - for (auto overlap_iter = quad_list.cbegin(); + for (auto overlap_iter = quad_list->cbegin(); overlap_iter != candidate_iterator; ++overlap_iter) { gfx::RectF overlap_rect = MathUtil::MapClippedRect( overlap_iter->shared_quad_state->quad_to_target_transform, @@ -58,7 +59,7 @@ // If the candidate can be handled by an overlay, create a pass for it. if (new_candidate_list.back().overlay_handled) { - quad_list.EraseAndInvalidateAllPointers(candidate_iterator); + quad_list->EraseAndInvalidateAllPointers(candidate_iterator); candidate_list->swap(new_candidate_list); return true; }
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h index e2991e48..bdf2cc2f 100644 --- a/cc/output/overlay_strategy_single_on_top.h +++ b/cc/output/overlay_strategy_single_on_top.h
@@ -17,11 +17,12 @@ OverlayCandidateValidator* capability_checker); ~OverlayStrategySingleOnTop() override; - bool Attempt(RenderPassList* render_passes, + bool Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) override; private: - bool TryOverlay(QuadList& quad_list, + bool TryOverlay(QuadList* quad_list, OverlayCandidateList* candidate_list, const OverlayCandidate& candidate, QuadList::Iterator candidate_iterator);
diff --git a/cc/output/overlay_strategy_underlay.cc b/cc/output/overlay_strategy_underlay.cc index 805855c..9a8a3628 100644 --- a/cc/output/overlay_strategy_underlay.cc +++ b/cc/output/overlay_strategy_underlay.cc
@@ -18,12 +18,13 @@ OverlayStrategyUnderlay::~OverlayStrategyUnderlay() {} -bool OverlayStrategyUnderlay::Attempt(RenderPassList* render_passes, +bool OverlayStrategyUnderlay::Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) { QuadList& quad_list = render_passes->back()->quad_list; for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { OverlayCandidate candidate; - if (!OverlayCandidate::FromDrawQuad(*it, &candidate)) + if (!OverlayCandidate::FromDrawQuad(resource_provider, *it, &candidate)) continue; // Add the overlay.
diff --git a/cc/output/overlay_strategy_underlay.h b/cc/output/overlay_strategy_underlay.h index 473e696..f276c1c 100644 --- a/cc/output/overlay_strategy_underlay.h +++ b/cc/output/overlay_strategy_underlay.h
@@ -22,7 +22,8 @@ OverlayCandidateValidator* capability_checker); ~OverlayStrategyUnderlay() override; - bool Attempt(RenderPassList* render_passes, + bool Attempt(ResourceProvider* resource_provider, + RenderPassList* render_passes, OverlayCandidateList* candidate_list) override; private:
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 4f66a93..722002e 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc
@@ -203,10 +203,13 @@ return pass.Pass(); } -ResourceId CreateResource(ResourceProvider* resource_provider) { +ResourceId CreateResource(ResourceProvider* resource_provider, + const gfx::Size& size, + bool is_overlay_candidate) { unsigned sync_point = 0; TextureMailbox mailbox = - TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); + TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point, size, + is_overlay_candidate); scoped_ptr<SingleReleaseCallbackImpl> release_callback = SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); @@ -229,13 +232,14 @@ const SharedQuadState* shared_quad_state, RenderPass* render_pass, const gfx::Rect& rect) { - ResourceId resource_id = CreateResource(resource_provider); bool premultiplied_alpha = false; bool flipped = false; bool nearest_neighbor = false; float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; gfx::Size resource_size_in_pixels = gfx::Size(64, 64); - bool allow_overlay = true; + bool is_overlay_candidate = true; + ResourceId resource_id = CreateResource( + resource_provider, resource_size_in_pixels, is_overlay_candidate); TextureDrawQuad* overlay_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); @@ -251,7 +255,6 @@ vertex_opacity, flipped, nearest_neighbor); - overlay_quad->set_allow_overlay(allow_overlay); overlay_quad->set_resource_size_in_pixels(resource_size_in_pixels); return overlay_quad; @@ -263,14 +266,15 @@ RenderPass* render_pass, const gfx::Rect& rect, const gfx::Transform& transform) { - ResourceId resource_id = CreateResource(resource_provider); gfx::Size resource_size_in_pixels = gfx::Size(64, 64); - bool allow_overlay = true; + bool is_overlay_candidate = true; + ResourceId resource_id = CreateResource( + resource_provider, resource_size_in_pixels, is_overlay_candidate); StreamVideoDrawQuad* overlay_quad = render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); overlay_quad->SetNew(shared_quad_state, rect, rect, rect, resource_id, - resource_size_in_pixels, allow_overlay, transform); + resource_size_in_pixels, transform); return overlay_quad; } @@ -414,7 +418,8 @@ // Check for potential candidates. OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); @@ -455,7 +460,8 @@ // Check for potential candidates. OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); // Ensure that the display and uv rects have cropping applied to them. ASSERT_EQ(1U, pass_list.size()); @@ -483,7 +489,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); // Both candidates should become overlays. EXPECT_EQ(1u, pass_list.size()); @@ -516,7 +523,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); // Only one of the candidates should become an overlay. EXPECT_EQ(1u, pass_list.size()); @@ -550,7 +558,8 @@ // Check for potential candidates. OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(2U, candidate_list.size()); @@ -605,7 +614,8 @@ RenderPass* main_pass = pass_list.back(); OverlayCandidateList candidate_list; EXPECT_EQ(4U, main_pass->quad_list.size()); - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(3U, candidate_list.size()); @@ -656,7 +666,8 @@ // Check for potential candidates. OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); @@ -689,7 +700,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(0U, candidate_list.size()); // There should be nothing new here. CompareRenderPassLists(pass_list, original_pass_list); @@ -713,7 +725,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(0U, candidate_list.size()); // There should be nothing new here. CompareRenderPassLists(pass_list, original_pass_list); @@ -742,7 +755,8 @@ // Check for potential candidates. OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, candidate_list.size()); // This should be the same. @@ -760,7 +774,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -776,7 +791,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -792,7 +808,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -807,7 +824,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -822,7 +840,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -838,7 +857,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -854,7 +874,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -872,7 +893,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, @@ -892,7 +914,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, @@ -911,7 +934,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -928,7 +952,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform); @@ -946,7 +971,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform); @@ -964,7 +990,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform); @@ -987,7 +1014,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1010,7 +1038,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1031,7 +1060,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1054,7 +1084,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -1075,7 +1106,8 @@ RenderPass::CopyAll(pass_list, &original_pass_list); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -1089,7 +1121,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(0U, candidate_list.size()); } @@ -1103,7 +1136,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1117,7 +1151,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1131,7 +1166,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1145,7 +1181,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); ASSERT_EQ(1U, pass_list.size()); EXPECT_EQ(1U, candidate_list.size()); } @@ -1162,7 +1199,8 @@ pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(-1, candidate_list[0].plane_z_order); @@ -1184,7 +1222,8 @@ pass_list.push_back(pass.Pass()); OverlayCandidateList candidate_list; - overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidate_list); EXPECT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, candidate_list.size()); EXPECT_EQ(-1, candidate_list[0].plane_z_order); @@ -1206,7 +1245,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidates; - overlay_processor_->ProcessForOverlays(&pass_list, &candidates); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidates); // Both quads should become overlays. EXPECT_EQ(2u, candidates.size()); @@ -1236,7 +1276,8 @@ RenderPassList pass_list; pass_list.push_back(pass.Pass()); OverlayCandidateList candidates; - overlay_processor_->ProcessForOverlays(&pass_list, &candidates); + overlay_processor_->ProcessForOverlays(resource_provider_.get(), &pass_list, + &candidates); // No quads should become overlays. EXPECT_EQ(0u, candidates.size()); @@ -1449,9 +1490,12 @@ Init(use_validator); renderer_->set_expect_overlays(true); - ResourceId resource1 = CreateResource(resource_provider_.get()); - ResourceId resource2 = CreateResource(resource_provider_.get()); - ResourceId resource3 = CreateResource(resource_provider_.get()); + ResourceId resource1 = + CreateResource(resource_provider_.get(), gfx::Size(32, 32), true); + ResourceId resource2 = + CreateResource(resource_provider_.get(), gfx::Size(32, 32), true); + ResourceId resource3 = + CreateResource(resource_provider_.get(), gfx::Size(32, 32), true); scoped_ptr<RenderPass> pass = CreateRenderPass(); RenderPassList pass_list;
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc index a1d1a904..2fd7a80c 100644 --- a/cc/quads/draw_quad_unittest.cc +++ b/cc/quads/draw_quad_unittest.cc
@@ -384,34 +384,22 @@ gfx::Size size(58, 95); ResourceId resource_id = 72; IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED; - bool allow_overlay = true; CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(IOSurfaceDrawQuad, - opaque_rect, - visible_rect, - size, - resource_id, - orientation, - allow_overlay); + CREATE_QUAD_5_NEW(IOSurfaceDrawQuad, opaque_rect, visible_rect, size, + resource_id, orientation); EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(size, copy_quad->io_surface_size); EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id()); EXPECT_EQ(orientation, copy_quad->orientation); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay); - CREATE_QUAD_4_ALL(IOSurfaceDrawQuad, - size, - resource_id, - orientation, - allow_overlay); + CREATE_QUAD_3_ALL(IOSurfaceDrawQuad, size, resource_id, orientation); EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material); EXPECT_EQ(size, copy_quad->io_surface_size); EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id()); EXPECT_EQ(orientation, copy_quad->orientation); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay); } TEST(DrawQuadTest, CopyRenderPassDrawQuad) { @@ -495,25 +483,22 @@ gfx::Rect visible_rect(40, 50, 30, 20); ResourceId resource_id = 64; gfx::Size resource_size_in_pixels = gfx::Size(40, 41); - bool allow_overlay = true; gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1); CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, - resource_size_in_pixels, allow_overlay, matrix); + CREATE_QUAD_5_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, + resource_size_in_pixels, matrix); EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(resource_id, copy_quad->resource_id()); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(matrix, copy_quad->matrix); - CREATE_QUAD_4_ALL(StreamVideoDrawQuad, resource_id, resource_size_in_pixels, - allow_overlay, matrix); + CREATE_QUAD_3_ALL(StreamVideoDrawQuad, resource_id, resource_size_in_pixels, + matrix); EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material); EXPECT_EQ(resource_id, copy_quad->resource_id()); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(matrix, copy_quad->matrix); } @@ -539,7 +524,6 @@ gfx::Rect visible_rect(40, 50, 30, 20); unsigned resource_id = 82; gfx::Size resource_size_in_pixels = gfx::Size(40, 41); - bool allow_overlay = true; bool premultiplied_alpha = true; gfx::PointF uv_top_left(0.5f, 224.f); gfx::PointF uv_bottom_right(51.5f, 260.f); @@ -570,13 +554,12 @@ EXPECT_EQ(y_flipped, copy_quad->y_flipped); EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); - CREATE_QUAD_10_ALL(TextureDrawQuad, resource_id, resource_size_in_pixels, - allow_overlay, premultiplied_alpha, uv_top_left, - uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity, - y_flipped, nearest_neighbor); + CREATE_QUAD_9_ALL(TextureDrawQuad, resource_id, resource_size_in_pixels, + premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, y_flipped, + nearest_neighbor); EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, copy_quad->material); EXPECT_EQ(resource_id, copy_quad->resource_id()); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay()); EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels()); EXPECT_EQ(premultiplied_alpha, copy_quad->premultiplied_alpha); EXPECT_EQ(uv_top_left, copy_quad->uv_top_left); @@ -745,20 +728,13 @@ gfx::Size size(58, 95); ResourceId resource_id = 72; IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED; - bool allow_overlay = true; CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(IOSurfaceDrawQuad, - opaque_rect, - visible_rect, - size, - resource_id, - orientation, - allow_overlay); + CREATE_QUAD_5_NEW(IOSurfaceDrawQuad, opaque_rect, visible_rect, size, + resource_id, orientation); EXPECT_EQ(resource_id, quad_new->io_surface_resource_id()); EXPECT_EQ(1, IterateAndCount(quad_new)); EXPECT_EQ(resource_id + 1, quad_new->io_surface_resource_id()); - EXPECT_EQ(allow_overlay, copy_quad->allow_overlay); } TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) { @@ -816,14 +792,12 @@ gfx::Rect visible_rect(40, 50, 30, 20); ResourceId resource_id = 64; gfx::Size resource_size_in_pixels = gfx::Size(40, 41); - bool allow_overlay = true; gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1); CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, - resource_size_in_pixels, allow_overlay, matrix); + CREATE_QUAD_5_NEW(StreamVideoDrawQuad, opaque_rect, visible_rect, resource_id, + resource_size_in_pixels, matrix); EXPECT_EQ(resource_id, quad_new->resource_id()); - EXPECT_EQ(allow_overlay, quad_new->allow_overlay()); EXPECT_EQ(resource_size_in_pixels, quad_new->resource_size_in_pixels()); EXPECT_EQ(1, IterateAndCount(quad_new)); EXPECT_EQ(resource_id + 1, quad_new->resource_id());
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc index 32e2ffc4..1ed0021d 100644 --- a/cc/quads/io_surface_draw_quad.cc +++ b/cc/quads/io_surface_draw_quad.cc
@@ -11,9 +11,7 @@ namespace cc { -IOSurfaceDrawQuad::IOSurfaceDrawQuad() - : orientation(FLIPPED), allow_overlay(false) { -} +IOSurfaceDrawQuad::IOSurfaceDrawQuad() : orientation(FLIPPED) {} void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, @@ -21,8 +19,7 @@ const gfx::Rect& visible_rect, const gfx::Size& io_surface_size, unsigned io_surface_resource_id, - Orientation orientation, - bool allow_overlay) { + Orientation orientation) { bool needs_blending = false; DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); @@ -30,7 +27,6 @@ resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id; resources.count = 1; this->orientation = orientation; - this->allow_overlay = allow_overlay; } void IOSurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state, @@ -40,15 +36,13 @@ bool needs_blending, const gfx::Size& io_surface_size, unsigned io_surface_resource_id, - Orientation orientation, - bool allow_overlay) { + Orientation orientation) { DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); this->io_surface_size = io_surface_size; resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id; resources.count = 1; this->orientation = orientation; - this->allow_overlay = allow_overlay; } const IOSurfaceDrawQuad* IOSurfaceDrawQuad::MaterialCast(
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h index 0374aa9..4a8a072c 100644 --- a/cc/quads/io_surface_draw_quad.h +++ b/cc/quads/io_surface_draw_quad.h
@@ -28,8 +28,7 @@ const gfx::Rect& visible_rect, const gfx::Size& io_surface_size, unsigned io_surface_resource_id, - Orientation orientation, - bool allow_overlay); + Orientation orientation); void SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, @@ -38,12 +37,10 @@ bool needs_blending, const gfx::Size& io_surface_size, unsigned io_surface_resource_id, - Orientation orientation, - bool allow_overlay); + Orientation orientation); gfx::Size io_surface_size; Orientation orientation; - bool allow_overlay; ResourceId io_surface_resource_id() const { return resources.ids[kIOSurfaceResourceIdIndex];
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc index c25e5d5..7760168a 100644 --- a/cc/quads/stream_video_draw_quad.cc +++ b/cc/quads/stream_video_draw_quad.cc
@@ -20,14 +20,12 @@ const gfx::Rect& visible_rect, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, const gfx::Transform& matrix) { bool needs_blending = false; DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect, opaque_rect, visible_rect, needs_blending); resources.ids[kResourceIdIndex] = resource_id; overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; - overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; resources.count = 1; this->matrix = matrix; } @@ -39,13 +37,11 @@ bool needs_blending, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, const gfx::Transform& matrix) { DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect, opaque_rect, visible_rect, needs_blending); resources.ids[kResourceIdIndex] = resource_id; overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; - overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; resources.count = 1; this->matrix = matrix; } @@ -63,8 +59,6 @@ } StreamVideoDrawQuad::OverlayResources::OverlayResources() { - for (size_t i = 0; i < Resources::kMaxResourceIdCount; ++i) - allow_overlay[i] = false; } } // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h index 519c353..1044fdc1 100644 --- a/cc/quads/stream_video_draw_quad.h +++ b/cc/quads/stream_video_draw_quad.h
@@ -22,7 +22,6 @@ const gfx::Rect& visible_rect, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, const gfx::Transform& matrix); void SetAll(const SharedQuadState* shared_quad_state, @@ -32,16 +31,13 @@ bool needs_blending, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, const gfx::Transform& matrix); gfx::Transform matrix; struct OverlayResources { OverlayResources(); - gfx::Size size_in_pixels[Resources::kMaxResourceIdCount]; - bool allow_overlay[Resources::kMaxResourceIdCount]; }; OverlayResources overlay_resources; @@ -51,9 +47,6 @@ const gfx::Size& resource_size_in_pixels() const { return overlay_resources.size_in_pixels[kResourceIdIndex]; } - bool allow_overlay() const { - return overlay_resources.allow_overlay[kResourceIdIndex]; - } private: static const size_t kResourceIdIndex = 0;
diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc index c469c875..370277b 100644 --- a/cc/quads/texture_draw_quad.cc +++ b/cc/quads/texture_draw_quad.cc
@@ -60,7 +60,6 @@ bool needs_blending, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, bool premultiplied_alpha, const gfx::PointF& uv_top_left, const gfx::PointF& uv_bottom_right, @@ -72,7 +71,6 @@ opaque_rect, visible_rect, needs_blending); resources.ids[kResourceIdIndex] = resource_id; overlay_resources.size_in_pixels[kResourceIdIndex] = resource_size_in_pixels; - overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; resources.count = 1; this->premultiplied_alpha = premultiplied_alpha; this->uv_top_left = uv_top_left; @@ -110,8 +108,6 @@ } TextureDrawQuad::OverlayResources::OverlayResources() { - for (size_t i = 0; i < Resources::kMaxResourceIdCount; ++i) - allow_overlay[i] = false; } } // namespace cc
diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h index 40c7623c..9b9fab9 100644 --- a/cc/quads/texture_draw_quad.h +++ b/cc/quads/texture_draw_quad.h
@@ -36,7 +36,6 @@ bool needs_blending, unsigned resource_id, gfx::Size resource_size_in_pixels, - bool allow_overlay, bool premultiplied_alpha, const gfx::PointF& uv_top_left, const gfx::PointF& uv_bottom_right, @@ -57,7 +56,6 @@ OverlayResources(); gfx::Size size_in_pixels[Resources::kMaxResourceIdCount]; - bool allow_overlay[Resources::kMaxResourceIdCount]; }; OverlayResources overlay_resources; @@ -68,12 +66,6 @@ void set_resource_size_in_pixels(const gfx::Size& size_in_pixels) { overlay_resources.size_in_pixels[kResourceIdIndex] = size_in_pixels; } - bool allow_overlay() const { - return overlay_resources.allow_overlay[kResourceIdIndex]; - } - void set_allow_overlay(bool allow_overlay) { - overlay_resources.allow_overlay[kResourceIdIndex] = allow_overlay; - } static const TextureDrawQuad* MaterialCast(const DrawQuad*);
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 083b486..c9d0389 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -221,6 +221,7 @@ allocated(false), read_lock_fences_enabled(false), has_shared_bitmap_id(false), + is_overlay_candidate(false), read_lock_fence(NULL), size(size), origin(origin), @@ -521,6 +522,7 @@ base::Bind(&SingleReleaseCallbackImpl::Run, base::Owned(release_callback_impl.release())); resource->read_lock_fences_enabled = read_lock_fences_enabled; + resource->is_overlay_candidate = mailbox.is_overlay_candidate(); return id; } @@ -779,6 +781,11 @@ !resource->lost && ReadLockFenceHasPassed(resource); } +bool ResourceProvider::IsOverlayCandidate(ResourceId id) { + Resource* resource = GetResource(id); + return resource->is_overlay_candidate; +} + void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) { DCHECK(resource->locked_for_write); DCHECK_EQ(resource->exported_count, 0); @@ -1220,6 +1227,7 @@ it->mailbox_holder.texture_target, it->mailbox_holder.sync_point); resource->read_lock_fences_enabled = it->read_lock_fences_enabled; + resource->is_overlay_candidate = it->is_overlay_candidate; } resource->child_id = child; // Don't allocate a texture for a child. @@ -1321,6 +1329,7 @@ resource->size = source->size; resource->read_lock_fences_enabled = source->read_lock_fences_enabled; resource->is_repeated = (source->wrap_mode == GL_REPEAT); + resource->is_overlay_candidate = source->is_overlay_candidate; if (source->type == RESOURCE_TYPE_BITMAP) { resource->mailbox_holder.mailbox = source->shared_bitmap_id;
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 4af135e..ca97bc4 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -422,6 +422,9 @@ // Indicates if we can currently lock this resource for write. bool CanLockForWrite(ResourceId id); + // Indicates if this resource may be used for a hardware overlay plane. + bool IsOverlayCandidate(ResourceId id); + void WaitSyncPointIfNeeded(ResourceId id); static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl); @@ -495,6 +498,7 @@ bool allocated : 1; bool read_lock_fences_enabled : 1; bool has_shared_bitmap_id : 1; + bool is_overlay_candidate : 1; scoped_refptr<Fence> read_lock_fence; gfx::Size size; Origin origin;
diff --git a/cc/resources/texture_mailbox.cc b/cc/resources/texture_mailbox.cc index 7e4dd297..ff4c6f9 100644 --- a/cc/resources/texture_mailbox.cc +++ b/cc/resources/texture_mailbox.cc
@@ -15,37 +15,35 @@ TextureMailbox::TextureMailbox(const gpu::MailboxHolder& mailbox_holder) : mailbox_holder_(mailbox_holder), shared_bitmap_(NULL), - allow_overlay_(false), - nearest_neighbor_(false) { -} + is_overlay_candidate_(false), + nearest_neighbor_(false) {} TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point) : mailbox_holder_(mailbox, target, sync_point), shared_bitmap_(NULL), - allow_overlay_(false), - nearest_neighbor_(false) { -} + is_overlay_candidate_(false), + nearest_neighbor_(false) {} TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point, const gfx::Size& size_in_pixels, - bool allow_overlay) + bool is_overlay_candidate) : mailbox_holder_(mailbox, target, sync_point), shared_bitmap_(nullptr), size_in_pixels_(size_in_pixels), - allow_overlay_(allow_overlay), + is_overlay_candidate_(is_overlay_candidate), nearest_neighbor_(false) { - DCHECK_IMPLIES(allow_overlay, !size_in_pixels.IsEmpty()); + DCHECK_IMPLIES(is_overlay_candidate, !size_in_pixels.IsEmpty()); } TextureMailbox::TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size_in_pixels) : shared_bitmap_(shared_bitmap), size_in_pixels_(size_in_pixels), - allow_overlay_(false), + is_overlay_candidate_(false), nearest_neighbor_(false) { // If an embedder of cc gives an invalid TextureMailbox, we should crash // here to identify the offender.
diff --git a/cc/resources/texture_mailbox.h b/cc/resources/texture_mailbox.h index 47e71acb..9fc0fb8 100644 --- a/cc/resources/texture_mailbox.h +++ b/cc/resources/texture_mailbox.h
@@ -26,7 +26,7 @@ uint32 target, uint32 sync_point, const gfx::Size& size_in_pixels, - bool allow_overlay); + bool is_overlay_candidate); TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size_in_pixels); ~TextureMailbox(); @@ -45,7 +45,7 @@ mailbox_holder_.sync_point = sync_point; } - bool allow_overlay() const { return allow_overlay_; } + bool is_overlay_candidate() const { return is_overlay_candidate_; } bool nearest_neighbor() const { return nearest_neighbor_; } void set_nearest_neighbor(bool nearest_neighbor) { nearest_neighbor_ = nearest_neighbor; @@ -61,7 +61,7 @@ gpu::MailboxHolder mailbox_holder_; SharedBitmap* shared_bitmap_; gfx::Size size_in_pixels_; - bool allow_overlay_; + bool is_overlay_candidate_; bool nearest_neighbor_; };
diff --git a/cc/resources/transferable_resource.cc b/cc/resources/transferable_resource.cc index 89771a78..7832cfe 100644 --- a/cc/resources/transferable_resource.cc +++ b/cc/resources/transferable_resource.cc
@@ -14,8 +14,7 @@ read_lock_fences_enabled(false), is_repeated(false), is_software(false), - allow_overlay(false) { -} + is_overlay_candidate(false) {} TransferableResource::~TransferableResource() { }
diff --git a/cc/resources/transferable_resource.h b/cc/resources/transferable_resource.h index 6f38a62..750a172 100644 --- a/cc/resources/transferable_resource.h +++ b/cc/resources/transferable_resource.h
@@ -37,7 +37,7 @@ bool read_lock_fences_enabled; bool is_repeated; bool is_software; - bool allow_overlay; + bool is_overlay_candidate; }; } // namespace cc
diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc index 71589ed..2960c44 100644 --- a/cc/surfaces/surface_aggregator_perftest.cc +++ b/cc/surfaces/surface_aggregator_perftest.cc
@@ -74,7 +74,7 @@ bool flipped = false; bool nearest_neighbor = false; quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, j, - gfx::Size(), false, premultiplied_alpha, uv_top_left, + gfx::Size(), premultiplied_alpha, uv_top_left, uv_bottom_right, background_color, vertex_opacity, flipped, nearest_neighbor); }
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index b2476d9d..bfec6e6 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -1582,9 +1582,9 @@ bool flipped = false; bool nearest_neighbor = false; quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, - resource_ids[i], gfx::Size(), false, premultiplied_alpha, - uv_top_left, uv_bottom_right, background_color, vertex_opacity, - flipped, nearest_neighbor); + resource_ids[i], gfx::Size(), premultiplied_alpha, uv_top_left, + uv_bottom_right, background_color, vertex_opacity, flipped, + nearest_neighbor); } frame_data->render_pass_list.push_back(pass.Pass()); scoped_ptr<CompositorFrame> frame(new CompositorFrame);
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc index c858ea51..bb3a809 100644 --- a/cc/test/render_pass_test_utils.cc +++ b/cc/test/render_pass_test_utils.cc
@@ -219,7 +219,7 @@ to_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>(); io_surface_quad->SetNew(shared_state, rect, opaque_rect, visible_rect, gfx::Size(50, 50), resource7, - IOSurfaceDrawQuad::FLIPPED, false); + IOSurfaceDrawQuad::FLIPPED); if (child_pass.layer_id) { RenderPassDrawQuad* render_pass_quad = @@ -245,7 +245,7 @@ StreamVideoDrawQuad* stream_video_quad = to_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); stream_video_quad->SetNew(shared_state, rect, opaque_rect, visible_rect, - resource6, gfx::Size(), false, gfx::Transform()); + resource6, gfx::Size(), gfx::Transform()); TextureDrawQuad* texture_quad = to_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index ce1bf70..0b5194e 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -40,7 +40,27 @@ gfx::Rect clip_rect_in_target_space; gfx::Rect combined_clip_rect_in_target_space; bool success = true; + + gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); + // When both the layer and the target are unclipped, the entire layer + // content rect is visible. + if (!clip_node->data.layers_are_clipped && + !clip_node->data.target_is_clipped) { + layer->set_visible_rect_from_property_trees(layer_content_rect); + layer->set_clip_rect_in_target_space_from_property_trees(gfx::Rect()); + continue; + } + if (clip_node->data.target_id != target_node->id) { + // In this case, layer has a clip parent (or shares the target with an + // ancestor layer that has clip parent) and the clip parent's target is + // different from the layer's target. As the layer's target has + // unclippped descendants, it is unclippped. + if (!clip_node->data.layers_are_clipped) { + layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds)); + layer->set_clip_rect_in_target_space_from_property_trees(gfx::Rect()); + continue; + } gfx::Transform clip_to_target; success = transform_tree.ComputeTransformWithDestinationSublayerScale( clip_node->data.target_id, target_node->id, &clip_to_target); @@ -53,9 +73,15 @@ continue; } DCHECK_LT(clip_node->data.target_id, target_node->id); + // We use the clip node's clip_in_target_space (and not + // combined_clip_in_target_space) here because we want to clip + // with respect to clip parent's local clip and not its combined clip as + // the combined clip has even the clip parent's target's clip baked into + // it and as our target is different, we don't want to use it in our + // visible rect computation. combined_clip_rect_in_target_space = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - clip_to_target, clip_node->data.combined_clip_in_target_space)); + clip_to_target, clip_node->data.clip_in_target_space)); clip_rect_in_target_space = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( clip_to_target, clip_node->data.clip_in_target_space)); @@ -78,7 +104,6 @@ content_to_target.Translate(layer->offset_to_transform_parent().x(), layer->offset_to_transform_parent().y()); - gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); gfx::Rect layer_content_bounds_in_target_space = MathUtil::MapEnclosingClippedRect(content_to_target, layer_content_rect); @@ -458,7 +483,7 @@ if (use_only_parent_clip) { clip_node->data.combined_clip_in_target_space = parent_combined_clip_in_target_space; - if (!clip_node->data.render_surface_is_clipped) { + if (!clip_node->data.target_is_clipped) { clip_node->data.clip_in_target_space = parent_combined_clip_in_target_space; } else { @@ -650,7 +675,7 @@ // clipped. if (render_surface->OwningLayerId() != clip_node->owner_id) return false; - return clip_node->data.render_surface_is_clipped; + return clip_node->data.target_is_clipped; } gfx::Rect SurfaceClipRect(const RenderSurfaceImpl* render_surface,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 7b8af5ac..c90ea949 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -7945,6 +7945,39 @@ render_surface->render_surface()->DrawableContentRect()); } +TEST_F(LayerTreeHostCommonTest, ClipChildVisibleRect) { + LayerImpl* root = root_layer(); + LayerImpl* clip_parent = AddChildToRoot<LayerImpl>(); + LayerImpl* render_surface = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_child = AddChild<LayerImpl>(render_surface); + + const gfx::Transform identity_matrix; + clip_parent->SetMasksToBounds(true); + render_surface->SetMasksToBounds(true); + render_surface->SetDrawsContent(true); + clip_child->SetDrawsContent(true); + clip_child->SetClipParent(clip_parent); + scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>); + clip_children->insert(clip_child); + clip_parent->SetClipChildren(clip_children.release()); + + SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(30, 30), true, false, + true); + SetLayerPropertiesForTesting(clip_parent, identity_matrix, gfx::Point3F(), + gfx::PointF(10.f, 10.f), gfx::Size(40, 40), true, + false, false); + SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, + true); + SetLayerPropertiesForTesting(clip_child, identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false, + false); + + ExecuteCalculateDrawProperties(root); + EXPECT_EQ(gfx::Rect(40, 40), clip_child->visible_layer_rect()); +} + TEST_F(LayerTreeHostCommonTest, LayerClipRectLargerThanClippingRenderSurfaceRect) { LayerImpl* root = root_layer();
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index cb6311a2..210d757a 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -105,7 +105,7 @@ applies_local_clip(true), layer_clipping_uses_only_local_clip(false), layer_visibility_uses_only_local_clip(false), - render_surface_is_clipped(false), + target_is_clipped(false), layers_are_clipped(false), resets_clip(false) {}
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 1b4d0925..e7457a19 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -190,9 +190,8 @@ // ancestor nodes. bool layer_visibility_uses_only_local_clip : 1; - // True if render surfaces with this clip tree node need to be drawn with a - // clip applied. - bool render_surface_is_clipped : 1; + // True if target surface needs to be drawn with a clip applied. + bool target_is_clipped : 1; // True if layers with this clip tree node need to be drawn with a clip // applied.
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 95145da..3000621 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -43,6 +43,7 @@ bool affected_by_inner_viewport_bounds_delta; bool affected_by_outer_viewport_bounds_delta; bool should_flatten; + bool target_is_clipped; const gfx::Transform* device_transform; gfx::Vector2dF scroll_compensation_adjustment; int sequence_number; @@ -121,9 +122,15 @@ // when computing clip rects or visibility. has_unclipped_surface = true; } + // A surface with unclipped descendants cannot be clipped by its ancestor + // clip at draw time since the unclipped descendants aren't affected by the + // ancestor clip. + data_for_children->target_is_clipped = + ancestor_clips_subtree && !layer->num_unclipped_descendants(); } else { // Without a new render surface, layer clipping state from ancestors needs // to continue to propagate. + data_for_children->target_is_clipped = data_from_ancestor.target_is_clipped; layers_are_clipped = ancestor_clips_subtree; } @@ -191,13 +198,7 @@ } node.data.resets_clip = has_unclipped_surface || !parent_applies_clip; - - // A surface with unclipped descendants cannot be clipped by its ancestor - // clip at draw time since the unclipped descendants aren't affected by the - // ancestor clip. - node.data.render_surface_is_clipped = layer->has_render_surface() && - ancestor_clips_subtree && - !layer->num_unclipped_descendants(); + node.data.target_is_clipped = data_for_children->target_is_clipped; node.data.layers_are_clipped = layers_are_clipped; data_for_children->clip_tree_parent = @@ -565,6 +566,7 @@ data_for_recursion.affected_by_inner_viewport_bounds_delta = false; data_for_recursion.affected_by_outer_viewport_bounds_delta = false; data_for_recursion.should_flatten = false; + data_for_recursion.target_is_clipped = false; data_for_recursion.device_transform = &device_transform; data_for_recursion.transform_tree->clear();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index b8d40d8..2ea38c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -70,7 +70,6 @@ import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoScreen; import org.chromium.chrome.browser.signin.SigninPromoScreen; import org.chromium.chrome.browser.snackbar.undo.UndoBarPopupController; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.ChromeTabCreator; import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; @@ -409,7 +408,7 @@ mLayoutManager = new LayoutManagerChromePhone(compositorViewHolder, new StackLayoutFactory()); } - + mLayoutManager.setEnableAnimations(DeviceClassManager.enableAnimations(this)); mLayoutManager.addOverviewModeObserver(this); // TODO(yusufo): get rid of findViewById(R.id.url_bar). @@ -673,7 +672,7 @@ case CLOBBER_CURRENT_TAB: // The browser triggered the intent. This happens when clicking links which // can be handled by other applications (e.g. www.youtube.com links). - ChromeTab currentTab = ChromeTab.fromTab(getActivityTab()); + Tab currentTab = getActivityTab(); if (currentTab != null) { currentTab.getTabRedirectHandler().updateIntent(intent); int transitionType = PageTransition.LINK | PageTransition.FROM_API;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java index c853efe..d2552e5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
@@ -215,10 +215,26 @@ cvc = activity.getCurrentContentViewCore(); if (cvc != null) cvc.zoomReset(); return true; + case SHIFT | CTRL | KeyEvent.KEYCODE_R: case CTRL | KeyEvent.KEYCODE_R: + case SHIFT | KeyEvent.KEYCODE_F5: case KeyEvent.KEYCODE_F5: Tab tab = activity.getActivityTab(); - if (tab != null) tab.reload(); + if (tab != null) { + if ((keyCodeAndMeta & SHIFT) == SHIFT) { + tab.reloadIgnoringCache(); + } else { + tab.reload(); + } + + if (activity.getToolbarManager() != null + && tab.getWebContents() != null + && tab.getWebContents().focusLocationBarByDefault()) { + activity.getToolbarManager().revertLocationBarChanges(); + } else { + tab.requestFocus(); + } + } return true; case ALT | KeyEvent.KEYCODE_DPAD_LEFT: tab = activity.getActivityTab();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java index b7378175..44751a6b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -77,7 +77,7 @@ /** Responsible for building all incognito titles. */ protected TitleBitmapFactory mIncognitoTitleBitmapFactory; /** Whether or not animations are enabled. This can disable certain layouts or effects. */ - protected boolean mEnableAnimations = true; + private boolean mEnableAnimations = true; private boolean mCreatingNtp; private final ObserverList<OverviewModeObserver> mOverviewModeObservers; private TabModelSelectorObserver mTabModelSelectorObserver; @@ -678,6 +678,14 @@ mEnableAnimations = enabled; } + /** + * @return Whether animations should be done for model changes. + */ + @VisibleForTesting + public boolean animationsEnabled() { + return mEnableAnimations; + } + @Override public boolean overviewVisible() { Layout activeLayout = getActiveLayout();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java index bb56c7c..9265acbf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -89,7 +89,7 @@ // The user is currently interacting with the {@code LayoutHost}. // Allow the foreground layout to animate the tab closing. getActiveLayout().onTabClosing(time(), id); - } else if (mEnableAnimations) { + } else if (animationsEnabled()) { startShowing(mSimpleAnimationLayout, false); getActiveLayout().onTabClosing(time(), id); } @@ -107,7 +107,7 @@ getActiveLayout().onTabClosed(time(), id, nextId, incognito); Tab nextTab = getTabById(nextId); if (nextTab != null) nextTab.requestFocus(); - if (getActiveLayout() != overviewLayout && showOverview && !mEnableAnimations) { + if (getActiveLayout() != overviewLayout && showOverview && !animationsEnabled()) { startShowing(overviewLayout, false); } } @@ -119,7 +119,7 @@ // This check allows us to switch from the StackLayout to the SimpleAnimationLayout // smoothly. getActiveLayout().onTabCreating(sourceId); - } else if (mEnableAnimations) { + } else if (animationsEnabled()) { if (getActiveLayout() != null && getActiveLayout().isHiding()) { setNextLayout(mSimpleAnimationLayout); // The method Layout#doneHiding() will automatically show the next layout.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java index 054595e..b1539d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java
@@ -39,7 +39,6 @@ import org.chromium.chrome.browser.dom_distiller.ReaderModeStaticEventFilter.ReaderModePanelSelector; import org.chromium.chrome.browser.dom_distiller.ReaderModeStaticEventFilter.ReaderModeTapHandler; import org.chromium.chrome.browser.fullscreen.FullscreenManager; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -256,7 +255,7 @@ if (getTabModelSelector() == null || getActiveLayout() == null) return; TabModelSelector selector = getTabModelSelector(); - ChromeTab tab = ChromeTab.fromTab(selector.getTabById(tabId)); + Tab tab = selector.getTabById(tabId); if (tab == null) return; LayoutTab layoutTab = mTabCache.get(tabId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java index 09dd64d..f659238 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
@@ -20,7 +20,6 @@ import org.chromium.chrome.browser.dom_distiller.ReaderModePanel; import org.chromium.chrome.browser.dom_distiller.ReaderModePanel.ReaderModePanelLayoutDelegate; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelImpl; @@ -31,8 +30,8 @@ /** * A {@link Layout} that shows a single tab at full screen. This tab is chosen based on the - * {@link #tabSelecting(long, int)} call, and is used to show a thumbnail of a {@link ChromeTab} - * until that {@link ChromeTab} is ready to be shown. + * {@link #tabSelecting(long, int)} call, and is used to show a thumbnail of a {@link Tab} + * until that {@link Tab} is ready to be shown. */ public class StaticLayout extends ContextualSearchSupportedLayout { public static final String TAG = "StaticLayout";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index da24817..8f2cbd2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -28,8 +28,6 @@ private static final String DISABLE_FOR_JAPANESE = "disable_for_japanese"; private static final String DISABLE_FOR_KOREAN = "disable_for_korean"; - // TODO(pedrosimonetti): Confirm if we can delete promo_on_longpress_only now. - private static final String PROMO_ON_LONGPRESS_ONLY = "promo_on_longpress_only"; static final String PROMO_ON_LIMITED_TAPS = "promo_on_limited_taps"; static final String TAP_TRIGGERED_PROMO_LIMIT = "tap_triggered_promo_limit"; static final String TAP_RESOLVE_LIMIT_FOR_DECIDED = "tap_resolve_limit_for_decided"; @@ -138,14 +136,6 @@ } /** - * Gets whether the promo should be triggered on longpress only. - * @return {@code true} iff Finch says we should trigger the promo only on touch-and-hold. - */ - static boolean isPromoLongpressTriggeredOnly() { - return getBooleanParam(PROMO_ON_LONGPRESS_ONLY); - } - - /** * @return Whether the promo should be triggered by a limited number of taps. */ public static boolean isPromoLimitedByTapCounts() { @@ -304,16 +294,4 @@ return defaultValue; } - - /** - * Returns a string value for a Finch parameter. Also checks for a command-line switch. - * @param paramName The name of the Finch parameter (or command-line switch) to get a value for. - * @return The command-line value, if present, or the finch parameter value. - */ - private static String getStringParam(String paramName) { - if (CommandLine.getInstance().hasSwitch(paramName)) { - return CommandLine.getInstance().getSwitchValue(paramName); - } - return VariationsAssociatedData.getVariationParamValue(FIELD_TRIAL_NAME, paramName); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index b7da20b2..1fcfee1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -85,9 +85,6 @@ */ boolean isTapSupported() { if (!isUserUndecided()) return true; - - if (ContextualSearchFieldTrial.isPromoLongpressTriggeredOnly()) return false; - return !ContextualSearchFieldTrial.isPromoLimitedByTapCounts() || getPromoTapsRemaining() != 0; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkPage.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkPage.java index f30da93..65bdb519 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkPage.java
@@ -30,6 +30,10 @@ private final int mThemeColor; private EnhancedBookmarkManager mManager; + // For temporary debugging purposes. + // TODO(newt): delete this once http://crbug.com/540537 is fixed. + private Exception mDestroyStackTrace; + /** * Create a new instance of an enhanced bookmark page. * @param activity The activity to get context and manage fragments. @@ -102,6 +106,13 @@ @Override public void destroy() { + if (mDestroyStackTrace != null) { + throw new RuntimeException("EnhancedBookmarksPage was destroyed twice", + mDestroyStackTrace); + } else { + mDestroyStackTrace = new RuntimeException( + "Stack trace for first call to EnhancedBookmarksPage.destroy()"); + } mManager.destroy(); mManager = null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java index b73dc56..31b52df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
@@ -301,6 +301,20 @@ provider.sendStringMessage(routeId, message, callbackId); } + /** + * Sends a binary message to the specified route. + * @param routeId The id of the route to send the message to. + * @param data The binary message to send. + * @param callbackId The id of the result callback tracked by the native side. + */ + @CalledByNative + public void sendBinaryMessage(String routeId, byte[] data, int callbackId) { + MediaRouteProvider provider = mRouteIdsToProviders.get(routeId); + assert provider != null; + + provider.sendBinaryMessage(routeId, data, callbackId); + } + @VisibleForTesting ChromeMediaRouter(long nativeMediaRouter, Context applicationContext) { MediaRouteProvider provider = CastMediaRouteProvider.create(applicationContext, this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java index 213e219..0694b86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java
@@ -71,4 +71,13 @@ * @param nativeCallbackId The id of the result callback tracked by the native side. */ void sendStringMessage(String routeId, String message, int nativeCallbackId); + + /** + * Sends a binary message to the route with the given id. The route must be created by this + * provider. + * @param routeId The id of the route to send the message to. + * @param data The binary message to send. + * @param nativeCallbackId The id of the result callback tracked by the native side. + */ + void sendBinaryMessage(String routeId, byte[] data, int nativeCallbackId); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/RouteController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/RouteController.java index 346a55a..de252373 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/RouteController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/RouteController.java
@@ -22,6 +22,14 @@ void sendStringMessage(String message, int nativeCallbackId); /** + * Sends a binary message to the route and invokes the {@link RouteDelegate} with the + * passed callback id on success or failure. + * @param data The binary message to send. + * @param nativeCallbackId The id of the callback handling the result. + */ + void sendBinaryMessage(byte[] data, int nativeCallbackId); + + /** * @return the source id for the route. */ String getSourceId();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java index b3cd9a4..6acdd56 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java
@@ -292,6 +292,15 @@ route.sendStringMessage(message, nativeCallbackId); } + @Override + public void sendBinaryMessage(String routeId, byte[] data, int nativeCallbackId) { + // TODO(crbug.com/524128): Cast API does not support sending binary message + // to receiver application. Binary data may be converted to String and send as + // an app_message within it's own message namespace, using the string version. + // Sending failure in the result callback for now. + mManager.onMessageSentResult(false, nativeCallbackId); + } + private CastMediaRouteProvider( Context applicationContext, MediaRouter androidMediaRouter, MediaRouteManager manager) { mApplicationContext = applicationContext;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java index 836e985..3def2008 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastRouteController.java
@@ -176,6 +176,10 @@ mRouteDelegate.onMessageSentResult(false, callbackId); } + public void sendBinaryMessage(byte[] data, int callbackId) { + // TODO(crbug.com/524128): Implement this. + } + @Override public String getSourceId() { return mSource.getUrn();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java index 49db2a2..3c153aff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java
@@ -47,7 +47,7 @@ } @CalledByNative - private static long getMainEntryPointTime() { + public static long getMainEntryPointTime() { return sApplicationStartWallClockMs; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java index 763afdc..16fcbf3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
@@ -32,6 +32,10 @@ private boolean mIsLoaded; + // For temporary debugging purposes. + // TODO(newt): delete this once http://crbug.com/540537 is fixed. + private Exception mDestroyStackTrace; + private final IncognitoNewTabPageManager mIncognitoNewTabPageManager = new IncognitoNewTabPageManager() { @Override @@ -78,6 +82,14 @@ @Override public void destroy() { + if (mDestroyStackTrace != null) { + throw new RuntimeException("IncognitoNewTabPage was destroyed twice", + mDestroyStackTrace); + } else { + mDestroyStackTrace = new RuntimeException( + "Stack trace for first call to IncognitoNewTabPage.destroy()"); + } + assert getView().getParent() == null : "Destroy called before removed from window"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/InterestsService.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/InterestsService.java new file mode 100644 index 0000000..23878bd --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/InterestsService.java
@@ -0,0 +1,101 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.ntp; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.chrome.browser.profiles.Profile; + +/** + * Retrieve the user's interests. + */ +public class InterestsService { + private long mNativeInterestsService; + + /** + * A user's interest. + */ + public static class Interest { + private final String mName; + private final String mImageUrl; + private final double mRelevance; + + public Interest(String name, String imageUrl, double relevance) { + mName = name; + mImageUrl = imageUrl; + mRelevance = relevance; + } + + public String getName() { + return mName; + } + + public String getImageUrl() { + return mImageUrl; + } + + public double getRelevance() { + return mRelevance; + } + } + /** + * Interface for receiving the interests of a user. + */ + public interface GetInterestsCallback { + /** + * Callback method for fetching the interests of a user. + * + * @param interests The array of interests. Null if error. + */ + @CalledByNative("GetInterestsCallback") + public void onInterestsAvailableCallback(Interest[] interests); + } + + /** + * InterestsService constructor requires a valid user profile object. + * + * @param profile The profile for which to fetch the interests + */ + public InterestsService(Profile profile) { + mNativeInterestsService = nativeInit(profile); + } + + /** + * Cleans up the C++ side of this class. This instance must not be used after calling destroy(). + */ + public void destroy() { + assert mNativeInterestsService != 0; + nativeDestroy(mNativeInterestsService); + mNativeInterestsService = 0; + } + + public void getInterests(final GetInterestsCallback callback) { + GetInterestsCallback wrappedCallback = new GetInterestsCallback() { + @Override + public void onInterestsAvailableCallback(Interest[] interests) { + callback.onInterestsAvailableCallback(interests); + } + }; + + nativeGetInterests(mNativeInterestsService, wrappedCallback); + } + + /* + * Helper methods for the native part. + */ + @CalledByNative + private static Interest createInterest(String name, String imageUrl, double relevance) { + return new Interest(name, imageUrl, relevance); + } + + @CalledByNative + private static Interest[] createInterestsArray(int size) { + return new Interest[size]; + } + + private native long nativeInit(Profile profile); + private native void nativeDestroy(long nativeInterestsService); + private native void nativeGetInterests( + long nativeInterestsService, GetInterestsCallback callback); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 5d7db9bd..91c555e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -110,6 +110,10 @@ // Whether destroy() has been called. private boolean mIsDestroyed; + // For temporary debugging purposes. + // TODO(newt): delete this once http://crbug.com/540537 is fixed. + private Exception mDestroyStackTrace; + /** * Allows clients to listen for updates to the scroll changes of the search box on the * NTP. @@ -565,6 +569,14 @@ @Override public void destroy() { + if (mDestroyStackTrace != null) { + throw new RuntimeException("NewTabPage was destroyed twice", + mDestroyStackTrace); + } else { + mDestroyStackTrace = new RuntimeException( + "Stack trace for first call to NewTabPage.destroy()"); + } + assert !mIsDestroyed; assert getView().getParent() == null : "Destroy called before removed from window"; if (mFaviconHelper != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java index bc6ce806..952ff37 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -115,6 +115,12 @@ void setUrlBarFocus(boolean shouldBeFocused); /** + * Reverts any pending edits of the location bar and reset to the page state. This does not + * change the focus state of the location bar. + */ + void revertChanges(); + + /** * @return The timestamp for the {@link UrlBar} gaining focus for the first time. */ long getFirstUrlBarFocusTime();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 585e9db..aa721714 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -67,8 +67,6 @@ import org.chromium.chrome.browser.WebsiteSettingsPopup; import org.chromium.chrome.browser.WindowDelegate; import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; -import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory; -import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils; import org.chromium.chrome.browser.ntp.NativePageFactory; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate; @@ -84,7 +82,6 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ActionModeController; import org.chromium.chrome.browser.toolbar.ActionModeController.ActionBarDelegate; @@ -96,8 +93,6 @@ import org.chromium.chrome.browser.util.KeyNavigationUtil; import org.chromium.chrome.browser.util.ViewUtils; import org.chromium.chrome.browser.widget.TintedImageButton; -import org.chromium.components.dom_distiller.core.DomDistillerService; -import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.accessibility.BrowserAccessibilityManager; import org.chromium.content_public.browser.LoadUrlParams; @@ -918,6 +913,21 @@ } @Override + public void revertChanges() { + if (!mUrlHasFocus) { + setUrlToPageUrl(); + } else { + Tab tab = mToolbarDataProvider.getTab(); + if (NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncognito())) { + mUrlBar.setUrl("", null); + } else { + mUrlBar.setUrl( + mToolbarDataProvider.getText(), mToolbarDataProvider.getTab().getUrl()); + } + } + } + + @Override public long getFirstUrlBarFocusTime() { return mUrlBar.getFirstFocusTime(); } @@ -1297,14 +1307,6 @@ findViewById(R.id.location_bar_icon).setVisibility(showContainer ? VISIBLE : GONE); } - private boolean isStoredArticle(String url) { - DomDistillerService domDistillerService = - DomDistillerServiceFactory.getForProfile(Profile.getLastUsedProfile()); - String entryIdFromUrl = DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id"); - if (TextUtils.isEmpty(entryIdFromUrl)) return false; - return domDistillerService.hasEntry(entryIdFromUrl); - } - /** * Updates the layout params for the location bar start aligned views. */ @@ -1668,9 +1670,9 @@ } /** - * Performs a search query on the current {@link ChromeTab}. This calls + * Performs a search query on the current {@link Tab}. This calls * {@link TemplateUrlService#getUrlForSearchQuery(String)} to get a url based on {@code query} - * and loads that url in the current {@link ChromeTab}. + * and loads that url in the current {@link Tab}. * @param query The {@link String} that represents the text query that should be searched for. */ @VisibleForTesting @@ -1960,12 +1962,15 @@ boolean showingQuery = false; String displayText = mToolbarDataProvider.getText(); - int securityLevel = getSecurityLevel(); - if (securityLevel != ConnectionSecurityLevel.SECURITY_ERROR - && !TextUtils.isEmpty(displayText) && mToolbarDataProvider.wouldReplaceURL()) { - url = displayText.trim(); - showingQuery = true; - mQueryInTheOmnibox = true; + if (!TextUtils.isEmpty(displayText) && mToolbarDataProvider.wouldReplaceURL()) { + if (getSecurityLevel() == ConnectionSecurityLevel.SECURITY_ERROR) { + assert false : "Search terms should not be shown for https error pages."; + displayText = url; + } else { + url = displayText.trim(); + showingQuery = true; + mQueryInTheOmnibox = true; + } } String path = null; if (!showingQuery && FeatureUtilities.isDocumentMode(getContext())) { @@ -1974,21 +1979,6 @@ path = urlText.second; } - if (DomDistillerUrlUtils.isDistilledPage(url)) { - if (isStoredArticle(url)) { - DomDistillerService domDistillerService = - DomDistillerServiceFactory.getForProfile(profile); - String originalUrl = domDistillerService.getUrlForEntry( - DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id")); - displayText = - DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl); - } else if (DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url) != null) { - String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); - displayText = - DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl); - } - } - if (setUrlBarText(displayText, path, url)) { mUrlBar.deEmphasizeUrl(); emphasizeUrl(); @@ -2087,12 +2077,12 @@ } /** - * @return The ChromeTab currently showing. + * @return The Tab currently showing. */ @Override - public ChromeTab getCurrentTab() { + public Tab getCurrentTab() { if (mToolbarDataProvider == null) return null; - return ChromeTab.fromTab(mToolbarDataProvider.getTab()); + return mToolbarDataProvider.getTab(); } private ContentViewCore getContentViewCore() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java index 6bc1e22..73fb9a8b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -37,7 +37,7 @@ import org.chromium.chrome.browser.UrlUtilities; import org.chromium.chrome.browser.metrics.StartupMetrics; import org.chromium.chrome.browser.omnibox.LocationBarLayout.OmniboxLivenessListener; -import org.chromium.chrome.browser.tab.ChromeTab; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.widget.VerticallyFixedEditText; import org.chromium.content.browser.ContentViewCore; import org.chromium.ui.UiUtils; @@ -133,9 +133,9 @@ */ public interface UrlBarDelegate { /** - * @return The current active {@link ChromeTab}. + * @return The current active {@link Tab}. */ - ChromeTab getCurrentTab(); + Tab getCurrentTab(); /** * Notify the linked {@link TextWatcher} to ignore any changes made in the UrlBar text. @@ -445,7 +445,7 @@ return true; } - ChromeTab currentTab = mUrlBarDelegate.getCurrentTab(); + Tab currentTab = mUrlBarDelegate.getCurrentTab(); if (event.getAction() == MotionEvent.ACTION_DOWN && currentTab != null) { // Make sure to hide the current ContentView ActionBar. ContentViewCore viewCore = currentTab.getContentViewCore(); @@ -948,7 +948,7 @@ // We retrieve the domain and registry from the full URL (the url bar shows a simplified // version of the URL). - ChromeTab currentTab = mUrlBarDelegate.getCurrentTab(); + Tab currentTab = mUrlBarDelegate.getCurrentTab(); if (currentTab == null || currentTab.getProfile() == null) return; boolean isInternalPage = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java index 6c67dc2..93f53e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java
@@ -30,7 +30,6 @@ import org.chromium.content.browser.crypto.CipherFactory; import org.chromium.content_public.browser.GestureStateListener; import org.chromium.content_public.browser.LoadUrlParams; -import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.ui.base.PageTransition; import org.chromium.ui.base.WindowAndroid; @@ -47,8 +46,6 @@ private ReaderModeManager mReaderModeManager; - private TabRedirectHandler mTabRedirectHandler; - private boolean mIsFullscreenWaitingForLoad = false; /** @@ -61,8 +58,6 @@ */ private boolean mIsNativePageCommitPending; - private WebContentsObserver mWebContentsObserver; - /** * Listens to gesture events fired by the ContentViewCore. */ @@ -106,26 +101,12 @@ mReaderModeManager = new ReaderModeManager(this, activity); RevenueStats.getInstance().tabCreated(this); - mTabRedirectHandler = new TabRedirectHandler(activity); - ContextualSearchTabHelper.createForTab(this); if (nativeWindow != null) ThumbnailTabHelper.createForTab(this); MediaSessionTabHelper.createForTab(this); } /** - * Creates a minimal {@link ChromeTab} for testing. Do not use outside testing. - * - * @param id The id of the tab. - * @param incognito Whether the tab is incognito. - */ - @VisibleForTesting - public ChromeTab(int id, boolean incognito) { - super(id, incognito, null); - mTabRedirectHandler = new TabRedirectHandler(null); - } - - /** * Creates a fresh tab. initialize() needs to be called afterwards to complete the second level * initialization. * @param initiallyHidden true iff the tab being created is initially in background @@ -235,9 +216,6 @@ try { TraceEvent.begin("ChromeTab.setContentViewCore"); super.setContentViewCore(cvc); - mWebContentsObserver = new TabWebContentsObserver(cvc.getWebContents(), this); - - setInterceptNavigationDelegate(createInterceptNavigationDelegate()); if (mGestureStateListener == null) mGestureStateListener = createGestureStateListener(); cvc.addGestureStateListener(mGestureStateListener); @@ -284,18 +262,6 @@ if (mGestureStateListener != null) { cvc.removeGestureStateListener(mGestureStateListener); } - if (mWebContentsObserver != null) { - mWebContentsObserver.destroy(); - } - mWebContentsObserver = null; - } - - /** - * @return Whether the tab is ready to display or it should be faded in as it loads. - */ - public boolean shouldStall() { - return (isFrozen() || needsReload()) - && !NativePageFactory.isNativePageUrl(getUrl(), isIncognito()); } @Override @@ -322,8 +288,6 @@ // Allow this tab's NativePage to be frozen if it stays hidden for a while. NativePageAssassin.getInstance().tabHidden(this); - - mTabRedirectHandler.clear(); } @Override @@ -351,38 +315,6 @@ } } - @VisibleForTesting - public AuthenticatorNavigationInterceptor getAuthenticatorHelper() { - return getInterceptNavigationDelegate().getAuthenticatorNavigationInterceptor(); - } - - /** - * @return the TabRedirectHandler for the tab. - */ - public TabRedirectHandler getTabRedirectHandler() { - return mTabRedirectHandler; - } - - @Override - protected boolean shouldIgnoreNewTab(String url, boolean incognito) { - InterceptNavigationDelegateImpl delegate = getInterceptNavigationDelegate(); - return delegate != null && delegate.shouldIgnoreNewTab(url, incognito); - } - - @Override - public InterceptNavigationDelegateImpl getInterceptNavigationDelegate() { - return (InterceptNavigationDelegateImpl) super.getInterceptNavigationDelegate(); - } - - /** - * Factory method for {@link InterceptNavigationDelegateImpl}. Meant to be overridden by - * subclasses. - * @return A new instance of {@link InterceptNavigationDelegateImpl}. - */ - protected InterceptNavigationDelegateImpl createInterceptNavigationDelegate() { - return new InterceptNavigationDelegateImpl(mActivity, this); - } - /** * @return The reader mode manager for this tab that handles UI events for reader mode. */ @@ -394,13 +326,9 @@ return mActivity == null ? null : mActivity.getReaderModeActivityDelegate(); } - /** - * Shows a native page for url if it's a valid chrome-native URL. Otherwise, does nothing. - * @param url The url of the current navigation. - * @param isReload Whether the current navigation is a reload. - * @return True, if a native page was displayed for url. - */ + @Override boolean maybeShowNativePage(String url, boolean isReload) { + super.maybeShowNativePage(url, isReload); NativePage candidateForReuse = isReload ? null : getNativePage(); NativePage nativePage = NativePageFactory.createNativePageForURL(url, candidateForReuse, this, mActivity.getTabModelSelector(), mActivity); @@ -413,12 +341,9 @@ return false; } - /** - * Update internal Tab state when provisional load gets committed. - * @param url The URL that was loaded. - * @param transitionType The transition type to the current URL. - */ + @Override void handleDidCommitProvisonalLoadForFrame(String url, int transitionType) { + super.handleDidCommitProvisonalLoadForFrame(url, transitionType); mIsNativePageCommitPending = false; boolean isReload = (transitionType == PageTransition.RELOAD); if (!maybeShowNativePage(url, isReload)) { @@ -429,6 +354,10 @@ mHandler.sendEmptyMessageDelayed( MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS); updateFullscreenEnabledState(); + + if (getInterceptNavigationDelegate() != null) { + getInterceptNavigationDelegate().maybeUpdateNavigationHistory(); + } } // TODO(dtrainor): Port more methods to the observer.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java index dce05ce..031c067 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
@@ -24,7 +24,7 @@ */ public class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate { private final ChromeActivity mActivity; - private final ChromeTab mTab; + private final Tab mTab; private final ExternalNavigationHandler mExternalNavHandler; private final AuthenticatorNavigationInterceptor mAuthenticatorHelper; private ExternalNavigationHandler.OverrideUrlLoadingResult mLastOverrideUrlLoadingResult = @@ -39,7 +39,7 @@ /** * Default constructor of {@link InterceptNavigationDelegateImpl}. */ - public InterceptNavigationDelegateImpl(ChromeActivity activity, ChromeTab tab) { + public InterceptNavigationDelegateImpl(ChromeActivity activity, Tab tab) { this(new ExternalNavigationHandler(activity), activity, tab); } @@ -48,7 +48,7 @@ * {@link ExternalNavigationHandler}. */ public InterceptNavigationDelegateImpl(ExternalNavigationHandler externalNavHandler, - ChromeActivity activity, ChromeTab tab) { + ChromeActivity activity, Tab tab) { mActivity = activity; mTab = tab; mExternalNavHandler = externalNavHandler;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 2f654a0..a78c740 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -22,11 +22,8 @@ import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; -import org.chromium.base.ActivityState; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.ApplicationState; import org.chromium.base.ApplicationStatus; -import org.chromium.base.CommandLine; import org.chromium.base.ObserverList; import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.base.TraceEvent; @@ -37,8 +34,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.AccessibilityUtil; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.FrozenNativePage; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.NativePage; @@ -61,9 +56,8 @@ import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.infobar.InfoBarContainer; -import org.chromium.chrome.browser.metrics.UmaSessionStats; -import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; +import org.chromium.chrome.browser.ntp.NativePageFactory; import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.printing.TabPrinter; @@ -77,7 +71,6 @@ import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModelImpl; import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.components.navigation_interception.InterceptNavigationDelegate; import org.chromium.content.browser.ActivityContentVideoViewClient; import org.chromium.content.browser.ContentVideoViewClient; @@ -86,7 +79,6 @@ import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.common.Referrer; import org.chromium.content_public.common.TopControlsState; import org.chromium.printing.PrintManagerDelegateImpl; @@ -130,12 +122,6 @@ private static final long INVALID_TIMESTAMP = -1; - // TabRendererCrashStatus defined in tools/metrics/histograms/histograms.xml. - private static final int TAB_RENDERER_CRASH_STATUS_SHOWN_IN_FOREGROUND_APP = 0; - private static final int TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP = 1; - private static final int TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP = 2; - private static final int TAB_RENDERER_CRASH_STATUS_MAX = 3; - /** * The required page load percentage for the page to be considered ready assuming the * TextureView is also ready. @@ -204,7 +190,7 @@ // Content layer Observers and Delegates private ContentViewClient mContentViewClient; - private WebContentsObserver mWebContentsObserver; + private TabWebContentsObserver mWebContentsObserver; private TabWebContentsDelegateAndroid mWebContentsDelegate; /** @@ -325,7 +311,9 @@ * allows presenting the intent picker to the user so that a native Android application can be * used if available. */ - private InterceptNavigationDelegate mInterceptNavigationDelegate; + private InterceptNavigationDelegateImpl mInterceptNavigationDelegate; + + private TabRedirectHandler mTabRedirectHandler; private FullscreenManager mFullscreenManager; private float mPreviousFullscreenTopControlsOffsetY = Float.NaN; @@ -345,7 +333,6 @@ private View mSadTabView; private final int mDefaultThemeColor; - private int mThemeColor; /** * The data reduction proxy was in use on the last page load if true. @@ -585,202 +572,6 @@ } } - private class TabWebContentsObserver extends WebContentsObserver { - public TabWebContentsObserver(WebContents webContents) { - super(webContents); - } - - @Override - public void renderProcessGone(boolean processWasOomProtected) { - Log.i(TAG, "renderProcessGone() for tab id: " + getId() - + ", oom protected: " + Boolean.toString(processWasOomProtected) - + ", already needs reload: " + Boolean.toString(needsReload())); - // Do nothing for subsequent calls that happen while the tab remains crashed. This - // can occur when the tab is in the background and it shares the renderer with other - // tabs. After the renderer crashes, the WebContents of its tabs are still around - // and they still share the RenderProcessHost. When one of the tabs reloads spawning - // a new renderer for the shared RenderProcessHost and the new renderer crashes - // again, all tabs sharing this renderer will be notified about the crash (including - // potential background tabs that did not reload yet). - if (needsReload() || isShowingSadTab()) return; - - int activityState = ApplicationStatus.getStateForActivity( - mWindowAndroid.getActivity().get()); - int rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_MAX; - if (!processWasOomProtected - || activityState == ActivityState.PAUSED - || activityState == ActivityState.STOPPED - || activityState == ActivityState.DESTROYED) { - // The tab crashed in background or was killed by the OS out-of-memory killer. - //setNeedsReload(true); - mNeedsReload = true; - if (ApplicationStatus.getStateForApplication() - == ApplicationState.HAS_RUNNING_ACTIVITIES) { - rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP; - } else { - rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP; - } - } else { - rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_SHOWN_IN_FOREGROUND_APP; - showSadTab(); - // This is necessary to correlate histogram data with stability counts. - UmaSessionStats.logRendererCrash(); - } - RecordHistogram.recordEnumeratedHistogram( - "Tab.RendererCrashStatus", rendererCrashStatus, TAB_RENDERER_CRASH_STATUS_MAX); - - mIsLoading = false; - mIsBeingRestored = false; - handleTabCrash(); - - boolean sadTabShown = isShowingSadTab(); - RewindableIterator<TabObserver> observers = getTabObservers(); - while (observers.hasNext()) { - observers.next().onCrash(Tab.this, sadTabShown); - } - } - - @Override - public void navigationEntryCommitted() { - if (getNativePage() != null) { - pushNativePageStateToNavigationEntry(); - } - } - - @Override - public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) { - if (isMainFrame) didFinishPageLoad(); - } - - @Override - public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode, - String description, String failingUrl, boolean wasIgnoredByHandler) { - for (TabObserver observer : mObservers) { - observer.onDidFailLoad(Tab.this, isProvisionalLoad, isMainFrame, errorCode, - description, failingUrl); - } - - if (isMainFrame) didFailPageLoad(errorCode); - } - - @Override - public void didStartProvisionalLoadForFrame(long frameId, long parentFrameId, - boolean isMainFrame, String validatedUrl, boolean isErrorPage, - boolean isIframeSrcdoc) { - if (isMainFrame) didStartPageLoad(validatedUrl, isErrorPage); - - for (TabObserver observer : mObservers) { - observer.onDidStartProvisionalLoadForFrame(Tab.this, frameId, parentFrameId, - isMainFrame, validatedUrl, isErrorPage, isIframeSrcdoc); - } - } - - @Override - public void didCommitProvisionalLoadForFrame(long frameId, boolean isMainFrame, String url, - int transitionType) { - if (isMainFrame && UmaUtils.isRunningApplicationStart()) { - nativeRecordStartupToCommitUma(); - UmaUtils.setRunningApplicationStart(false); - } - - if (isMainFrame) { - mIsTabStateDirty = true; - updateTitle(); - } - - for (TabObserver observer : mObservers) { - observer.onDidCommitProvisionalLoadForFrame( - Tab.this, frameId, isMainFrame, url, transitionType); - } - - notifyPageUrlChanged(); - } - - @Override - public void didNavigateMainFrame(String url, String baseUrl, - boolean isNavigationToDifferentPage, boolean isFragmentNavigation, int statusCode) { - FullscreenManager fullscreenManager = getFullscreenManager(); - if (isNavigationToDifferentPage && fullscreenManager != null) { - fullscreenManager.setPersistentFullscreenMode(false); - } - - for (TabObserver observer : mObservers) { - observer.onDidNavigateMainFrame( - Tab.this, url, baseUrl, isNavigationToDifferentPage, - isFragmentNavigation, statusCode); - } - - if (mSwipeRefreshHandler != null) { - mSwipeRefreshHandler.didStopRefreshing(); - } - } - - @Override - public void didFirstVisuallyNonEmptyPaint() { - for (TabObserver observer : mObservers) { - observer.didFirstVisuallyNonEmptyPaint(Tab.this); - } - } - - @Override - public void didChangeThemeColor(int color) { - int securityLevel = getSecurityLevel(); - if (securityLevel == ConnectionSecurityLevel.SECURITY_ERROR - || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING - || securityLevel == ConnectionSecurityLevel.SECURITY_POLICY_WARNING) { - color = mDefaultThemeColor; - } - if (isShowingInterstitialPage()) color = mDefaultThemeColor; - if (!FeatureUtilities.isDocumentMode(mApplicationContext) - && !isThemeColorEnabledInTabbedMode()) { - color = mDefaultThemeColor; - } - if (color == Color.TRANSPARENT) color = mDefaultThemeColor; - if (isIncognito()) color = mDefaultThemeColor; - color |= 0xFF000000; - - if (mThemeColor == color) return; - mThemeColor = color; - for (TabObserver observer : mObservers) { - observer.onDidChangeThemeColor(Tab.this, mThemeColor); - } - } - - @Override - public void didAttachInterstitialPage() { - getInfoBarContainer().setVisibility(View.INVISIBLE); - showRenderedPage(); - didChangeThemeColor(mDefaultThemeColor); - - for (TabObserver observer : mObservers) { - observer.onDidAttachInterstitialPage(Tab.this); - } - notifyLoadProgress(getProgress()); - - updateFullscreenEnabledState(); - } - - @Override - public void didDetachInterstitialPage() { - getInfoBarContainer().setVisibility(View.VISIBLE); - didChangeThemeColor(getWebContents().getThemeColor(mDefaultThemeColor)); - - for (TabObserver observer : mObservers) { - observer.onDidDetachInterstitialPage(Tab.this); - } - notifyLoadProgress(getProgress()); - - updateFullscreenEnabledState(); - } - - @Override - public void didStartNavigationToPendingEntry(String url) { - for (TabObserver observer : mObservers) { - observer.onDidStartNavigationToPendingEntry(Tab.this, url); - } - } - } - /** * Creates an instance of a {@link Tab}. * @param id The id this tab should be identified with. @@ -815,7 +606,6 @@ mDefaultThemeColor = mIncognito ? ApiCompatibilityUtils.getColor(resources, R.color.incognito_primary_color) : ApiCompatibilityUtils.getColor(resources, R.color.default_primary_color); - mThemeColor = mDefaultThemeColor; } else { mIdealFaviconSize = 16; mDefaultThemeColor = 0; @@ -840,6 +630,8 @@ } } }; + + mTabRedirectHandler = new TabRedirectHandler(activity); } /** @@ -1159,7 +951,8 @@ */ public int getThemeColor() { if (isNativePage()) return mNativePage.getThemeColor(); - return mThemeColor; + if (mWebContentsObserver != null) return mWebContentsObserver.getThemeColor(); + return mDefaultThemeColor; } /** @@ -1317,6 +1110,14 @@ } /** + * @return Whether the tab is ready to display or it should be faded in as it loads. + */ + public boolean shouldStall() { + return (isFrozen() || needsReload()) + && !NativePageFactory.isNativePageUrl(getUrl(), isIncognito()); + } + + /** * Prepares the tab to be shown. This method is supposed to be called before the tab is * displayed. It restores the ContentView if it is not available after the cold start and * reloads the tab if its renderer has crashed. @@ -1381,6 +1182,8 @@ if (mTabUma != null) mTabUma.onHide(); + mTabRedirectHandler.clear(); + hideInternal(); for (TabObserver observer : mObservers) observer.onHidden(this); @@ -1697,7 +1500,7 @@ new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); mWebContentsDelegate = createWebContentsDelegate(); - mWebContentsObserver = new TabWebContentsObserver(mContentViewCore.getWebContents()); + mWebContentsObserver = new TabWebContentsObserver(mContentViewCore.getWebContents(), this); if (mContentViewClient != null) mContentViewCore.setContentViewClient(mContentViewClient); @@ -1730,6 +1533,28 @@ mDownloadDelegate = new ChromeDownloadDelegate(mActivity, mActivity.getTabModelSelector(), this); cvc.setDownloadDelegate(mDownloadDelegate); + + setInterceptNavigationDelegate(createInterceptNavigationDelegate()); + } + + /** + * Shows a native page for url if it's a valid chrome-native URL. Otherwise, does nothing. + * @param url The url of the current navigation. + * @param isReload Whether the current navigation is a reload. + * @return True, if a native page was displayed for url. + */ + boolean maybeShowNativePage(String url, boolean isReload) { + // TODO(aurimas): move the implementation of this method from ChromeTab to Tab. + return false; + } + + /** + * Update internal Tab state when provisional load gets committed. + * @param url The URL that was loaded. + * @param transitionType The transition type to the current URL. + */ + void handleDidCommitProvisonalLoadForFrame(String url, int transitionType) { + // TODO(aurimas): move the implementation of this method from ChromeTab to Tab. } /** @@ -1925,13 +1750,6 @@ } } - private void notifyPageUrlChanged() { - RewindableIterator<TabObserver> observers = getTabObservers(); - while (observers.hasNext()) { - observers.next().onUrlUpdated(this); - } - } - /** * @return True if the tab title should be displayed from right to left. */ @@ -2579,7 +2397,10 @@ /** * Performs any subclass-specific tasks when the Tab crashes. */ - private void handleTabCrash() { + void handleTabCrash() { + mIsLoading = false; + mIsBeingRestored = false; + if (mTabUma != null) mTabUma.onRendererCrashed(); // Update the most recent minidump file with the logcat. Doing this asynchronously @@ -2644,7 +2465,10 @@ return mPreviousFullscreenOverdrawBottomHeight; } - private void pushNativePageStateToNavigationEntry() { + /** + * Add a new navigation entry for the current URL and page title. + */ + void pushNativePageStateToNavigationEntry() { assert mNativeTabAndroid != 0 && getNativePage() != null; nativeSetActiveNavigationEntryTitleForUrl(mNativeTabAndroid, getNativePage().getUrl(), getNativePage().getTitle()); @@ -2769,25 +2593,47 @@ * @return True if the Tab should block the creation of new tabs via {@link #openNewTab}. */ protected boolean shouldIgnoreNewTab(String url, boolean incognito) { - return false; + InterceptNavigationDelegateImpl delegate = getInterceptNavigationDelegate(); + return delegate != null && delegate.shouldIgnoreNewTab(url, incognito); } /** * See {@link #mInterceptNavigationDelegate}. */ - protected InterceptNavigationDelegate getInterceptNavigationDelegate() { + public InterceptNavigationDelegateImpl getInterceptNavigationDelegate() { return mInterceptNavigationDelegate; } + @VisibleForTesting + public AuthenticatorNavigationInterceptor getAuthenticatorHelper() { + return getInterceptNavigationDelegate().getAuthenticatorNavigationInterceptor(); + } + + /** + * Factory method for {@link InterceptNavigationDelegateImpl}. Meant to be overridden by + * subclasses. + * @return A new instance of {@link InterceptNavigationDelegateImpl}. + */ + protected InterceptNavigationDelegateImpl createInterceptNavigationDelegate() { + return new InterceptNavigationDelegateImpl(mActivity, this); + } + /** * See {@link #mInterceptNavigationDelegate}. */ - protected void setInterceptNavigationDelegate(InterceptNavigationDelegate delegate) { + protected void setInterceptNavigationDelegate(InterceptNavigationDelegateImpl delegate) { mInterceptNavigationDelegate = delegate; nativeSetInterceptNavigationDelegate(mNativeTabAndroid, delegate); } /** + * @return the TabRedirectHandler for the tab. + */ + public TabRedirectHandler getTabRedirectHandler() { + return mTabRedirectHandler; + } + + /** * @return the AppBannerManager. */ @VisibleForTesting @@ -2864,7 +2710,14 @@ * @return Whether the theme color for this tab is the default color. */ public boolean isDefaultThemeColor() { - return mDefaultThemeColor == mThemeColor; + return isNativePage() || mDefaultThemeColor == getThemeColor(); + } + + /** + * @return The default theme color for this tab. + */ + int getDefaultThemeColor() { + return mDefaultThemeColor; } /** @@ -2891,12 +2744,6 @@ return intent; } - private static boolean isThemeColorEnabledInTabbedMode() { - CommandLine commandLine = CommandLine.getInstance(); - return ChromeVersionInfo.isLocalBuild() - || commandLine.hasSwitch(ChromeSwitches.ENABLE_THEME_COLOR_IN_TABBED_MODE); - } - /** * Check whether the context menu download should be intercepted. * @@ -2920,6 +2767,9 @@ mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN; } + /** + * Reset swipe-to-refresh handler. + */ void resetSwipeRefreshHandler() { // When the dialog is visible, keeping the refresh animation active // in the background is distracting and unnecessary (and likely to @@ -2930,6 +2780,15 @@ } /** + * Stop swipe-to-refresh animation. + */ + void stopSwipeRefreshHandler() { + if (mSwipeRefreshHandler != null) { + mSwipeRefreshHandler.didStopRefreshing(); + } + } + + /** * Checks if spdy proxy is enabled for input url. * @param url Input url to check for spdy setting. * @return true if url is enabled for spdy proxy. @@ -2997,6 +2856,4 @@ private native void nativeDetachOverlayContentViewCore(long nativeTabAndroid, ContentViewCore content); private native boolean nativeHasPrerenderedUrl(long nativeTabAndroid, String url); - - private static native void nativeRecordStartupToCommitUma(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index 97291eb..46fbb7d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -4,13 +4,32 @@ package org.chromium.chrome.browser.tab; +import android.graphics.Color; +import android.view.View; + +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.CommandLine; +import org.chromium.base.Log; +import org.chromium.base.ObserverList.RewindableIterator; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.ChromeApplication; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.media.MediaCaptureNotificationService; +import org.chromium.chrome.browser.metrics.UmaSessionStats; +import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.chrome.browser.policy.PolicyAuditor; import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent; +import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel; +import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; +import java.util.concurrent.TimeUnit; + /** * WebContentsObserver used by Tab. */ @@ -18,15 +37,82 @@ // URL didFailLoad error code. Should match the value in net_error_list.h. public static final int BLOCKED_BY_ADMINISTRATOR = -22; - private final ChromeTab mTab; + /** Used for logging. */ + private static final String TAG = "TabWebContentsObs"; - public TabWebContentsObserver(WebContents webContents, ChromeTab tab) { + // TabRendererCrashStatus defined in tools/metrics/histograms/histograms.xml. + private static final int TAB_RENDERER_CRASH_STATUS_SHOWN_IN_FOREGROUND_APP = 0; + private static final int TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP = 1; + private static final int TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP = 2; + private static final int TAB_RENDERER_CRASH_STATUS_MAX = 3; + + private final Tab mTab; + private int mThemeColor; + + public TabWebContentsObserver(WebContents webContents, Tab tab) { super(webContents); mTab = tab; + mThemeColor = mTab.getDefaultThemeColor(); + } + + @Override + public void renderProcessGone(boolean processWasOomProtected) { + Log.i(TAG, "renderProcessGone() for tab id: " + mTab.getId() + + ", oom protected: " + Boolean.toString(processWasOomProtected) + + ", already needs reload: " + Boolean.toString(mTab.needsReload())); + // Do nothing for subsequent calls that happen while the tab remains crashed. This + // can occur when the tab is in the background and it shares the renderer with other + // tabs. After the renderer crashes, the WebContents of its tabs are still around + // and they still share the RenderProcessHost. When one of the tabs reloads spawning + // a new renderer for the shared RenderProcessHost and the new renderer crashes + // again, all tabs sharing this renderer will be notified about the crash (including + // potential background tabs that did not reload yet). + if (mTab.needsReload() || mTab.isShowingSadTab()) return; + + int activityState = ApplicationStatus.getStateForActivity( + mTab.getWindowAndroid().getActivity().get()); + int rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_MAX; + if (!processWasOomProtected + || activityState == ActivityState.PAUSED + || activityState == ActivityState.STOPPED + || activityState == ActivityState.DESTROYED) { + // The tab crashed in background or was killed by the OS out-of-memory killer. + //setNeedsReload(true); + mTab.setNeedsReload(true); + if (ApplicationStatus.getStateForApplication() + == ApplicationState.HAS_RUNNING_ACTIVITIES) { + rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP; + } else { + rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP; + } + } else { + rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_SHOWN_IN_FOREGROUND_APP; + mTab.showSadTab(); + // This is necessary to correlate histogram data with stability counts. + UmaSessionStats.logRendererCrash(); + } + RecordHistogram.recordEnumeratedHistogram( + "Tab.RendererCrashStatus", rendererCrashStatus, TAB_RENDERER_CRASH_STATUS_MAX); + + mTab.handleTabCrash(); + + boolean sadTabShown = mTab.isShowingSadTab(); + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onCrash(mTab, sadTabShown); + } + } + + @Override + public void navigationEntryCommitted() { + if (mTab.getNativePage() != null) { + mTab.pushNativePageStateToNavigationEntry(); + } } @Override public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) { + if (isMainFrame) mTab.didFinishPageLoad(); PolicyAuditor auditor = ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor(); auditor.notifyAuditEvent( @@ -36,6 +122,14 @@ @Override public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode, String description, String failingUrl, boolean wasIgnoredByHandler) { + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidFailLoad(mTab, isProvisionalLoad, isMainFrame, errorCode, + description, failingUrl); + } + + if (isMainFrame) mTab.didFailPageLoad(errorCode); + PolicyAuditor auditor = ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor(); auditor.notifyAuditEvent(mTab.getApplicationContext(), AuditEvent.OPEN_URL_FAILURE, @@ -47,18 +141,120 @@ } @Override - public void didCommitProvisionalLoadForFrame( - long frameId, boolean isMainFrame, String url, int transitionType) { + public void didStartProvisionalLoadForFrame(long frameId, long parentFrameId, + boolean isMainFrame, String validatedUrl, boolean isErrorPage, + boolean isIframeSrcdoc) { + if (isMainFrame) mTab.didStartPageLoad(validatedUrl, isErrorPage); + + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidStartProvisionalLoadForFrame(mTab, frameId, parentFrameId, + isMainFrame, validatedUrl, isErrorPage, isIframeSrcdoc); + } + } + + @Override + public void didCommitProvisionalLoadForFrame(long frameId, boolean isMainFrame, String url, + int transitionType) { + if (isMainFrame && UmaUtils.isRunningApplicationStart()) { + // Currently it takes about 2000ms to commit a navigation if the measurement + // begins very early in the browser start. How many buckets (b) are needed to + // explore the _typical_ values with granularity 100ms and a maximum duration + // of 1 minute? + // s^{n+1} / s^{n} = 2100 / 2000 + // s = 1.05 + // s^b = 60000 + // b = ln(60000) / ln(1.05) ~= 225 + RecordHistogram.recordCustomTimesHistogram("Startup.FirstCommitNavigationTime", + System.currentTimeMillis() - UmaUtils.getMainEntryPointTime(), + 1, 60000 /* 1 minute */, TimeUnit.MILLISECONDS, 225); + UmaUtils.setRunningApplicationStart(false); + } + + if (isMainFrame) { + mTab.setIsTabStateDirty(true); + mTab.updateTitle(); + } + + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidCommitProvisionalLoadForFrame( + mTab, frameId, isMainFrame, url, transitionType); + } + + observers.rewind(); + while (observers.hasNext()) { + observers.next().onUrlUpdated(mTab); + } + if (!isMainFrame) return; mTab.handleDidCommitProvisonalLoadForFrame(url, transitionType); + } - if (mTab.getInterceptNavigationDelegate() != null) { - mTab.getInterceptNavigationDelegate().maybeUpdateNavigationHistory(); + @Override + public void didNavigateMainFrame(String url, String baseUrl, + boolean isNavigationToDifferentPage, boolean isFragmentNavigation, int statusCode) { + FullscreenManager fullscreenManager = mTab.getFullscreenManager(); + if (isNavigationToDifferentPage && fullscreenManager != null) { + fullscreenManager.setPersistentFullscreenMode(false); + } + + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidNavigateMainFrame( + mTab, url, baseUrl, isNavigationToDifferentPage, + isFragmentNavigation, statusCode); + } + + mTab.stopSwipeRefreshHandler(); + } + + @Override + public void didFirstVisuallyNonEmptyPaint() { + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().didFirstVisuallyNonEmptyPaint(mTab); + } + } + + @Override + public void didChangeThemeColor(int color) { + int securityLevel = mTab.getSecurityLevel(); + if (securityLevel == ConnectionSecurityLevel.SECURITY_ERROR + || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING + || securityLevel == ConnectionSecurityLevel.SECURITY_POLICY_WARNING) { + color = mTab.getDefaultThemeColor(); + } + if (mTab.isShowingInterstitialPage()) color = mTab.getDefaultThemeColor(); + if (!FeatureUtilities.isDocumentMode(mTab.getApplicationContext()) + && !isThemeColorEnabledInTabbedMode()) { + color = mTab.getDefaultThemeColor(); + } + if (color == Color.TRANSPARENT) color = mTab.getDefaultThemeColor(); + if (mTab.isIncognito()) color = mTab.getDefaultThemeColor(); + color |= 0xFF000000; + if (mTab.getThemeColor() == color) return; + mThemeColor = color; + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidChangeThemeColor(mTab, mTab.getThemeColor()); } } @Override public void didAttachInterstitialPage() { + mTab.getInfoBarContainer().setVisibility(View.INVISIBLE); + mTab.showRenderedPage(); + didChangeThemeColor(mTab.getDefaultThemeColor()); + + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidAttachInterstitialPage(mTab); + } + mTab.notifyLoadProgress(mTab.getProgress()); + + mTab.updateFullscreenEnabledState(); + PolicyAuditor auditor = ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor(); auditor.notifyCertificateFailure(mTab.getWebContents(), mTab.getApplicationContext()); @@ -66,15 +262,47 @@ @Override public void didDetachInterstitialPage() { + mTab.getInfoBarContainer().setVisibility(View.VISIBLE); + didChangeThemeColor(mTab.getWebContents().getThemeColor(mTab.getDefaultThemeColor())); + + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidDetachInterstitialPage(mTab); + } + mTab.notifyLoadProgress(mTab.getProgress()); + + mTab.updateFullscreenEnabledState(); + if (!mTab.maybeShowNativePage(mTab.getUrl(), false)) { mTab.showRenderedPage(); } } @Override + public void didStartNavigationToPendingEntry(String url) { + RewindableIterator<TabObserver> observers = mTab.getTabObservers(); + while (observers.hasNext()) { + observers.next().onDidStartNavigationToPendingEntry(mTab, url); + } + } + + @Override public void destroy() { MediaCaptureNotificationService.updateMediaNotificationForTab( mTab.getApplicationContext(), mTab.getId(), false, false, mTab.getUrl()); super.destroy(); } + + /** + * @return The theme-color for this web contents. + */ + int getThemeColor() { + return mThemeColor; + } + + private static boolean isThemeColorEnabledInTabbedMode() { + CommandLine commandLine = CommandLine.getInstance(); + return ChromeVersionInfo.isLocalBuild() + || commandLine.hasSwitch(ChromeSwitches.ENABLE_THEME_COLOR_IN_TABBED_MODE); + } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java index c3c7767..df87a09 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ActionModeController.ActionBarDelegate; import org.chromium.chrome.browser.util.ColorUtils; @@ -173,8 +172,8 @@ } @Override - public ChromeTab getCurrentTab() { - return ChromeTab.fromTab(getToolbarDataProvider().getTab()); + public Tab getCurrentTab() { + return getToolbarDataProvider().getTab(); } @Override @@ -509,6 +508,9 @@ public void setUrlBarFocus(boolean shouldBeFocused) { } @Override + public void revertChanges() { } + + @Override public long getFirstUrlBarFocusTime() { return 0; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 9b81813..fda31cc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -861,6 +861,14 @@ } /** + * Reverts any pending edits of the location bar and reset to the page state. This does not + * change the focus state of the location bar. + */ + public void revertLocationBarChanges() { + mLocationBar.revertChanges(); + } + + /** * Handle all necessary tasks that can be delayed until initialization completes. * @param activityCreationTimeMs The time of creation for the activity this toolbar belongs to. * @param activityName Simple class name for the activity this toolbar belongs to.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java index f40da6d3..3342bdfa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
@@ -5,14 +5,19 @@ package org.chromium.chrome.browser.toolbar; import android.content.Context; +import android.text.TextUtils; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApplicationStatus; import org.chromium.chrome.R; +import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory; +import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ToolbarModel.ToolbarModelDelegate; +import org.chromium.components.dom_distiller.core.DomDistillerService; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.content_public.browser.WebContents; /** @@ -71,6 +76,39 @@ } @Override + public String getText() { + String displayText = super.getText(); + + if (mTab == null) return displayText; + + String url = mTab.getUrl().trim(); + if (DomDistillerUrlUtils.isDistilledPage(url)) { + if (isStoredArticle(url)) { + DomDistillerService domDistillerService = + DomDistillerServiceFactory.getForProfile(mTab.getProfile()); + String originalUrl = domDistillerService.getUrlForEntry( + DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id")); + displayText = + DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl); + } else if (DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url) != null) { + String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); + displayText = + DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl); + } + } + + return displayText; + } + + private boolean isStoredArticle(String url) { + DomDistillerService domDistillerService = + DomDistillerServiceFactory.getForProfile(mTab.getProfile()); + String entryIdFromUrl = DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id"); + if (TextUtils.isEmpty(entryIdFromUrl)) return false; + return domDistillerService.hasEntry(entryIdFromUrl); + } + + @Override public boolean isIncognito() { return mIsIncognito; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java index 530d345f..0159d18fd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
@@ -11,6 +11,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.os.Handler; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; @@ -261,8 +262,12 @@ } private void updateTabTitle() { - String title = mTab != null ? mTab.getTitle() : null; - if (title == null || title.isEmpty()) { + String title = null; + if (mTab != null) { + title = mTab.getTitle(); + if (TextUtils.isEmpty(title)) title = mTab.getUrl(); + } + if (TextUtils.isEmpty(title)) { title = getContext().getResources().getString(R.string.tab_loading_default_title); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java index 0ba06e9..21a3a49 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java
@@ -5,8 +5,10 @@ package org.chromium.chrome.browser; import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.ChromeTabCreator; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; @@ -14,6 +16,8 @@ import org.chromium.chrome.test.util.TestHttpServerClient; import org.chromium.content_public.browser.LoadUrlParams; +import java.util.concurrent.Callable; + /** * Instrumentation tests for ChromeActivity. */ @@ -85,6 +89,18 @@ assertTrue(tabs[1].isHidden()); } + @SmallTest + public void testTabAnimationsCorrectlyEnabled() { + boolean animationsEnabled = ThreadUtils.runOnUiThreadBlockingNoException( + new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return getActivity().getLayoutManager().animationsEnabled(); + } + }); + assertEquals(animationsEnabled, DeviceClassManager.enableAnimations(getActivity())); + } + @Override public void startMainActivity() throws InterruptedException { startMainActivityOnBlankPage();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java index 367e406..db03cdc4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -29,7 +29,6 @@ import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout; import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack; import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -523,6 +522,6 @@ @Override public Tab createTab(int id, boolean incognito) { - return new ChromeTab(id, incognito); + return new Tab(id, incognito, null); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java index df88fd5..1d556b6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -22,7 +22,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult; -import org.chromium.chrome.browser.tab.ChromeTab; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; @@ -193,7 +192,7 @@ // and NO_OVERRIDE since tab clobbering will eventually lead to NO_OVERRIDE. // in the tab. Rather, we check the final URL to distinguish between // fallback and normal navigation. See crbug.com/487364 for more. - ChromeTab tab = (ChromeTab) latestTabHolder[0]; + Tab tab = latestTabHolder[0]; if (shouldLaunchExternalIntent != (OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT == tab.getInterceptNavigationDelegate()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java index 9e42ff70..191fa0f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java
@@ -13,6 +13,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.tab.ChromeTab; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.test.ChromeTabbedActivityTestBase; import org.chromium.chrome.test.util.ChromeTabUtils; @@ -37,8 +38,8 @@ @Feature({"Browser"}) public void testCreateNewTabInBackgroundLowEnd() throws ExecutionException, InterruptedException { - final ChromeTab fgTab = ChromeTab.fromTab(getActivity().getActivityTab()); - final ChromeTab bgTab = ThreadUtils.runOnUiThreadBlocking(new Callable<ChromeTab>() { + final Tab fgTab = getActivity().getActivityTab(); + final Tab bgTab = ThreadUtils.runOnUiThreadBlocking(new Callable<ChromeTab>() { @Override public ChromeTab call() { return getActivity().getCurrentTabCreator().createNewTab( @@ -73,7 +74,7 @@ @Feature({"Browser"}) public void testCreateNewTabInBackground() throws ExecutionException, InterruptedException { - final ChromeTab fgTab = ChromeTab.fromTab(getActivity().getActivityTab()); + final Tab fgTab = getActivity().getActivityTab(); ChromeTab bgTab = ThreadUtils.runOnUiThreadBlocking(new Callable<ChromeTab>() { @Override public ChromeTab call() { @@ -91,7 +92,7 @@ /** * @return the index of the given tab in the current tab model */ - private int indexOf(ChromeTab tab) { + private int indexOf(Tab tab) { return getActivity().getCurrentTabModel().indexOf(tab); }
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java index 097b702..de8ac3c 100644 --- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java +++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java
@@ -42,7 +42,7 @@ ModelType.TYPED_URLS, })); - protected SyncTestUtil.SyncTestContext mContext; + protected Context mContext; protected SyncController mSyncController; protected FakeServerHelper mFakeServerHelper; protected ProfileSyncService mProfileSyncService; @@ -65,8 +65,7 @@ SigninTestUtil.setUpAuthForTest(getInstrumentation()); super.setUp(); - Context targetContext = getInstrumentation().getTargetContext(); - mContext = new SyncTestUtil.SyncTestContext(targetContext); + mContext = getInstrumentation().getTargetContext(); setUpMockAndroidSyncSettings(); @@ -79,7 +78,7 @@ mFakeServerHelper = FakeServerHelper.get(); } }); - FakeServerHelper.useFakeServer(targetContext); + FakeServerHelper.useFakeServer(mContext); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() {
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS index 9ee5fb9..c555dc7 100644 --- a/chrome/app/OWNERS +++ b/chrome/app/OWNERS
@@ -20,6 +20,8 @@ per-file media_router_strings.grdp*=mfoltz@chromium.org per-file media_router_strings.grdp*=wez@chromium.org -per-file settings_strings.grdp=michaelpg@chromium.org -per-file settings_strings.grdp=stevenjb@chromium.org -per-file settings_strings.grdp=tommycli@chromium.org +per-file settings*strings*=dbeam@chromium.org +per-file settings*strings*=dschuyler@chromium.org +per-file settings*strings*=michaelpg@chromium.org +per-file settings*strings*=stevenjb@chromium.org +per-file settings*strings*=tommycli@chromium.org
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b8d9e5bc..7e7e84e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -15291,6 +15291,13 @@ <message name="IDS_FLAGS_TRACE_EXPORT_EVENTS_TO_ETW_DESRIPTION" desc="Description for the flag to enable exporting of tracing events to ETW."> If enabled, trace events will be exported to the Event Tracing for Windows (ETW) and can then be captured by tools such as UIForETW or Xperf. </message> + + <message name="IDS_FLAGS_MERGE_KEY_CHAR_EVENTS_NAME" desc="Name for the flag to enable/disable merging the key event with char event."> + Enable or disable merging merging the key event (WM_KEY*) with char event (WM_CHAR). + </message> + <message name="IDS_FLAGS_MERGE_KEY_CHAR_EVENTS_DESCRIPTION" desc="Description for the flag to enable/disable merging the key event with char event."> + If disabled, Chrome will handle WM_KEY* and WM_CHAR separatedly. + </message> </if> <if expr="not is_android and not is_ios">
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp index ae39e3c7..62fc3991 100644 --- a/chrome/app/media_router_strings.grdp +++ b/chrome/app/media_router_strings.grdp
@@ -54,6 +54,9 @@ </message> <!-- Issue Messaging --> + <message name="IDS_MEDIA_ROUTER_ISSUE_HEADER" desc="Title of the header in the dialog when there is a user action blocking issue surfaced."> + Error + </message> <message name="IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT" desc="Title of an issue to show when the user attempts to create a route and the Media Router times out while waiting for a route creation response."> <ph name="HOST_NAME">$1<ex>youtube.com</ex></ph> not responding. Unable to cast. </message>
diff --git a/chrome/app/theme/default_100_percent/common/save_password_active.png b/chrome/app/theme/default_100_percent/legacy/save_password_active.png similarity index 100% rename from chrome/app/theme/default_100_percent/common/save_password_active.png rename to chrome/app/theme/default_100_percent/legacy/save_password_active.png Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password_inactive.png b/chrome/app/theme/default_100_percent/legacy/save_password_inactive.png similarity index 100% rename from chrome/app/theme/default_100_percent/common/save_password_inactive.png rename to chrome/app/theme/default_100_percent/legacy/save_password_inactive.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password_active.png b/chrome/app/theme/default_200_percent/legacy/save_password_active.png similarity index 100% rename from chrome/app/theme/default_200_percent/common/save_password_active.png rename to chrome/app/theme/default_200_percent/legacy/save_password_active.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password_inactive.png b/chrome/app/theme/default_200_percent/legacy/save_password_inactive.png similarity index 100% rename from chrome/app/theme/default_200_percent/common/save_password_inactive.png rename to chrome/app/theme/default_200_percent/legacy/save_password_inactive.png Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 17e91d6..a0f0008 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -802,13 +802,14 @@ <structure type="chrome_scaled_image" name="IDR_RELOAD_P" file="common/browser_reload_pressed.png" /> </if> <structure type="chrome_scaled_image" name="IDR_RESTORE_BUTTON_MASK" file="common/restore_button_mask.png" /> - <structure type="chrome_scaled_image" name="IDR_SAD_FAVICON" file="common/favicon_sad_tab.png" /> <if expr="is_macosx"> <structure type="chrome_scaled_image" name="IDR_SAD_TAB" file="legacy/sadtab.png" /> </if> <structure type="chrome_scaled_image" name="IDR_SAFEBROWSING_WARNING" file="common/safebrowsing_warning.png" /> - <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_ACTIVE" file="common/save_password_active.png" /> - <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_INACTIVE" file="common/save_password_inactive.png" /> + <if expr="is_macosx"> + <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_ACTIVE" file="legacy/save_password_active.png" /> + <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_INACTIVE" file="legacy/save_password_inactive.png" /> + </if> <structure type="chrome_scaled_image" name="IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP" file="screen_capture_notification_grip.png" /> <structure type="chrome_scaled_image" name="IDR_SCREENSHOT_NOTIFICATION_ICON" file="common/notification_screenshot_icon.png" /> <if expr="chromeos">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 783d064b..ad677a2 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -112,6 +112,7 @@ "//components/content_settings/core/common", "//components/crx_file", "//components/data_reduction_proxy/core/browser", + "//components/data_usage/core", "//components/data_use_measurement/core", "//components/device_event_log", "//components/domain_reliability", @@ -155,6 +156,7 @@ "//components/startup_metric_utils", "//components/strings", "//components/suggestions", + "//components/sync_bookmarks", "//components/sync_driver", "//components/tracing:startup_tracing", "//components/translate/core/browser",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index cf4b3570..d9e2ac62 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -33,6 +33,7 @@ "+components/crash", "+components/crx_file", "+components/data_reduction_proxy", + "+components/data_usage/core", "+components/data_use_measurement/core", "+components/device_event_log", "+components/dom_distiller", @@ -93,6 +94,7 @@ "+components/startup_metric_utils", "+components/storage_monitor", "+components/suggestions", + "+components/sync_bookmarks", "+components/sync_driver", "+components/syncable_prefs", "+components/tracing",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 63237e4..1024afc 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -871,7 +871,8 @@ IDS_FLAGS_ENABLE_MULTILINGUAL_SPELLCHECKER_NAME, IDS_FLAGS_ENABLE_MULTILINGUAL_SPELLCHECKER_DESCRIPTION, kOsWin | kOsLinux | kOsCrOS, - SINGLE_VALUE_TYPE(switches::kEnableMultilingualSpellChecker)}, + ENABLE_DISABLE_VALUE_TYPE(switches::kEnableMultilingualSpellChecker, + switches::kDisableMultilingualSpellChecker)}, #endif {"enable-scroll-prediction", IDS_FLAGS_ENABLE_SCROLL_PREDICTION_NAME, @@ -1877,13 +1878,13 @@ kOsDesktop, ENABLE_DISABLE_VALUE_TYPE(switches::kV8PacMojoOutOfProcess, switches::kDisableOutOfProcessPac)}, -#if defined(ENABLE_MEDIA_ROUTER) +#if defined(ENABLE_MEDIA_ROUTER) && !defined(OS_ANDROID) {"enable-media-router", IDS_FLAGS_ENABLE_MEDIA_ROUTER_NAME, IDS_FLAGS_ENABLE_MEDIA_ROUTER_DESCRIPTION, - kOsAll, + kOsDesktop, SINGLE_VALUE_TYPE(switches::kEnableMediaRouter)}, -#endif // defined(ENABLE_MEDIA_ROUTER) +#endif // defined(ENABLE_MEDIA_ROUTER) && !defined(OS_ANDROID) // Since Drive Search is not available when app list is disabled, flag guard // enable-drive-search-in-chrome-launcher flag. #if defined(ENABLE_APP_LIST) @@ -2089,6 +2090,12 @@ IDS_FLAGS_TRACE_EXPORT_EVENTS_TO_ETW_DESRIPTION, kOsWin, SINGLE_VALUE_TYPE(switches::kTraceExportEventsToETW)}, + {"merge-key-char-events", + IDS_FLAGS_MERGE_KEY_CHAR_EVENTS_NAME, + IDS_FLAGS_MERGE_KEY_CHAR_EVENTS_DESCRIPTION, + kOsWin, + ENABLE_DISABLE_VALUE_TYPE(switches::kEnableMergeKeyCharEvents, + switches::kDisableMergeKeyCharEvents)}, #endif // defined(OS_WIN) #if defined(ENABLE_BACKGROUND) {"enable-push-api-background-mode",
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 019a403..210bbd9 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -85,6 +85,7 @@ #include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h" #include "chrome/browser/dom_distiller/tab_utils_android.h" #include "chrome/browser/history/android/sqlite_cursor.h" +#include "chrome/browser/interests/android/interests_service.h" #include "chrome/browser/invalidation/invalidation_service_factory_android.h" #include "chrome/browser/lifetime/application_lifetime_android.h" #include "chrome/browser/media/android/remote/record_cast_action.h" @@ -255,6 +256,7 @@ RegisterGeneratedPasswordSavedInfoBarDelegate}, {"HistoryReportJniBridge", history_report::RegisterHistoryReportJniBridge}, {"InfoBarContainer", RegisterInfoBarContainer}, + {"InterestsService", InterestsService::Register}, {"InvalidationServiceFactory", invalidation::InvalidationServiceFactoryAndroid::Register}, {"ShortcutHelper", ShortcutHelper::RegisterShortcutHelper},
diff --git a/chrome/browser/android/media/media_throttle_infobar_delegate.cc b/chrome/browser/android/media/media_throttle_infobar_delegate.cc index 45f8db3..ccafe900 100644 --- a/chrome/browser/android/media/media_throttle_infobar_delegate.cc +++ b/chrome/browser/android/media/media_throttle_infobar_delegate.cc
@@ -52,6 +52,10 @@ return l10n_util::GetStringUTF16(IDS_MEDIA_THROTTLE_INFOBAR_TEXT); } +int MediaThrottleInfoBarDelegate::GetIconId() const { + return IDR_INFOBAR_WARNING; +} + base::string16 MediaThrottleInfoBarDelegate::GetButtonLabel( InfoBarButton button) const { return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
diff --git a/chrome/browser/android/media/media_throttle_infobar_delegate.h b/chrome/browser/android/media/media_throttle_infobar_delegate.h index 5a717cb..d4797f0 100644 --- a/chrome/browser/android/media/media_throttle_infobar_delegate.h +++ b/chrome/browser/android/media/media_throttle_infobar_delegate.h
@@ -31,6 +31,7 @@ // ConfirmInfoBarDelegate: MediaThrottleInfoBarDelegate* AsMediaThrottleInfoBarDelegate() override; base::string16 GetMessageText() const override; + int GetIconId() const override; base::string16 GetButtonLabel(InfoBarButton button) const override; bool Accept() override; bool Cancel() override;
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index 94eed3f..d6fc362 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -935,20 +935,3 @@ bool TabAndroid::RegisterTabAndroid(JNIEnv* env) { return RegisterNativesImpl(env); } - -static void RecordStartupToCommitUma(JNIEnv* env, - const JavaParamRef<jclass>& jcaller) { - // Currently it takes about 2000ms to commit a navigation if the measurement - // begins very early in the browser start. How many buckets (b) are needed to - // explore the _typical_ values with granularity 100ms and a maximum duration - // of 1 minute? - // s^{n+1} / s^{n} = 2100 / 2000 - // s = 1.05 - // s^b = 60000 - // b = ln(60000) / ln(1.05) ~= 225 - UMA_HISTOGRAM_CUSTOM_TIMES("Startup.FirstCommitNavigationTime", - base::Time::Now() - chrome::android::GetMainEntryPointTime(), - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), - 225); -}
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index f5b9d9d..ba4b439 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -26,8 +26,10 @@ #include "chrome/browser/ui/find_bar/find_tab_helper.h" #include "chrome/browser/ui/tab_helpers.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" #include "components/app_modal/javascript_dialog_manager.h" #include "components/infobars/core/infobar.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" @@ -141,6 +143,24 @@ WebContentsDelegateAndroid::CloseContents(web_contents); } +bool TabWebContentsDelegateAndroid::ShouldFocusLocationBarByDefault( + WebContents* source) { + const content::NavigationEntry* entry = + source->GetController().GetActiveEntry(); + if (entry) { + GURL url = entry->GetURL(); + GURL virtual_url = entry->GetVirtualURL(); + if ((url.SchemeIs(chrome::kChromeUINativeScheme) && + url.host() == chrome::kChromeUINewTabHost) || + (virtual_url.SchemeIs(chrome::kChromeUINativeScheme) && + virtual_url.host() == chrome::kChromeUINewTabHost)) { + return true; + } + } + return false; +} + + void TabWebContentsDelegateAndroid::Observe( int type, const content::NotificationSource& source,
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.h b/chrome/browser/android/tab_web_contents_delegate_android.h index af0795db..47b4234 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.h +++ b/chrome/browser/android/tab_web_contents_delegate_android.h
@@ -47,6 +47,7 @@ const content::BluetoothChooser::EventHandler& event_handler, const GURL& origin) override; void CloseContents(content::WebContents* web_contents) override; + bool ShouldFocusLocationBarByDefault(content::WebContents* source) override; blink::WebDisplayMode GetDisplayMode( const content::WebContents* web_contents) const override; void FindReply(content::WebContents* web_contents,
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index f15108f..dba6a13 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -180,6 +180,8 @@ "copyFromDirectoryTreeWithKeyboardShortcut"), TestParameter(IN_GUEST_MODE, "copyFromDirectoryTreeWithKeyboardShortcut"), + TestParameter(NOT_IN_GUEST_MODE, + "copyFromDirectoryTreeWithoutChaningCurrentDirectory"), TestParameter(NOT_IN_GUEST_MODE, "cutFromDirectoryTreeWithContextMenu"), TestParameter(IN_GUEST_MODE, "cutFromDirectoryTreeWithContextMenu"), TestParameter(NOT_IN_GUEST_MODE, @@ -187,9 +189,14 @@ TestParameter(IN_GUEST_MODE, "cutFromDirectoryTreeWithKeyboardShortcut"), TestParameter(NOT_IN_GUEST_MODE, + "cutFromDirectoryTreeWithoutChaningCurrentDirectory"), + TestParameter(NOT_IN_GUEST_MODE, "pasteIntoFolderFromDirectoryTreeWithContextMenu"), TestParameter(IN_GUEST_MODE, "pasteIntoFolderFromDirectoryTreeWithContextMenu"), + TestParameter( + NOT_IN_GUEST_MODE, + "pasteIntoFolderFromDirectoryTreeWithoutChaningCurrentDirectory"), TestParameter(NOT_IN_GUEST_MODE, "renameDirectoryFromDirectoryTreeWithContextMenu"), TestParameter(IN_GUEST_MODE, @@ -198,6 +205,9 @@ "renameDirectoryFromDirectoryTreeWithKeyboardShortcut"), TestParameter(IN_GUEST_MODE, "renameDirectoryFromDirectoryTreeWithKeyboardShortcut"), + TestParameter( + NOT_IN_GUEST_MODE, + "renameDirectoryFromDirectoryTreeWithoutChangingCurrentDirectory"), TestParameter(NOT_IN_GUEST_MODE, "renameDirectoryToEmptyStringFromDirectoryTree"), TestParameter(IN_GUEST_MODE, @@ -209,7 +219,10 @@ TestParameter(NOT_IN_GUEST_MODE, "createDirectoryFromDirectoryTreeWithContextMenu"), TestParameter(NOT_IN_GUEST_MODE, - "createDirectoryFromDirectoryTreeWithKeyboardShortcut"))); + "createDirectoryFromDirectoryTreeWithKeyboardShortcut"), + TestParameter(NOT_IN_GUEST_MODE, + "createDirectoryFromDirectoryTreeWithoutChangingCurrentDi" + "rectory"))); // Fails on official build. http://crbug.com/429294 #if defined(DISABLE_SLOW_FILESAPP_TESTS) || defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/chromeos/first_run/goodies_displayer.cc b/chrome/browser/chromeos/first_run/goodies_displayer.cc index c95401c..b3fc3d4 100644 --- a/chrome/browser/chromeos/first_run/goodies_displayer.cc +++ b/chrome/browser/chromeos/first_run/goodies_displayer.cc
@@ -56,11 +56,6 @@ } // namespace -GoodiesDisplayerTestInfo::GoodiesDisplayerTestInfo() - : days_since_oobe(0), setup_complete(false) {} - -GoodiesDisplayerTestInfo::~GoodiesDisplayerTestInfo() {} - const char GoodiesDisplayer::kGoodiesURL[] = "https://www.google.com/chrome/devices/goodies.html"; @@ -131,5 +126,10 @@ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&Delete)); } +GoodiesDisplayerTestInfo::GoodiesDisplayerTestInfo() + : days_since_oobe(0), setup_complete(false) {} + +GoodiesDisplayerTestInfo::~GoodiesDisplayerTestInfo() {} + } // namespace first_run } // namespace chromeos
diff --git a/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc b/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc new file mode 100644 index 0000000..51625f5 --- /dev/null +++ b/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc
@@ -0,0 +1,135 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/prefs/pref_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/first_run/goodies_displayer.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" + +namespace chromeos { + +class GoodiesDisplayerBrowserTest : public InProcessBrowserTest { + public: + GoodiesDisplayerBrowserTest() {} + + protected: + ~GoodiesDisplayerBrowserTest() override { + first_run::GoodiesDisplayer::Delete(); + } + + // Set up windowless browser and GoodiesDisplayer. |delta_days| is +/- delta + // in days from kMaxDaysAfterOobeForGoodies; <= 0: "show", > 0: "don't show". + Browser* CreateBrowserAndDisplayer(int delta_days) { + // Create a new browser and wait for completion. + ui_test_utils::BrowserAddedObserver browser_added_observer; + Browser* browser = new Browser(Browser::CreateParams( + ProfileManager::GetActiveUserProfile(), chrome::GetActiveDesktop())); + browser_added_observer.WaitForSingleNewBrowser(); + + // Set up Goodies Displayer and set fake age of device. + setup_info_.days_since_oobe = + first_run::GoodiesDisplayer::kMaxDaysAfterOobeForGoodies + delta_days; + first_run::GoodiesDisplayer::InitForTesting(&setup_info_); + WaitForGoodiesSetup(); + + return browser; + } + + // The point of all tests here is to check whether the Goodies tab has been + // correctly opened; this function does the checking. |expected_tabs| is the + // expected number of total tabs; |expected_goodies_tabs| should be 0 or 1. + void ExpectTabCounts(Browser* browser, + int expected_tabs, + int expected_goodies_tabs) { + const int tab_count = browser->tab_strip_model()->count(); + int goodies_tab_count = 0; + for (int index = 0; index < tab_count; index++) { + const std::string tab_url = browser->tab_strip_model() + ->GetWebContentsAt(index)->GetVisibleURL().spec(); + if (tab_url == first_run::GoodiesDisplayer::kGoodiesURL) + ++goodies_tab_count; + } + EXPECT_EQ(expected_tabs, tab_count); + EXPECT_EQ(expected_goodies_tabs, goodies_tab_count); + } + + private: + void WaitForGoodiesSetup() { + if (setup_info_.setup_complete) + return; + + // Wait for GoodiesDisplayer setup completion. The completion callback will + // shut down the message loop. + scoped_refptr<content::MessageLoopRunner> message_loop_runner = + new content::MessageLoopRunner; + setup_info_.on_setup_complete_callback = message_loop_runner->QuitClosure(); + message_loop_runner->Run(); + setup_info_.on_setup_complete_callback.Reset(); + EXPECT_TRUE(setup_info_.setup_complete); + } + + // InProcessBrowserTest overrides. + void SetUpCommandLine(base::CommandLine* command_line) override { + // Don't want a browser window until GoodiesDisplayer is observing. + command_line->AppendSwitch(switches::kNoStartupWindow); + } + + first_run::GoodiesDisplayerTestInfo setup_info_; +}; + +// Tests that the Goodies page is not shown on older device. +IN_PROC_BROWSER_TEST_F(GoodiesDisplayerBrowserTest, OldDeviceNoDisplay) { + EXPECT_TRUE(g_browser_process->local_state()->GetBoolean( + prefs::kCanShowOobeGoodiesPage)); + + ASSERT_EQ(0u, chrome::GetTotalBrowserCount()); + Browser* browser = CreateBrowserAndDisplayer(1); // 1 day too old. + ASSERT_EQ(1u, chrome::GetTotalBrowserCount()); + + AddBlankTabAndShow(browser); + ExpectTabCounts(browser, 1, 0); // Shouldn't show Goodies tab. + EXPECT_FALSE(g_browser_process->local_state()->GetBoolean( + prefs::kCanShowOobeGoodiesPage)); +} + +// Tests that the Goodies page is shown, only once, on non-incognito browser +// when device isn't too old. +IN_PROC_BROWSER_TEST_F(GoodiesDisplayerBrowserTest, DisplayGoodies) { + ASSERT_EQ(0u, chrome::GetTotalBrowserCount()); + Browser* browser = CreateBrowserAndDisplayer(-1); + ASSERT_EQ(1u, chrome::GetTotalBrowserCount()); + + // Shouldn't show Goodies tab in incognito mode. + Browser* incognito_browser = new Browser( + Browser::CreateParams(browser->profile()->GetOffTheRecordProfile(), + chrome::GetActiveDesktop())); + ASSERT_EQ(2u, chrome::GetTotalBrowserCount()); + AddBlankTabAndShow(incognito_browser); + ExpectTabCounts(incognito_browser, 1, 0); + CloseBrowserSynchronously(incognito_browser); + ASSERT_EQ(1u, chrome::GetTotalBrowserCount()); + EXPECT_TRUE(g_browser_process->local_state()->GetBoolean( + prefs::kCanShowOobeGoodiesPage)); + + // First logged-in browser shows Goodies. + AddBlankTabAndShow(browser); + ExpectTabCounts(browser, 2, 1); + EXPECT_FALSE(g_browser_process->local_state()->GetBoolean( + prefs::kCanShowOobeGoodiesPage)); + + // Next time a browser is opened, no Goodies. + Browser* browser2 = CreateBrowser(browser->profile()); + ASSERT_EQ(2u, chrome::GetTotalBrowserCount()); + ExpectTabCounts(browser2, 1, 0); +} + +} // namespace chromeos +
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h index 32cb58e4..7a8bd6b7 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h
@@ -67,15 +67,15 @@ void OnOAuthError() override; void OnNetworkError(int response_code) override; - private: - friend class DeviceOAuth2TokenService; - friend class DeviceOAuth2TokenServiceTest; - class ValidationStatusDelegate { public: virtual void OnValidationCompleted(GoogleServiceAuthError::State error) {} }; + private: + friend class DeviceOAuth2TokenService; + friend class DeviceOAuth2TokenServiceTest; + // Describes the operational state of this object. enum State { // Pending system salt / refresh token load.
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc index d303156..66b5d26c 100644 --- a/chrome/browser/download/notification/download_item_notification.cc +++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -497,7 +497,7 @@ #else SetNotificationVectorIcon( gfx::VectorIconId::WARNING, - model.MightBeMalicious() ? gfx::kErrorRed : gfx::kAmber); + model.MightBeMalicious() ? gfx::kGoogleRed700 : gfx::kGoogleYellow700); #endif return; } @@ -525,7 +525,7 @@ SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_ERROR); #else SetNotificationVectorIcon(gfx::VectorIconId::ERROR_CIRCLE, - gfx::kErrorRed); + gfx::kGoogleRed700); #endif break;
diff --git a/chrome/browser/download/notification/download_notification_manager.cc b/chrome/browser/download/notification/download_notification_manager.cc index 7315ecb..a91349b 100644 --- a/chrome/browser/download/notification/download_notification_manager.cc +++ b/chrome/browser/download/notification/download_notification_manager.cc
@@ -24,9 +24,7 @@ /////////////////////////////////////////////////////////////////////////////// bool DownloadNotificationManager::IsEnabled() { - // Disabled by default. - bool enable_download_notification = false; - + bool enable_download_notification = true; std::string arg = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kEnableDownloadNotification); if (!arg.empty()) {
diff --git a/chrome/browser/extensions/api/dial/dial_service_unittest.cc b/chrome/browser/extensions/api/dial/dial_service_unittest.cc index a43240b..f00edbb 100644 --- a/chrome/browser/extensions/api/dial/dial_service_unittest.cc +++ b/chrome/browser/extensions/api/dial/dial_service_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/extensions/api/dial/dial_device_data.h" #include "chrome/browser/extensions/api/dial/dial_service.h" #include "net/base/ip_endpoint.h" +#include "net/base/net_util.h" #include "net/base/network_interfaces.h" #include "net/log/test_net_log.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index 504754b..13eea4b 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -424,7 +424,9 @@ 1, 1, // received_bytes, total_bytes history_info[i].state, // state content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - content::DOWNLOAD_INTERRUPT_REASON_NONE, + (history_info[i].state != content::DownloadItem::CANCELLED ? + content::DOWNLOAD_INTERRUPT_REASON_NONE : + content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED), false); // opened items->push_back(item); }
diff --git a/chrome/browser/interests/android/interests_service.cc b/chrome/browser/interests/android/interests_service.cc new file mode 100644 index 0000000..15c45e3 --- /dev/null +++ b/chrome/browser/interests/android/interests_service.cc
@@ -0,0 +1,99 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/interests/android/interests_service.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "chrome/browser/interests/interests_fetcher.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_android.h" +#include "jni/InterestsService_jni.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertUTF8ToJavaString; +using base::android::ScopedJavaGlobalRef; +using base::android::ScopedJavaLocalRef; + +namespace { + +ScopedJavaLocalRef<jobjectArray> ConvertInterestsToJava( + JNIEnv* env, + scoped_ptr<std::vector<InterestsFetcher::Interest>> interests) { + if (!interests) + return ScopedJavaLocalRef<jobjectArray>(); + + ScopedJavaLocalRef<jobjectArray> j_interests = + Java_InterestsService_createInterestsArray(env, interests->size()); + + for (size_t i = 0; i != interests->size(); i++) { + const InterestsFetcher::Interest& interest = (*interests)[i]; + ScopedJavaLocalRef<jobject> j_interest = + Java_InterestsService_createInterest( + env, + ConvertUTF8ToJavaString(env, interest.name).obj(), + ConvertUTF8ToJavaString(env, interest.image_url.spec()).obj(), + interest.relevance); + + env->SetObjectArrayElement(j_interests.obj(), i, j_interest.obj()); + } + + return j_interests; +} + +} // namespace + +InterestsService::InterestsService(Profile* profile) + : profile_(profile), weak_ptr_factory_(this) {} + +InterestsService::~InterestsService() {} + +void InterestsService::Destroy(JNIEnv* env, jobject obj) { + delete this; +} + +void InterestsService::GetInterests(JNIEnv* env, + jobject obj, + jobject j_callback_obj) { + ScopedJavaGlobalRef<jobject> j_callback(env, j_callback_obj); + + scoped_ptr<InterestsFetcher> fetcher = + InterestsFetcher::CreateFromProfile(profile_); + InterestsFetcher* fetcher_raw_ptr = fetcher.get(); + + InterestsFetcher::InterestsCallback callback = base::Bind( + &InterestsService::OnObtainedInterests, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(fetcher.Pass()), + j_callback); + + fetcher_raw_ptr->FetchInterests(callback); +} + +// static +bool InterestsService::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +void InterestsService::OnObtainedInterests( + scoped_ptr<InterestsFetcher> fetcher, + const ScopedJavaGlobalRef<jobject>& j_callback, + scoped_ptr<std::vector<InterestsFetcher::Interest>> interests) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> j_interests = + ConvertInterestsToJava(env, interests.Pass()); + Java_GetInterestsCallback_onInterestsAvailableCallback(env, + j_callback.obj(), + j_interests.obj()); +} + +static jlong Init(JNIEnv* env, + const JavaParamRef<jobject>& jobj, + const JavaParamRef<jobject>& jprofile) { + InterestsService* interests_service = + new InterestsService(ProfileAndroid::FromProfileAndroid(jprofile)); + return reinterpret_cast<intptr_t>(interests_service); +}
diff --git a/chrome/browser/interests/android/interests_service.h b/chrome/browser/interests/android/interests_service.h new file mode 100644 index 0000000..d226caa7 --- /dev/null +++ b/chrome/browser/interests/android/interests_service.h
@@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_INTERESTS_ANDROID_INTERESTS_SERVICE_H_ +#define CHROME_BROWSER_INTERESTS_ANDROID_INTERESTS_SERVICE_H_ + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/interests/interests_fetcher.h" + +class Profile; + +// Provides a list of user interests to Java +class InterestsService { + public: + explicit InterestsService(Profile* profile); + virtual ~InterestsService(); + + void Destroy(JNIEnv* env, jobject obj); + static bool Register(JNIEnv* env); + void GetInterests(JNIEnv* env, + jobject obj, + jobject j_callback); + + private: + void OnObtainedInterests( + scoped_ptr<InterestsFetcher> fetcher, + const base::android::ScopedJavaGlobalRef<jobject>& j_callback, + scoped_ptr<std::vector<InterestsFetcher::Interest>> interests); + + Profile* profile_; + + base::WeakPtrFactory<InterestsService> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(InterestsService); +}; + +#endif // CHROME_BROWSER_INTERESTS_ANDROID_INTERESTS_SERVICE_H_
diff --git a/chrome/browser/interests/interests_fetcher.cc b/chrome/browser/interests/interests_fetcher.cc index 5096af2..40fa204 100644 --- a/chrome/browser/interests/interests_fetcher.cc +++ b/chrome/browser/interests/interests_fetcher.cc
@@ -31,10 +31,6 @@ const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; -std::vector<InterestsFetcher::Interest> EmptyResponse() { - return std::vector<InterestsFetcher::Interest>(); -} - GURL GetInterestsURL() { const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -93,7 +89,7 @@ const net::URLRequestStatus& status = source->GetStatus(); if (!status.is_success()) { VLOG(2) << "Network error " << status.error(); - callback_.Run(EmptyResponse()); + callback_.Run(nullptr); return; } @@ -110,7 +106,7 @@ if (response_code != net::HTTP_OK) { VLOG(2) << "HTTP error " << response_code; - callback_.Run(EmptyResponse()); + callback_.Run(nullptr); return; } @@ -143,7 +139,7 @@ const GoogleServiceAuthError& error) { DLOG(WARNING) << error.ToString(); - callback_.Run(EmptyResponse()); + callback_.Run(nullptr); } void InterestsFetcher::StartOAuth2Request() { @@ -162,24 +158,24 @@ net::URLFetcher::Create(0, GetInterestsURL(), net::URLFetcher::GET, this); } -std::vector<InterestsFetcher::Interest> InterestsFetcher::ExtractInterests( - const std::string& response) { +scoped_ptr<std::vector<InterestsFetcher::Interest>> +InterestsFetcher::ExtractInterests(const std::string& response) { scoped_ptr<base::Value> value = base::JSONReader::Read(response); DVLOG(2) << response; const base::DictionaryValue* dict = nullptr; if (!value || !value->GetAsDictionary(&dict)) { DLOG(WARNING) << "Failed to parse global dictionary."; - return EmptyResponse(); + return nullptr; } const base::ListValue* interests_list = nullptr; if (!dict->GetList(kIdInterests, &interests_list)) { DLOG(WARNING) << "Failed to parse interests list."; - return EmptyResponse(); + return nullptr; } - std::vector<Interest> res; + scoped_ptr<std::vector<Interest>> res(new std::vector<Interest>()); for (const base::Value* entry : *interests_list) { const base::DictionaryValue* interest_dict = nullptr; if (!entry->GetAsDictionary(&interest_dict)) { @@ -207,7 +203,7 @@ continue; } - res.push_back(Interest{name, GURL(image_url), relevance}); + res->push_back(Interest{name, GURL(image_url), relevance}); } return res;
diff --git a/chrome/browser/interests/interests_fetcher.h b/chrome/browser/interests/interests_fetcher.h index 4ea31dd..38e1f0f 100644 --- a/chrome/browser/interests/interests_fetcher.h +++ b/chrome/browser/interests/interests_fetcher.h
@@ -45,7 +45,8 @@ double relevance; }; - using InterestsCallback = base::Callback<void(const std::vector<Interest>&)>; + using InterestsCallback = + base::Callback<void(scoped_ptr<std::vector<Interest>>)>; InterestsFetcher(OAuth2TokenService* oauth2_token_service, const std::string& account_id, @@ -73,7 +74,8 @@ scoped_ptr<net::URLFetcher> CreateFetcher(); // Parse the json response. - std::vector<Interest> ExtractInterests(const std::string& response); + scoped_ptr<std::vector<Interest>> + ExtractInterests(const std::string& response); InterestsCallback callback_; scoped_ptr<net::URLFetcher> fetcher_;
diff --git a/chrome/browser/interests/interests_fetcher_unittest.cc b/chrome/browser/interests/interests_fetcher_unittest.cc index 8449d15d..ec67a18b 100644 --- a/chrome/browser/interests/interests_fetcher_unittest.cc +++ b/chrome/browser/interests/interests_fetcher_unittest.cc
@@ -78,8 +78,24 @@ command_line->AppendSwitchASCII(switches::kInterestsURL, kInterestsURL); } - MOCK_METHOD1(OnReceivedInterests, - void(const std::vector<InterestsFetcher::Interest>&)); + MOCK_METHOD0(OnSuccessfulResponse, void()); + MOCK_METHOD0(OnEmptyResponse, void()); + MOCK_METHOD0(OnFailedResponse, void()); + + void OnReceivedInterests( + scoped_ptr<std::vector<InterestsFetcher::Interest>> interests) { + if (!interests) { + OnFailedResponse(); + return; + } + + if (*interests == GetExpectedEmptyResponse()) + OnEmptyResponse(); + else if (*interests == GetExpectedSuccessfulResponse()) + OnSuccessfulResponse(); + else + FAIL() << "Unexpected interests response."; + } protected: void RequestInterests() { @@ -140,39 +156,39 @@ TEST_F(InterestsFetcherTest, EmptyResponse) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())); + EXPECT_CALL(*this, OnEmptyResponse()); IssueAccessTokens(); SendValidResponse(kEmptyResponse); } TEST_F(InterestsFetcherTest, SuccessfullResponse) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedSuccessfulResponse())); + EXPECT_CALL(*this, OnSuccessfulResponse()); IssueAccessTokens(); SendValidResponse(kSuccessfulResponse); } TEST_F(InterestsFetcherTest, FailedResponse) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())); + EXPECT_CALL(*this, OnFailedResponse()); IssueAccessTokens(); SendFailedResponse(); } TEST_F(InterestsFetcherTest, FailedOAuthRequest) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())); + EXPECT_CALL(*this, OnFailedResponse()); IssueAccessTokenErrors(); } TEST_F(InterestsFetcherTest, RetryOnAuthorizationError) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())).Times(0); + EXPECT_CALL(*this, OnEmptyResponse()).Times(0); IssueAccessTokens(); SendAuthorizationError(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())); + EXPECT_CALL(*this, OnEmptyResponse()); IssueAccessTokens(); SendValidResponse(kEmptyResponse); } @@ -180,11 +196,11 @@ TEST_F(InterestsFetcherTest, RetryOnlyOnceOnAuthorizationError) { RequestInterests(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())).Times(0); + EXPECT_CALL(*this, OnEmptyResponse()).Times(0); IssueAccessTokens(); SendAuthorizationError(); - EXPECT_CALL(*this, OnReceivedInterests(GetExpectedEmptyResponse())); + EXPECT_CALL(*this, OnFailedResponse()); IssueAccessTokens(); SendAuthorizationError(); }
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index bfa56f2..165bf37a 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -40,6 +40,7 @@ #include "chrome/common/pref_names.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_usage/core/data_use_aggregator.h" #include "components/net_log/chrome_net_log.h" #include "components/policy/core/common/policy_service.h" #include "components/proxy_config/pref_proxy_config_tracker.h" @@ -567,6 +568,8 @@ extension_event_router_forwarder_; #endif + globals_->data_use_aggregator.reset(new data_usage::DataUseAggregator()); + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432 // is fixed. tracked_objects::ScopedTracker tracking_profile3( @@ -575,6 +578,10 @@ scoped_ptr<ChromeNetworkDelegate> chrome_network_delegate( new ChromeNetworkDelegate(extension_event_router_forwarder(), &system_enable_referrers_)); + // By default, data usage is considered off the record. + chrome_network_delegate->set_data_use_aggregator( + globals_->data_use_aggregator.get(), + true /* is_data_usage_off_the_record */); // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432 // is fixed.
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 22697c6..5ef542f 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -43,6 +43,10 @@ class EventRouterForwarder; } +namespace data_usage { +class DataUseAggregator; +} + namespace net { class CertPolicyEnforcer; class CertVerifier; @@ -122,6 +126,9 @@ Globals(); ~Globals(); + // Global aggregator of data use. It must outlive the + // |system_network_delegate|. + scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator; // The "system" NetworkDelegate, used for Profile-agnostic network events. scoped_ptr<net::NetworkDelegate> system_network_delegate; scoped_ptr<net::HostResolver> host_resolver;
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc index 6afb8c3..545f3b5 100644 --- a/chrome/browser/media/android/router/media_router_android.cc +++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/media/android/router/media_router_android.h" #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/guid.h" #include "base/logging.h" @@ -165,7 +166,16 @@ const MediaRoute::Id& route_id, scoped_ptr<std::vector<uint8>> data, const SendRouteMessageCallback& callback) { - NOTIMPLEMENTED(); + int callback_id = + message_callbacks_.Add(new SendRouteMessageCallback(callback)); + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jstring> jroute_id = + base::android::ConvertUTF8ToJavaString(env, route_id); + ScopedJavaLocalRef<jbyteArray> jbyte_array = + base::android::ToJavaByteArray(env, &((*data)[0]), data->size()); + Java_ChromeMediaRouter_sendBinaryMessage(env, java_media_router_.obj(), + jroute_id.obj(), jbyte_array.obj(), + callback_id); } void MediaRouterAndroid::AddIssue(const Issue& issue) {
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 8fd2976..ef78b9ed 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -36,6 +36,7 @@ #include "chrome/browser/task_management/task_manager_interface.h" #include "chrome/common/pref_names.h" #include "components/content_settings/core/browser/cookie_settings.h" +#include "components/data_usage/core/data_use_aggregator.h" #include "components/domain_reliability/monitor.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" @@ -293,8 +294,10 @@ #endif domain_reliability_monitor_(NULL), experimental_web_platform_features_enabled_( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures)) { + base::CommandLine::ForCurrentProcess() + ->HasSwitch(switches::kEnableExperimentalWebPlatformFeatures)), + data_use_aggregator_(nullptr), + is_data_usage_off_the_record_(true) { DCHECK(enable_referrers); extensions_delegate_.reset( ChromeExtensionsNetworkDelegate::Create(event_router)); @@ -323,6 +326,13 @@ new chrome_browser_net::ConnectInterceptor(predictor)); } +void ChromeNetworkDelegate::set_data_use_aggregator( + data_usage::DataUseAggregator* data_use_aggregator, + bool is_data_usage_off_the_record) { + data_use_aggregator_ = data_use_aggregator; + is_data_usage_off_the_record_ = is_data_usage_off_the_record; +} + // static void ChromeNetworkDelegate::InitializePrefsOnUIThread( BooleanPrefMember* enable_referrers, @@ -491,6 +501,29 @@ task_management::TaskManagerInterface::OnRawBytesRead(request, bytes_received); #endif // defined(ENABLE_TASK_MANAGER) + + if (data_use_aggregator_) { + if (is_data_usage_off_the_record_) { + data_use_aggregator_->ReportOffTheRecordDataUse(0 /* tx_bytes */, + bytes_received); + } else { + data_use_aggregator_->ReportDataUse(request, -1 /* tab_id */, + 0 /* tx_bytes */, bytes_received); + } + } +} + +void ChromeNetworkDelegate::OnNetworkBytesSent(const net::URLRequest& request, + int64_t bytes_sent) { + if (data_use_aggregator_) { + if (is_data_usage_off_the_record_) { + data_use_aggregator_->ReportOffTheRecordDataUse(bytes_sent, + 0 /* rx_bytes */); + } else { + data_use_aggregator_->ReportDataUse(request, -1 /* tab_id */, bytes_sent, + 0 /* rx_bytes */); + } + } } void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 3717a33..43dbc57e 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h
@@ -15,7 +15,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "net/base/network_delegate_impl.h" #if !defined(OS_IOS) @@ -42,6 +41,10 @@ class CookieSettings; } +namespace data_usage { +class DataUseAggregator; +} + namespace domain_reliability { class DomainReliabilityMonitor; } @@ -120,6 +123,10 @@ domain_reliability_monitor_ = monitor; } + void set_data_use_aggregator( + data_usage::DataUseAggregator* data_use_aggregator, + bool is_data_usage_off_the_record); + // Binds the pref members to |pref_service| and moves them to the IO thread. // |enable_referrers| cannot be NULL, the others can. // This method should be called on the UI thread. @@ -155,6 +162,8 @@ void OnResponseStarted(net::URLRequest* request) override; void OnNetworkBytesReceived(const net::URLRequest& request, int64_t bytes_received) override; + void OnNetworkBytesSent(const net::URLRequest& request, + int64_t bytes_sent) override; void OnCompleted(net::URLRequest* request, bool started) override; void OnURLRequestDestroyed(net::URLRequest* request) override; void OnURLRequestJobOrphaned(net::URLRequest* request) override; @@ -180,10 +189,6 @@ const GURL& target_url, const GURL& referrer_url) const override; - void AccumulateContentLength( - int64 received_payload_byte_count, - int64 original_payload_byte_count); - scoped_ptr<ChromeExtensionsNetworkDelegate> extensions_delegate_; void* profile_; @@ -214,6 +219,11 @@ bool experimental_web_platform_features_enabled_; + // Aggregates and reports network usage. + data_usage::DataUseAggregator* data_use_aggregator_; + // Controls whether network usage is reported as being off the record. + bool is_data_usage_off_the_record_; + DISALLOW_COPY_AND_ASSIGN(ChromeNetworkDelegate); };
diff --git a/chrome/browser/net/chrome_network_delegate_unittest.cc b/chrome/browser/net/chrome_network_delegate_unittest.cc index 07dac2b..a4d97af 100644 --- a/chrome/browser/net/chrome_network_delegate_unittest.cc +++ b/chrome/browser/net/chrome_network_delegate_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/net/chrome_network_delegate.h" +#include <stdint.h> + #include "base/command_line.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -20,6 +22,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/common/pref_names.h" +#include "components/data_usage/core/data_use_aggregator.h" #include "components/syncable_prefs/testing_pref_service_syncable.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/content_switches.h" @@ -49,10 +52,11 @@ // request's user data. (As an example suggestions service tag is attached). if // |redirect| is true, it adds necessary socket data to have it follow redirect // before getting the final response. -void RequestURL(net::URLRequestContext* context, - net::MockClientSocketFactory* socket_factory, - bool from_user, - bool redirect) { +scoped_ptr<net::URLRequest> RequestURL( + net::URLRequestContext* context, + net::MockClientSocketFactory* socket_factory, + bool from_user, + bool redirect) { net::MockRead redirect_mock_reads[] = { net::MockRead("HTTP/1.1 302 Found\r\n" "Location: http://bar.com/\r\n\r\n"), @@ -87,8 +91,45 @@ } request->Start(); base::RunLoop().RunUntilIdle(); + return request.Pass(); } +// A fake DataUseAggregator for testing that only counts how many times its +// respective methods have been called. +class FakeDataUseAggregator : public data_usage::DataUseAggregator { + public: + FakeDataUseAggregator() + : on_the_record_tx_bytes_(0), + on_the_record_rx_bytes_(0), + off_the_record_tx_bytes_(0), + off_the_record_rx_bytes_(0) {} + ~FakeDataUseAggregator() override {} + + void ReportDataUse(const net::URLRequest& request, + int32_t tab_id, + int64_t tx_bytes, + int64_t rx_bytes) override { + on_the_record_tx_bytes_ += tx_bytes; + on_the_record_rx_bytes_ += rx_bytes; + } + + void ReportOffTheRecordDataUse(int64_t tx_bytes, int64_t rx_bytes) override { + off_the_record_tx_bytes_ += tx_bytes; + off_the_record_rx_bytes_ += rx_bytes; + } + + int64_t on_the_record_tx_bytes() const { return on_the_record_tx_bytes_; } + int64_t on_the_record_rx_bytes() const { return on_the_record_rx_bytes_; } + int64_t off_the_record_tx_bytes() const { return off_the_record_tx_bytes_; } + int64_t off_the_record_rx_bytes() const { return off_the_record_rx_bytes_; } + + private: + int64_t on_the_record_tx_bytes_; + int64_t on_the_record_rx_bytes_; + int64_t off_the_record_tx_bytes_; + int64_t off_the_record_rx_bytes_; +}; + } // namespace class ChromeNetworkDelegateTest : public testing::Test { @@ -122,6 +163,10 @@ net::NetworkDelegate* network_delegate() { return network_delegate_.get(); } net::MockClientSocketFactory* socket_factory() { return &socket_factory_; } + ChromeNetworkDelegate* chrome_network_delegate() { + return network_delegate_.get(); + } + extensions::EventRouterForwarder* forwarder() { #if defined(ENABLE_EXTENSIONS) return forwarder_.get(); @@ -138,7 +183,7 @@ #endif TestingProfile profile_; BooleanPrefMember enable_referrers_; - scoped_ptr<net::NetworkDelegate> network_delegate_; + scoped_ptr<ChromeNetworkDelegate> network_delegate_; net::MockClientSocketFactory socket_factory_; scoped_ptr<net::TestURLRequestContext> context_; }; @@ -247,6 +292,40 @@ EXPECT_TRUE(network_delegate()->FirstPartyOnlyCookieExperimentEnabled()); } +TEST_F(ChromeNetworkDelegateTest, ReportDataUseToAggregator) { + FakeDataUseAggregator fake_aggregator; + Initialize(); + + chrome_network_delegate()->set_data_use_aggregator( + &fake_aggregator, false /* is_data_usage_off_the_record */); + + scoped_ptr<net::URLRequest> request = + RequestURL(context(), socket_factory(), true, false); + EXPECT_EQ(request->GetTotalSentBytes(), + fake_aggregator.on_the_record_tx_bytes()); + EXPECT_EQ(request->GetTotalReceivedBytes(), + fake_aggregator.on_the_record_rx_bytes()); + EXPECT_EQ(0, fake_aggregator.off_the_record_tx_bytes()); + EXPECT_EQ(0, fake_aggregator.off_the_record_rx_bytes()); +} + +TEST_F(ChromeNetworkDelegateTest, ReportOffTheRecordDataUseToAggregator) { + FakeDataUseAggregator fake_aggregator; + Initialize(); + + chrome_network_delegate()->set_data_use_aggregator( + &fake_aggregator, true /* is_data_usage_off_the_record */); + scoped_ptr<net::URLRequest> request = + RequestURL(context(), socket_factory(), true, false); + + EXPECT_EQ(0, fake_aggregator.on_the_record_tx_bytes()); + EXPECT_EQ(0, fake_aggregator.on_the_record_rx_bytes()); + EXPECT_EQ(request->GetTotalSentBytes(), + fake_aggregator.off_the_record_tx_bytes()); + EXPECT_EQ(request->GetTotalReceivedBytes(), + fake_aggregator.off_the_record_rx_bytes()); +} + class ChromeNetworkDelegateSafeSearchTest : public testing::Test { public: ChromeNetworkDelegateSafeSearchTest()
diff --git a/chrome/browser/notifications/notification_browsertest.cc b/chrome/browser/notifications/notification_browsertest.cc index cbb9a000..a0eabf4 100644 --- a/chrome/browser/notifications/notification_browsertest.cc +++ b/chrome/browser/notifications/notification_browsertest.cc
@@ -45,10 +45,43 @@ #include "ui/base/window_open_disposition.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_observer.h" +#include "ui/message_center/message_center_style.h" +#include "ui/message_center/notification_blocker.h" #include "url/gurl.h" namespace { +class ToggledNotificationBlocker : public message_center::NotificationBlocker { + public: + ToggledNotificationBlocker() + : message_center::NotificationBlocker( + message_center::MessageCenter::Get()), + notifications_enabled_(true) {} + ~ToggledNotificationBlocker() override {} + + void SetNotificationsEnabled(bool enabled) { + if (notifications_enabled_ != enabled) { + notifications_enabled_ = enabled; + NotifyBlockingStateChanged(); + } + } + + // NotificationBlocker overrides: + bool ShouldShowNotificationAsPopup( + const message_center::NotifierId& notifier_id) const override { + return notifications_enabled_; + } + + private: + bool notifications_enabled_; + + DISALLOW_COPY_AND_ASSIGN(ToggledNotificationBlocker); +}; + +} // namespace + +namespace { + const char kExpectedIconUrl[] = "/notifications/no_such_file.png"; class NotificationChangeObserver { @@ -399,6 +432,24 @@ (*notifications.rbegin())->message()); } +IN_PROC_BROWSER_TEST_F(NotificationsTest, NotificationBlockerTest) { + ToggledNotificationBlocker blocker; + + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + + // Creates a simple notification. + AllowAllOrigins(); + ui_test_utils::NavigateToURL(browser(), GetTestPageURL()); + + std::string result = CreateSimpleNotification(browser(), true); + EXPECT_NE("-1", result); + result = CreateSimpleNotification(browser(), true); + EXPECT_NE("-1", result); + + blocker.SetNotificationsEnabled(false); + EXPECT_EQ(0, GetNotificationPopupCount()); +} + IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseNotification) { ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 57ca56c6..1087cbac 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1066,6 +1066,8 @@ network_delegate->set_enable_do_not_track(&enable_do_not_track_); network_delegate->set_force_google_safe_search(&force_google_safesearch_); network_delegate->set_force_youtube_safety_mode(&force_youtube_safety_mode_); + network_delegate->set_data_use_aggregator( + io_thread_globals->data_use_aggregator.get(), IsOffTheRecord()); // NOTE: Proxy service uses the default io thread network delegate, not the // delegate just created.
diff --git a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css index 23922588..ccaaefa3 100644 --- a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css +++ b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css
@@ -3,31 +3,52 @@ * found in the LICENSE file. */ .blocking { + background-color: white; overflow: hidden; - padding-bottom: 15px; - padding-top: 15px; position: relative; text-align: center; } +.blocking > #buttons { + padding-bottom: 24px; + padding-top: 20px; +} + .blocking > div > #title { - color: rgb(150, 150, 150); + color: rgba(0, 0, 0, 0.87); line-height: 1.125em; padding: 10px; vertical-align: middle; } #blocking-icon { + color: rgb(219, 68, 55); height: 75px; - padding: 15px; + padding-top: 24px; width: 75px; } +#close-button::shadow #icon { + height: 15px; + width: 15px; +} + +#header-text { + -webkit-padding-start: 5px; + color: white; + flex-grow: 1; + font-size: 1.25em; + margin: 0; +} + +#issue-header { + background-color: rgb(219, 68, 55); +} + .non-blocking { background-color: rgb(66, 66, 66); - max-height: 65px; overflow: hidden; - padding: 6px; + padding: 16px; } .non-blocking > #buttons { @@ -38,6 +59,9 @@ } .non-blocking > div > #title { - color: white; - padding: 6px 6px 20px 6px; + color: rgba(255, 255, 255, 0.87); } + +paper-button { + margin: 0; +} \ No newline at end of file
diff --git a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html index c2b25085..0909cbe 100644 --- a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html +++ b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html
@@ -2,14 +2,23 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html"> <dom-module name="issue-banner"> <link rel="import" type="css" href="../../media_router_common.css"> <link rel="import" type="css" href="issue_banner.css"> - <template> + <template> + <paper-toolbar id="issue-header" + hidden$="[[computeIsBlockingIssueHidden_(issue)]]"> + <span id="header-text">[[headerText_]]</span> + <paper-icon-button icon="close" id="close-button" + on-click="onCloseButtonClick_"> + </paper-icon-button> + </paper-toolbar> <div class$="[[computeIssueClass_(issue)]]"> <div> <div hidden$="[[computeIsBlockingIssueHidden_(issue)]]"> - <iron-icon icon="report-problem" id="blocking-icon"> + <iron-icon icon="error-outline" id="blocking-icon"> </iron-icon> </div> <div id="title">[[issue.title]]</div>
diff --git a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js index 7466340..c522423 100644 --- a/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js +++ b/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js
@@ -9,6 +9,24 @@ properties: { /** + * The text shown in the default action button. + * @private {string} + */ + defaultActionButtonText_: { + type: String, + value: '', + }, + + /** + * The header text. + * @private {string} + */ + headerText_: { + type: String, + value: loadTimeData.getString('issueHeader'), + }, + + /** * The issue to show. * @type {?media_router.Issue} */ @@ -32,15 +50,6 @@ }, /** - * The text shown in the default action button. - * @private {string} - */ - defaultActionButtonText_: { - type: String, - value: '', - }, - - /** * The text shown in the secondary action button. * @private {string} */ @@ -125,6 +134,15 @@ }, /** + * Handles a click on the close button by firing a close-button-click event. + * + * @private + */ + onCloseButtonClick_: function() { + this.fire('close-button-click'); + }, + + /** * Called when |issue| is updated. This updates the default and secondary * action button text. *
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css index b8df52e3..308d7c1af 100644 --- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css +++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
@@ -13,15 +13,15 @@ .cast-mode-icon, .sink-icon { - -webkit-padding-end: 16px; - -webkit-padding-start: 20px; + -webkit-padding-end: 12px; + -webkit-padding-start: 16px; height: 16px; width: 16px; } #cast-mode-list { - padding-bottom: 8px; - padding-top: 8px; + padding-bottom: 12px; + padding-top: 4px; } #close-button::shadow #icon { @@ -85,7 +85,7 @@ paper-menu { -webkit-user-select: none; - color: rgb(0, 0, 0); + color: rgba(0, 0, 0, 0.87); padding: 0; } @@ -99,10 +99,10 @@ } #share-screen-text { - -webkit-padding-start: 20px; + -webkit-padding-start: 16px; color: rgb(150, 150, 150); - padding-bottom: 8px; - padding-top: 8px; + padding-bottom: 4px; + padding-top: 12px; } .sink-content {
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.css b/chrome/browser/resources/media_router/elements/route_details/route_details.css index dc4d2142..f4a2142 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.css +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.css
@@ -3,9 +3,8 @@ * found in the LICENSE file. */ #close-route-button { + -webkit-padding-end: 24px; background-color: white; - color: rgb(33, 150, 243); - height: 32px; line-height: 32px; margin: 0; text-align: end; @@ -29,7 +28,7 @@ #route-details-header { background-color: rgb(33, 150, 243); - font-size: 1.4em; + font-size: 1.25em; } #route-information {
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.html b/chrome/browser/resources/media_router/elements/route_details/route_details.html index 16d45790..406d7ca 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.html +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.html
@@ -8,7 +8,8 @@ <link rel="import" type="css" href="route_details.css"> <template> <paper-toolbar id="route-details-header"> - <paper-icon-button icon="arrow-back" id="back-button" on-click="back_"> + <paper-icon-button icon="[[arrowIcon_]]" id="back-button" + on-click="back_"> </paper-icon-button> <span id="sink-name">[[sink.name]]</span> <paper-icon-button icon="close" id="close-button" @@ -18,7 +19,8 @@ <div id="route-information" hidden$="[[!isCustomControllerHidden_]]"> <span>[[activityStatus_]]</span> </div> - <extensionview id="custom-controller" hidden$="[[isCustomControllerHidden_]]"> + <extensionview id="custom-controller" + hidden$="[[isCustomControllerHidden_]]"> </extensionview> <paper-button raised id="close-route-button" class="button" on-click="closeRoute_">
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.js b/chrome/browser/resources/media_router/elements/route_details/route_details.js index 43d1aba..f5d072a 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.js +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.js
@@ -18,6 +18,16 @@ }, /** + * The name of the icon used as the back button. This is set once, when + * the |this| is ready. + * @private {string} + */ + arrowIcon_: { + type: String, + value: '', + }, + + /** * The route to show. * @type {?media_router.Route} */ @@ -57,6 +67,12 @@ }, }, + attached: function() { + // isRTL() only works after i18n_template.js runs to set <html dir>. + // Set the back button icon based on text direction. + this.arrowIcon_ = isRTL() ? 'arrow-forward' : 'arrow-back'; + }, + /** * Fires a back-click event. This is called when the back link is clicked. *
diff --git a/chrome/browser/resources/options/supervised_user_import.js b/chrome/browser/resources/options/supervised_user_import.js index 6b9a757..b9030b7 100644 --- a/chrome/browser/resources/options/supervised_user_import.js +++ b/chrome/browser/resources/options/supervised_user_import.js
@@ -77,7 +77,8 @@ $('import-existing-supervised-user-link').hidden = false; options.SupervisedUserListData.requestExistingSupervisedUsers().then( - this.receiveExistingSupervisedUsers_, this.onSigninError_.bind(this)); + this.receiveExistingSupervisedUsers_.bind(this), + this.onSigninError_.bind(this)); options.SupervisedUserListData.addObserver(this); this.updateImportInProgress_(false);
diff --git a/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.html b/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.html new file mode 100644 index 0000000..6a18a85 --- /dev/null +++ b/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.html
@@ -0,0 +1 @@ +<script src="i18n_behavior.js"></script>
diff --git a/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.js b/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.js new file mode 100644 index 0000000..f499e83 --- /dev/null +++ b/chrome/browser/resources/settings/i18n_behavior/i18n_behavior.js
@@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'I18nBehavior' is a behavior to mix in loading of + * internationalization strings. + * + * Example: + * behaviors: [ + * I18nBehavior, + * ], + * + * @group Chrome Settings Elements + */ + +var I18nBehavior = { + /** + * @param {string} id The ID of the string to translate. + * @param {...var_args} Placeholders required by the string ($1-9). + * @return {string} A translated, substituted string. + */ + i18n: function(id, var_args) { + return loadTimeData.getStringF.apply(loadTimeData, arguments); + }, +};
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index f6d5deba..9702180 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -65,6 +65,12 @@ <structure name="IDR_SETTINGS_BASIC_PAGE_CSS" file="basic_page/basic_page.css" type="chrome_html" /> + <structure name="IDR_SETTINGS_I18N_BEHAVIOR_HTML" + file="i18n_behavior/i18n_behavior.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_I18N_BEHAVIOR_JS" + file="i18n_behavior/i18n_behavior.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_ON_STARTUP_PAGE_HTML" file="on_startup_page/on_startup_page.html" type="chrome_html" />
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc index 1d6e1e9..55b87bd 100644 --- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc +++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -135,8 +135,7 @@ // that all languages get deselected and spellchecking gets enabled. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, SpellcheckingDisabledPreferenceMigration) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableMultilingualSpellChecker); + ASSERT_TRUE(chrome::spellcheck_common::IsMultilingualSpellcheckEnabled()); PrefService* prefs = user_prefs::UserPrefs::Get(GetContext()); base::ListValue dictionaries; @@ -155,6 +154,10 @@ // multilingual spellchecking. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, MultilingualToSingleLanguagePreferenceMigration) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableMultilingualSpellChecker); + ASSERT_FALSE(chrome::spellcheck_common::IsMultilingualSpellcheckEnabled()); + PrefService* prefs = user_prefs::UserPrefs::Get(GetContext()); base::ListValue dictionaries; dictionaries.AppendString("en-US"); @@ -175,8 +178,7 @@ // preference stays the same and spellchecking stays enabled. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, MultilingualPreferenceNotMigrated) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableMultilingualSpellChecker); + ASSERT_TRUE(chrome::spellcheck_common::IsMultilingualSpellcheckEnabled()); PrefService* prefs = user_prefs::UserPrefs::Get(GetContext()); base::ListValue dictionaries; @@ -203,6 +205,10 @@ // the preference should not change. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, SingleLanguagePreferenceNotMigrated) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableMultilingualSpellChecker); + ASSERT_FALSE(chrome::spellcheck_common::IsMultilingualSpellcheckEnabled()); + PrefService* prefs = user_prefs::UserPrefs::Get(GetContext()); base::ListValue dictionaries; dictionaries.AppendString("en-US");
diff --git a/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.cc b/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.cc index 697d6b2..e3e6acaf 100644 --- a/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.cc +++ b/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.cc
@@ -5,17 +5,17 @@ #include "chrome/browser/supervised_user/supervised_user_sync_data_type_controller.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "content/public/browser/browser_thread.h" SupervisedUserSyncDataTypeController::SupervisedUserSyncDataTypeController( syncer::ModelType type, + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : sync_driver::UIDataTypeController( content::BrowserThread::GetMessageLoopProxyForThread( content::BrowserThread::UI), - base::Bind(&browser_sync::ChromeReportUnrecoverableError), + error_callback, type, sync_client), profile_(profile) {
diff --git a/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.h b/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.h index 352ca02..e0596b2 100644 --- a/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.h +++ b/chrome/browser/supervised_user/supervised_user_sync_data_type_controller.h
@@ -20,10 +20,10 @@ class SupervisedUserSyncDataTypeController : public sync_driver::UIDataTypeController { public: - SupervisedUserSyncDataTypeController( - syncer::ModelType type, - sync_driver::SyncClient* sync_client, - Profile* profile); + SupervisedUserSyncDataTypeController(syncer::ModelType type, + const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, + Profile* profile); bool ReadyForStart() const override;
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index bb55f5b..106e7e1 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h" +#include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" @@ -17,6 +18,7 @@ #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/themes/theme_syncable_service.h" +#include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "chrome/browser/web_data_service_factory.h" #include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h" @@ -100,6 +102,12 @@ return BookmarkModelFactory::GetForProfile(profile_); } +favicon::FaviconService* ChromeSyncClient::GetFaviconService() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return FaviconServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); +} + history::HistoryService* ChromeSyncClient::GetHistoryService() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return HistoryServiceFactory::GetForProfile( @@ -125,6 +133,10 @@ profile_, ServiceAccessType::EXPLICIT_ACCESS); } +BookmarkUndoService* ChromeSyncClient::GetBookmarkUndoServiceIfExists() { + return BookmarkUndoServiceFactory::GetForProfileIfExists(profile_); +} + base::WeakPtr<syncer::SyncableService> ChromeSyncClient::GetSyncableServiceForType(syncer::ModelType type) { if (!profile_) { // For tests.
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h index d16d0e7..6839c78d 100644 --- a/chrome/browser/sync/chrome_sync_client.h +++ b/chrome/browser/sync/chrome_sync_client.h
@@ -30,10 +30,12 @@ sync_driver::SyncService* GetSyncService() override; PrefService* GetPrefService() override; bookmarks::BookmarkModel* GetBookmarkModel() override; + favicon::FaviconService* GetFaviconService() override; history::HistoryService* GetHistoryService() override; scoped_refptr<password_manager::PasswordStore> GetPasswordStore() override; autofill::PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<autofill::AutofillWebDataService> GetWebDataService() override; + BookmarkUndoService* GetBookmarkUndoServiceIfExists() override; base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType( syncer::ModelType type) override;
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc index 41a2bf2..f5db01f3 100644 --- a/chrome/browser/sync/glue/autofill_data_type_controller.cc +++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/metrics/histogram.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/sync_driver/sync_client.h" @@ -19,13 +18,13 @@ namespace browser_sync { AutofillDataTypeController::AutofillDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client) : NonUIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, sync_client), - sync_client_(sync_client) { -} + sync_client_(sync_client) {} syncer::ModelType AutofillDataTypeController::type() const { return syncer::AUTOFILL;
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.h b/chrome/browser/sync/glue/autofill_data_type_controller.h index f9a4d9b..1d1a10a 100644 --- a/chrome/browser/sync/glue/autofill_data_type_controller.h +++ b/chrome/browser/sync/glue/autofill_data_type_controller.h
@@ -22,7 +22,8 @@ class AutofillDataTypeController : public sync_driver::NonUIDataTypeController { public: - explicit AutofillDataTypeController(sync_driver::SyncClient* sync_client); + explicit AutofillDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client); // NonUIDataTypeController implementation. syncer::ModelType type() const override;
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc index 2762a8a..f65b46b 100644 --- a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc +++ b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
@@ -150,7 +150,8 @@ void SetUp() override { WebDataServiceFactory::GetInstance()->SetTestingFactory( &profile_, MockWebDataServiceWrapperSyncable::Build); - autofill_dtc_ = new AutofillDataTypeController(this); + autofill_dtc_ = + new AutofillDataTypeController(base::Bind(&base::DoNothing), this); } // Passed to AutofillDTC::Start().
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc index 99f0221e..1a0f87f 100644 --- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc +++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/metrics/histogram.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/sync_driver/sync_client.h" @@ -20,10 +19,11 @@ namespace browser_sync { AutofillProfileDataTypeController::AutofillProfileDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client) : NonUIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, sync_client), sync_client_(sync_client), personal_data_(NULL),
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h index cc8cca73..638d575e 100644 --- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h +++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
@@ -21,8 +21,8 @@ : public sync_driver::NonUIDataTypeController, public autofill::PersonalDataManagerObserver { public: - AutofillProfileDataTypeController( - sync_driver::SyncClient* sync_client); + AutofillProfileDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client); // NonUIDataTypeController implementation. syncer::ModelType type() const override;
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc index 7cd3b0a..55424df 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc +++ b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" +#include "components/sync_bookmarks/bookmark_data_type_controller.h" #include "base/bind.h" #include "base/bind_helpers.h"
diff --git a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.h b/chrome/browser/sync/glue/chrome_report_unrecoverable_error.h deleted file mode 100644 index adb0ece2..0000000 --- a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_ -#define CHROME_BROWSER_SYNC_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_ - -namespace browser_sync { - -// On Windows, sends up a minidump via breakpad. On other platforms, -// does nothing. -void ChromeReportUnrecoverableError(); - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_
diff --git a/chrome/browser/sync/glue/extension_data_type_controller.cc b/chrome/browser/sync/glue/extension_data_type_controller.cc index 0b6e429..cbdb600 100644 --- a/chrome/browser/sync/glue/extension_data_type_controller.cc +++ b/chrome/browser/sync/glue/extension_data_type_controller.cc
@@ -6,7 +6,6 @@ #include "base/metrics/histogram.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_system.h" @@ -16,11 +15,12 @@ ExtensionDataTypeController::ExtensionDataTypeController( syncer::ModelType type, + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, type, sync_client), profile_(profile) {
diff --git a/chrome/browser/sync/glue/extension_data_type_controller.h b/chrome/browser/sync/glue/extension_data_type_controller.h index baba9a9..aca48d40 100644 --- a/chrome/browser/sync/glue/extension_data_type_controller.h +++ b/chrome/browser/sync/glue/extension_data_type_controller.h
@@ -21,6 +21,7 @@ public: ExtensionDataTypeController( syncer::ModelType type, // Either EXTENSIONS or APPS. + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile);
diff --git a/chrome/browser/sync/glue/extension_setting_data_type_controller.cc b/chrome/browser/sync/glue/extension_setting_data_type_controller.cc index 79195f5..67cc9db0 100644 --- a/chrome/browser/sync/glue/extension_setting_data_type_controller.cc +++ b/chrome/browser/sync/glue/extension_setting_data_type_controller.cc
@@ -8,7 +8,6 @@ #include "base/metrics/histogram.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/sync_driver/generic_change_processor.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_system.h" @@ -20,11 +19,12 @@ ExtensionSettingDataTypeController::ExtensionSettingDataTypeController( syncer::ModelType type, + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : NonUIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, sync_client), type_(type), profile_(profile) {
diff --git a/chrome/browser/sync/glue/extension_setting_data_type_controller.h b/chrome/browser/sync/glue/extension_setting_data_type_controller.h index c753cd0..d72701ee 100644 --- a/chrome/browser/sync/glue/extension_setting_data_type_controller.h +++ b/chrome/browser/sync/glue/extension_setting_data_type_controller.h
@@ -28,6 +28,7 @@ ExtensionSettingDataTypeController( // Either EXTENSION_SETTINGS or APP_SETTINGS. syncer::ModelType type, + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile);
diff --git a/chrome/browser/sync/glue/history_delete_directives_data_type_controller.cc b/chrome/browser/sync/glue/history_delete_directives_data_type_controller.cc index 846d7ee..821eb54 100644 --- a/chrome/browser/sync/glue/history_delete_directives_data_type_controller.cc +++ b/chrome/browser/sync/glue/history_delete_directives_data_type_controller.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/sync/glue/history_delete_directives_data_type_controller.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/sync_driver/sync_client.h" #include "components/sync_driver/sync_service.h" #include "content/public/browser/browser_thread.h" @@ -15,14 +14,14 @@ HistoryDeleteDirectivesDataTypeController:: HistoryDeleteDirectivesDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client) : sync_driver::UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, syncer::HISTORY_DELETE_DIRECTIVES, sync_client), - sync_client_(sync_client) { -} + sync_client_(sync_client) {} HistoryDeleteDirectivesDataTypeController:: ~HistoryDeleteDirectivesDataTypeController() {
diff --git a/chrome/browser/sync/glue/history_delete_directives_data_type_controller.h b/chrome/browser/sync/glue/history_delete_directives_data_type_controller.h index e1e3481..45f9f12 100644 --- a/chrome/browser/sync/glue/history_delete_directives_data_type_controller.h +++ b/chrome/browser/sync/glue/history_delete_directives_data_type_controller.h
@@ -18,6 +18,7 @@ public sync_driver::SyncServiceObserver { public: HistoryDeleteDirectivesDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client); // UIDataTypeController override.
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc index a6bffcc..15fc959 100644 --- a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc +++ b/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
@@ -14,8 +14,6 @@ #include "base/test/test_timeouts.h" #include "base/thread_task_runner_handle.h" #include "base/tracked_objects.h" -#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h" -#include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/profile_sync_service_mock.h" #include "chrome/test/base/profile_mock.h" @@ -23,6 +21,8 @@ #include "components/sync_driver/data_type_controller_mock.h" #include "components/sync_driver/fake_sync_client.h" #include "components/sync_driver/model_associator_mock.h" +#include "components/sync_driver/non_frontend_data_type_controller.h" +#include "components/sync_driver/non_frontend_data_type_controller_mock.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" #include "sync/internal_api/public/engine/model_safe_worker.h"
diff --git a/chrome/browser/sync/glue/password_data_type_controller.cc b/chrome/browser/sync/glue/password_data_type_controller.cc index 18dd95e..1edc4c8 100644 --- a/chrome/browser/sync/glue/password_data_type_controller.cc +++ b/chrome/browser/sync/glue/password_data_type_controller.cc
@@ -8,7 +8,6 @@ #include "base/metrics/histogram.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/password_manager/core/browser/password_store.h" #include "components/sync_driver/sync_client.h" #include "components/sync_driver/sync_service.h" @@ -19,15 +18,15 @@ namespace browser_sync { PasswordDataTypeController::PasswordDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : NonUIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, sync_client), sync_client_(sync_client), - profile_(profile) { -} + profile_(profile) {} syncer::ModelType PasswordDataTypeController::type() const { return syncer::PASSWORDS;
diff --git a/chrome/browser/sync/glue/password_data_type_controller.h b/chrome/browser/sync/glue/password_data_type_controller.h index 101ab8c..d065d99 100644 --- a/chrome/browser/sync/glue/password_data_type_controller.h +++ b/chrome/browser/sync/glue/password_data_type_controller.h
@@ -27,7 +27,8 @@ class PasswordDataTypeController : public sync_driver::NonUIDataTypeController, public sync_driver::SyncServiceObserver { public: - PasswordDataTypeController(sync_driver::SyncClient* sync_client, + PasswordDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, Profile* profile); // NonFrontendDataTypeController implementation
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller.cc b/chrome/browser/sync/glue/search_engine_data_type_controller.cc index b05f832e..d96d3a2 100644 --- a/chrome/browser/sync/glue/search_engine_data_type_controller.cc +++ b/chrome/browser/sync/glue/search_engine_data_type_controller.cc
@@ -7,7 +7,6 @@ #include "base/metrics/histogram.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "chrome/browser/sync/profile_sync_service.h" #include "content/public/browser/browser_thread.h" #include "sync/api/syncable_service.h" @@ -17,15 +16,15 @@ namespace browser_sync { SearchEngineDataTypeController::SearchEngineDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, syncer::SEARCH_ENGINES, sync_client), - profile_(profile) { -} + profile_(profile) {} TemplateURLService::Subscription* SearchEngineDataTypeController::GetSubscriptionForTesting() {
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller.h b/chrome/browser/sync/glue/search_engine_data_type_controller.h index a40f2b98..2165ad4 100644 --- a/chrome/browser/sync/glue/search_engine_data_type_controller.h +++ b/chrome/browser/sync/glue/search_engine_data_type_controller.h
@@ -22,7 +22,8 @@ class SearchEngineDataTypeController : public sync_driver::UIDataTypeController { public: - SearchEngineDataTypeController(sync_driver::SyncClient* sync_client, + SearchEngineDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, Profile* profile); TemplateURLService::Subscription* GetSubscriptionForTesting();
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc index 77f9e69..ecf708e9 100644 --- a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc +++ b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
@@ -48,8 +48,8 @@ service_.reset(new ProfileSyncServiceMock(&profile_)); // Feed the DTC the profile so it is reused later. // This allows us to control the associated TemplateURLService. - search_engine_dtc_ = - new SearchEngineDataTypeController(this, &profile_); + search_engine_dtc_ = new SearchEngineDataTypeController( + base::Bind(&base::DoNothing), this, &profile_); } void TearDown() override {
diff --git a/chrome/browser/sync/glue/theme_data_type_controller.cc b/chrome/browser/sync/glue/theme_data_type_controller.cc index bfc895b1..38123b8b 100644 --- a/chrome/browser/sync/glue/theme_data_type_controller.cc +++ b/chrome/browser/sync/glue/theme_data_type_controller.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/sync/glue/theme_data_type_controller.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_system.h" @@ -14,15 +13,15 @@ namespace browser_sync { ThemeDataTypeController::ThemeDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile) : UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, syncer::THEMES, sync_client), - profile_(profile) { -} + profile_(profile) {} ThemeDataTypeController::~ThemeDataTypeController() {}
diff --git a/chrome/browser/sync/glue/theme_data_type_controller.h b/chrome/browser/sync/glue/theme_data_type_controller.h index 46108910..091e1cd 100644 --- a/chrome/browser/sync/glue/theme_data_type_controller.h +++ b/chrome/browser/sync/glue/theme_data_type_controller.h
@@ -13,7 +13,8 @@ class ThemeDataTypeController : public sync_driver::UIDataTypeController { public: - ThemeDataTypeController(sync_driver::SyncClient* sync_client, + ThemeDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, Profile* profile); private:
diff --git a/chrome/browser/sync/glue/typed_url_data_type_controller.cc b/chrome/browser/sync/glue/typed_url_data_type_controller.cc index 072e426..689eedf 100644 --- a/chrome/browser/sync/glue/typed_url_data_type_controller.cc +++ b/chrome/browser/sync/glue/typed_url_data_type_controller.cc
@@ -9,7 +9,6 @@ #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "chrome/browser/sync/glue/typed_url_change_processor.h" #include "chrome/common/pref_names.h" #include "components/history/core/browser/history_db_task.h" @@ -62,10 +61,11 @@ } // namespace TypedUrlDataTypeController::TypedUrlDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client) : NonFrontendDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, sync_client), backend_(NULL) { pref_registrar_.Init(sync_client->GetPrefService());
diff --git a/chrome/browser/sync/glue/typed_url_data_type_controller.h b/chrome/browser/sync/glue/typed_url_data_type_controller.h index d5436164..833ec33 100644 --- a/chrome/browser/sync/glue/typed_url_data_type_controller.h +++ b/chrome/browser/sync/glue/typed_url_data_type_controller.h
@@ -11,7 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/prefs/pref_change_registrar.h" #include "base/task/cancelable_task_tracker.h" -#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h" +#include "components/sync_driver/non_frontend_data_type_controller.h" #include "components/sync_driver/sync_api_component_factory.h" namespace history { @@ -25,7 +25,8 @@ // A class that manages the startup and shutdown of typed_url sync. class TypedUrlDataTypeController : public NonFrontendDataTypeController { public: - explicit TypedUrlDataTypeController(sync_driver::SyncClient* sync_client); + explicit TypedUrlDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client); // NonFrontendDataTypeController implementation syncer::ModelType type() const override;
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc index 098bb8a..efba56d6 100644 --- a/chrome/browser/sync/profile_sync_components_factory_impl.cc +++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -11,10 +11,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/autofill_data_type_controller.h" #include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h" -#include "chrome/browser/sync/glue/bookmark_change_processor.h" -#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" -#include "chrome/browser/sync/glue/bookmark_model_associator.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "chrome/browser/sync/glue/history_delete_directives_data_type_controller.h" #include "chrome/browser/sync/glue/local_device_info_provider_impl.h" #include "chrome/browser/sync/glue/password_data_type_controller.h" @@ -26,14 +22,19 @@ #include "chrome/browser/sync/glue/typed_url_data_type_controller.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sessions/session_data_type_controller.h" +#include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/autofill/core/browser/autofill_wallet_data_type_controller.h" #include "components/autofill/core/common/autofill_pref_names.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/dom_distiller/core/dom_distiller_features.h" +#include "components/sync_bookmarks/bookmark_change_processor.h" +#include "components/sync_bookmarks/bookmark_data_type_controller.h" +#include "components/sync_bookmarks/bookmark_model_associator.h" #include "components/sync_driver/data_type_manager_impl.h" #include "components/sync_driver/device_info_data_type_controller.h" +#include "components/sync_driver/glue/chrome_report_unrecoverable_error.h" #include "components/sync_driver/glue/typed_url_model_associator.h" #include "components/sync_driver/proxy_data_type_controller.h" #include "components/sync_driver/sync_client.h" @@ -160,25 +161,26 @@ syncer::ModelTypeSet enabled_types, sync_driver::SyncClient* sync_client) { sync_driver::SyncService* sync_service = sync_client->GetSyncService(); + base::Closure error_callback = + base::Bind(&ChromeReportUnrecoverableError, chrome::GetChannel()); // TODO(stanisc): can DEVICE_INFO be one of disabled datatypes? sync_service->RegisterDataTypeController(new DeviceInfoDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), sync_client, - sync_service->GetLocalDeviceInfoProvider())); + error_callback, sync_client, sync_service->GetLocalDeviceInfoProvider())); // Autofill sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::AUTOFILL)) { sync_service->RegisterDataTypeController( - new AutofillDataTypeController(sync_client)); + new AutofillDataTypeController(error_callback, sync_client)); } // Autofill profile sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::AUTOFILL_PROFILE)) { sync_service->RegisterDataTypeController( - new AutofillProfileDataTypeController(sync_client)); + new AutofillProfileDataTypeController(error_callback, sync_client)); } // Wallet data sync is enabled by default, but behind a syncer experiment @@ -189,8 +191,7 @@ new browser_sync::AutofillWalletDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), - base::Bind(&ChromeReportUnrecoverableError), sync_client, - syncer::AUTOFILL_WALLET_DATA)); + error_callback, sync_client, syncer::AUTOFILL_WALLET_DATA)); } // Wallet metadata sync depends on Wallet data sync and is disabled by @@ -201,8 +202,7 @@ new browser_sync::AutofillWalletDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), - base::Bind(&ChromeReportUnrecoverableError), sync_client, - syncer::AUTOFILL_WALLET_DATA)); + error_callback, sync_client, syncer::AUTOFILL_WALLET_METADATA)); } // Bookmark sync is enabled by default. Register unless explicitly @@ -210,7 +210,7 @@ if (!disabled_types.Has(syncer::BOOKMARKS)) { sync_service->RegisterDataTypeController(new BookmarkDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), sync_client)); + error_callback, sync_client)); } const bool history_disabled = @@ -219,7 +219,7 @@ // or if saving history is disabled. if (!disabled_types.Has(syncer::TYPED_URLS) && !history_disabled) { sync_service->RegisterDataTypeController( - new TypedUrlDataTypeController(sync_client)); + new TypedUrlDataTypeController(error_callback, sync_client)); } // Delete directive sync is enabled by default. Register unless full history @@ -227,7 +227,8 @@ if (!disabled_types.Has(syncer::HISTORY_DELETE_DIRECTIVES) && !history_disabled) { sync_service->RegisterDataTypeController( - new HistoryDeleteDirectivesDataTypeController(sync_client)); + new HistoryDeleteDirectivesDataTypeController(error_callback, + sync_client)); } // Session sync is enabled by default. Register unless explicitly disabled. @@ -242,7 +243,8 @@ // ProfileSyncService at this level. ProfileSyncService* pss = static_cast<ProfileSyncService*>(sync_service); sync_service->RegisterDataTypeController(new SessionDataTypeController( - sync_client, profile_, pss->GetSyncedWindowDelegatesGetter(), + error_callback, sync_client, profile_, + pss->GetSyncedWindowDelegatesGetter(), sync_service->GetLocalDeviceInfoProvider())); } @@ -263,31 +265,31 @@ // disabled. if (!disabled_types.Has(syncer::PASSWORDS)) { sync_service->RegisterDataTypeController( - new PasswordDataTypeController(sync_client, profile_)); + new PasswordDataTypeController(error_callback, sync_client, profile_)); } if (!disabled_types.Has(syncer::PRIORITY_PREFERENCES)) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), - syncer::PRIORITY_PREFERENCES, sync_client)); + error_callback, syncer::PRIORITY_PREFERENCES, sync_client)); } // Article sync is disabled by default. Register only if explicitly enabled. if (dom_distiller::IsEnableSyncArticlesSet()) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), syncer::ARTICLES, - sync_client)); + error_callback, syncer::ARTICLES, sync_client)); } #if defined(ENABLE_SUPERVISED_USERS) sync_service->RegisterDataTypeController( new SupervisedUserSyncDataTypeController(syncer::SUPERVISED_USER_SETTINGS, - sync_client, profile_)); + error_callback, sync_client, + profile_)); sync_service->RegisterDataTypeController( new SupervisedUserSyncDataTypeController( - syncer::SUPERVISED_USER_WHITELISTS, sync_client, profile_)); + syncer::SUPERVISED_USER_WHITELISTS, error_callback, sync_client, + profile_)); #endif } @@ -296,20 +298,22 @@ syncer::ModelTypeSet enabled_types, sync_driver::SyncClient* sync_client) { sync_driver::SyncService* sync_service = sync_client->GetSyncService(); + base::Closure error_callback = + base::Bind(&ChromeReportUnrecoverableError, chrome::GetChannel()); #if defined(ENABLE_EXTENSIONS) // App sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::APPS)) { - sync_service->RegisterDataTypeController( - new ExtensionDataTypeController(syncer::APPS, sync_client, profile_)); + sync_service->RegisterDataTypeController(new ExtensionDataTypeController( + syncer::APPS, error_callback, sync_client, profile_)); } // Extension sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::EXTENSIONS)) { sync_service->RegisterDataTypeController(new ExtensionDataTypeController( - syncer::EXTENSIONS, sync_client, profile_)); + syncer::EXTENSIONS, error_callback, sync_client, profile_)); } #endif @@ -318,23 +322,22 @@ if (!disabled_types.Has(syncer::PREFERENCES)) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), syncer::PREFERENCES, - sync_client)); + error_callback, syncer::PREFERENCES, sync_client)); } #if defined(ENABLE_THEMES) // Theme sync is enabled by default. Register unless explicitly disabled. if (!disabled_types.Has(syncer::THEMES)) { sync_service->RegisterDataTypeController( - new ThemeDataTypeController(sync_client, profile_)); + new ThemeDataTypeController(error_callback, sync_client, profile_)); } #endif // Search Engine sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::SEARCH_ENGINES)) { - sync_service->RegisterDataTypeController( - new SearchEngineDataTypeController(sync_client, profile_)); + sync_service->RegisterDataTypeController(new SearchEngineDataTypeController( + error_callback, sync_client, profile_)); } #if defined(ENABLE_EXTENSIONS) @@ -342,16 +345,16 @@ // disabled. if (!disabled_types.Has(syncer::EXTENSION_SETTINGS)) { sync_service->RegisterDataTypeController( - new ExtensionSettingDataTypeController(syncer::EXTENSION_SETTINGS, - sync_client, profile_)); + new ExtensionSettingDataTypeController( + syncer::EXTENSION_SETTINGS, error_callback, sync_client, profile_)); } // App setting sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::APP_SETTINGS)) { sync_service->RegisterDataTypeController( - new ExtensionSettingDataTypeController(syncer::APP_SETTINGS, - sync_client, profile_)); + new ExtensionSettingDataTypeController( + syncer::APP_SETTINGS, error_callback, sync_client, profile_)); } #endif @@ -359,8 +362,7 @@ if (app_list::switches::IsAppListSyncEnabled()) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), syncer::APP_LIST, - sync_client)); + error_callback, syncer::APP_LIST, sync_client)); } #endif @@ -369,18 +371,18 @@ if (!disabled_types.Has(syncer::DICTIONARY)) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), syncer::DICTIONARY, - sync_client)); + error_callback, syncer::DICTIONARY, sync_client)); } #endif #if defined(ENABLE_SUPERVISED_USERS) sync_service->RegisterDataTypeController( - new SupervisedUserSyncDataTypeController(syncer::SUPERVISED_USERS, - sync_client, profile_)); + new SupervisedUserSyncDataTypeController( + syncer::SUPERVISED_USERS, error_callback, sync_client, profile_)); sync_service->RegisterDataTypeController( new SupervisedUserSyncDataTypeController( - syncer::SUPERVISED_USER_SHARED_SETTINGS, sync_client, profile_)); + syncer::SUPERVISED_USER_SHARED_SETTINGS, error_callback, sync_client, + profile_)); #endif #if defined(OS_CHROMEOS) @@ -388,8 +390,7 @@ !disabled_types.Has(syncer::WIFI_CREDENTIALS)) { sync_service->RegisterDataTypeController(new UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), syncer::WIFI_CREDENTIALS, - sync_client)); + error_callback, syncer::WIFI_CREDENTIALS, sync_client)); } #endif } @@ -401,12 +402,8 @@ const sync_driver::DataTypeEncryptionHandler* encryption_handler, SyncBackendHost* backend, DataTypeManagerObserver* observer) { - return new DataTypeManagerImpl(base::Bind(ChromeReportUnrecoverableError), - debug_info_listener, - controllers, - encryption_handler, - backend, - observer); + return new DataTypeManagerImpl(debug_info_listener, controllers, + encryption_handler, backend, observer); } browser_sync::SyncBackendHost* @@ -531,16 +528,11 @@ #else const bool kExpectMobileBookmarksFolder = false; #endif - BookmarkModelAssociator* model_associator = - new BookmarkModelAssociator(bookmark_model, - profile_, - user_share, - error_handler, - kExpectMobileBookmarksFolder); - BookmarkChangeProcessor* change_processor = - new BookmarkChangeProcessor(profile_, - model_associator, - error_handler); + BookmarkModelAssociator* model_associator = new BookmarkModelAssociator( + bookmark_model, sync_service->GetSyncClient(), user_share, error_handler, + kExpectMobileBookmarksFolder); + BookmarkChangeProcessor* change_processor = new BookmarkChangeProcessor( + sync_service->GetSyncClient(), model_associator, error_handler); return SyncComponents(model_associator, change_processor); }
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index d62419ca..3f42ed2 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc
@@ -38,7 +38,6 @@ #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/glue/sync_backend_host_impl.h" #include "chrome/browser/sync/glue/sync_start_util.h" @@ -71,6 +70,7 @@ #include "components/sync_driver/data_type_controller.h" #include "components/sync_driver/device_info.h" #include "components/sync_driver/favicon_cache.h" +#include "components/sync_driver/glue/chrome_report_unrecoverable_error.h" #include "components/sync_driver/pref_names.h" #include "components/sync_driver/sync_api_component_factory.h" #include "components/sync_driver/sync_client.h" @@ -552,7 +552,8 @@ new syncer::SyncManagerFactory(GetManagerType())) .Pass(), MakeWeakHandle(weak_factory_.GetWeakPtr()), - base::Bind(browser_sync::ChromeReportUnrecoverableError), + base::Bind(browser_sync::ChromeReportUnrecoverableError, + chrome::GetChannel()), network_resources_.get(), saved_nigori_state_.Pass()); } @@ -1847,6 +1848,10 @@ return Difference(preferred_types, failed_types); } +sync_driver::SyncClient* ProfileSyncService::GetSyncClient() const { + return sync_client_.get(); +} + syncer::ModelTypeSet ProfileSyncService::GetPreferredDataTypes() const { const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes(); const syncer::ModelTypeSet preferred_types = @@ -2660,10 +2665,6 @@ backend_->FlushDirectory(); } -sync_driver::SyncClient* ProfileSyncService::GetSyncClient() const { - return sync_client_.get(); -} - base::FilePath ProfileSyncService::GetDirectoryPathForTest() const { return directory_path_; }
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 7d40410..8a29d57 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h
@@ -249,6 +249,7 @@ void RequestStop(SyncStopDataFate data_fate) override; void RequestStart() override; syncer::ModelTypeSet GetActiveDataTypes() const override; + sync_driver::SyncClient* GetSyncClient() const override; syncer::ModelTypeSet GetPreferredDataTypes() const override; void OnUserChoseDatatypes(bool sync_everything, syncer::ModelTypeSet chosen_types) override; @@ -561,9 +562,6 @@ // killed in the near future. void FlushDirectory() const; - // Returns the SyncClient associated with this profile. - sync_driver::SyncClient* GetSyncClient() const; - // Needed to test whether the directory is deleted properly. base::FilePath GetDirectoryPathForTest() const;
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc index dfab2554..2168809 100644 --- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -390,7 +390,6 @@ ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) { return new sync_driver::DataTypeManagerImpl( - base::Closure(), debug_listener, arg1, arg2, @@ -674,9 +673,11 @@ DataTypeController* CreateDataTypeController(syncer::ModelType type) { DCHECK(type == AUTOFILL || type == AUTOFILL_PROFILE); if (type == AUTOFILL) - return new AutofillDataTypeController(sync_client_.get()); + return new AutofillDataTypeController(base::Bind(&base::DoNothing), + sync_client_.get()); else - return new AutofillProfileDataTypeController(sync_client_.get()); + return new AutofillProfileDataTypeController(base::Bind(&base::DoNothing), + sync_client_.get()); } friend class AddAutofillHelper<AutofillEntry>;
diff --git a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc index 9de2529..44effc4 100644 --- a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc
@@ -26,16 +26,19 @@ #include "chrome/browser/bookmarks/chrome_bookmark_client.h" #include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h" #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h" -#include "chrome/browser/sync/glue/bookmark_change_processor.h" -#include "chrome/browser/sync/glue/bookmark_model_associator.h" +#include "chrome/browser/favicon/favicon_service_factory.h" +#include "chrome/browser/history/history_service_factory.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" #include "components/bookmarks/browser/base_bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/managed/managed_bookmark_service.h" #include "components/bookmarks/test/bookmark_test_helpers.h" +#include "components/sync_bookmarks/bookmark_change_processor.h" +#include "components/sync_bookmarks/bookmark_model_associator.h" #include "components/sync_driver/data_type_error_handler.h" #include "components/sync_driver/data_type_error_handler_mock.h" +#include "components/sync_driver/fake_sync_client.h" #include "content/public/test/test_browser_thread_bundle.h" #include "sync/api/sync_error.h" #include "sync/api/sync_merge_result.h" @@ -88,6 +91,28 @@ MakeServerUpdate(trans, &node); } +class TestSyncClient : public sync_driver::FakeSyncClient { + public: + explicit TestSyncClient(Profile* profile) : profile_(profile) {} + + bookmarks::BookmarkModel* GetBookmarkModel() override { + return BookmarkModelFactory::GetForProfile(profile_); + } + + favicon::FaviconService* GetFaviconService() override { + return FaviconServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + } + + history::HistoryService* GetHistoryService() override { + return HistoryServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + } + + private: + Profile* profile_; +}; + // FakeServerChange constructs a list of syncer::ChangeRecords while modifying // the sync model, and can pass the ChangeRecord list to a // syncer::SyncObserver (i.e., the ProfileSyncService) to test the client @@ -350,7 +375,8 @@ enum SaveOption { SAVE_TO_STORAGE, DONT_SAVE_TO_STORAGE }; ProfileSyncServiceBookmarkTest() - : model_(NULL), + : sync_client_(&profile_), + model_(NULL), local_merge_result_(syncer::BOOKMARKS), syncer_merge_result_(syncer::BOOKMARKS) {} @@ -522,10 +548,8 @@ // Set up model associator. model_associator_.reset(new BookmarkModelAssociator( - BookmarkModelFactory::GetForProfile(&profile_), - &profile_, - test_user_share_.user_share(), - &mock_error_handler_, + BookmarkModelFactory::GetForProfile(&profile_), &sync_client_, + test_user_share_.user_share(), &mock_error_handler_, kExpectMobileBookmarks)); local_merge_result_ = syncer::SyncMergeResult(syncer::BOOKMARKS); @@ -568,10 +592,8 @@ ASSERT_TRUE(AssociateModels()); // Set up change processor. - change_processor_.reset( - new BookmarkChangeProcessor(&profile_, - model_associator_.get(), - &mock_error_handler_)); + change_processor_.reset(new BookmarkChangeProcessor( + &sync_client_, model_associator_.get(), &mock_error_handler_)); change_processor_->Start(test_user_share_.user_share()); } @@ -781,6 +803,7 @@ protected: TestingProfile profile_; + TestSyncClient sync_client_; BookmarkModel* model_; syncer::TestUserShare test_user_share_; scoped_ptr<BookmarkChangeProcessor> change_processor_; @@ -2569,7 +2592,7 @@ // Recreate the change processor then update that bookmark. Sync should // receive the update call and gracefully treat that as if it were an add. change_processor_.reset(new BookmarkChangeProcessor( - &profile_, model_associator_.get(), &mock_error_handler_)); + &sync_client_, model_associator_.get(), &mock_error_handler_)); change_processor_->Start(test_user_share_.user_share()); model_->SetTitle(node, base::ASCIIToUTF16("title2")); ExpectModelMatch();
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc index ccc86b92..03d3f8be 100644 --- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -269,7 +269,8 @@ sync_service_ = TestProfileSyncService::BuildAutoStartAsyncInit(profile_, callback); TypedUrlDataTypeController* data_type_controller = - new TypedUrlDataTypeController(sync_service_->GetSyncClient()); + new TypedUrlDataTypeController(base::Bind(&base::DoNothing), + sync_service_->GetSyncClient()); ProfileSyncComponentsFactoryMock* components = sync_service_->GetSyncApiComponentFactoryMock(); EXPECT_CALL(*components, CreateTypedUrlSyncComponents(_, _, _)).
diff --git a/chrome/browser/sync/sessions/session_data_type_controller.cc b/chrome/browser/sync/sessions/session_data_type_controller.cc index fb45a1e0..a5a08f9c 100644 --- a/chrome/browser/sync/sessions/session_data_type_controller.cc +++ b/chrome/browser/sync/sessions/session_data_type_controller.cc
@@ -7,7 +7,6 @@ #include "base/prefs/pref_service.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "chrome/common/pref_names.h" #include "components/sync_driver/glue/synced_window_delegate.h" #include "components/sync_driver/sessions/synced_window_delegates_getter.h" @@ -22,13 +21,14 @@ namespace browser_sync { SessionDataTypeController::SessionDataTypeController( + const base::Closure& error_callback, sync_driver::SyncClient* sync_client, Profile* profile, SyncedWindowDelegatesGetter* synced_window_getter, sync_driver::LocalDeviceInfoProvider* local_device) : UIDataTypeController( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), + error_callback, syncer::SESSIONS, sync_client), sync_client_(sync_client),
diff --git a/chrome/browser/sync/sessions/session_data_type_controller.h b/chrome/browser/sync/sessions/session_data_type_controller.h index 6bb53973..95cadda 100644 --- a/chrome/browser/sync/sessions/session_data_type_controller.h +++ b/chrome/browser/sync/sessions/session_data_type_controller.h
@@ -23,7 +23,8 @@ class SessionDataTypeController : public sync_driver::UIDataTypeController, public content::NotificationObserver { public: - SessionDataTypeController(sync_driver::SyncClient* sync_client, + SessionDataTypeController(const base::Closure& error_callback, + sync_driver::SyncClient* sync_client, Profile* profile, SyncedWindowDelegatesGetter* synced_window_getter, sync_driver::LocalDeviceInfoProvider* local_device);
diff --git a/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc b/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc index 9f3eb29..2d7ab51 100644 --- a/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc +++ b/chrome/browser/sync/sessions/session_data_type_controller_unittest.cc
@@ -114,10 +114,8 @@ "device_id")); controller_ = new SessionDataTypeController( - this, - &profile_, - synced_window_getter_.get(), - local_device_.get()); + base::Bind(&base::DoNothing), this, &profile_, + synced_window_getter_.get(), local_device_.get()); load_finished_ = false; last_type_ = syncer::UNSPECIFIED;
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc index 8526cac..aa9aba7 100644 --- a/chrome/browser/sync/test/integration/bookmarks_helper.cc +++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -24,7 +24,8 @@ #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/glue/bookmark_change_processor.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/test/integration/await_match_status_change_checker.h" #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" @@ -42,6 +43,7 @@ #include "components/history/core/browser/history_db_task.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" +#include "components/sync_bookmarks/bookmark_change_processor.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -260,8 +262,10 @@ favicon_service->SetFavicons( node->url(), icon_url, favicon_base::FAVICON, image); } else { + ProfileSyncService* pss = + ProfileSyncServiceFactory::GetForProfile(profile); browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( - node, profile, icon_url, image.As1xPNGBytes()); + node, pss->GetSyncClient(), icon_url, image.As1xPNGBytes()); } // Wait for the favicon for |node| to be invalidated.
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h index edd4e54..5b7cb99fa 100644 --- a/chrome/browser/sync/test_profile_sync_service.h +++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -23,12 +23,7 @@ class ProfileSyncComponentsFactoryMock; ACTION(ReturnNewDataTypeManager) { - return new sync_driver::DataTypeManagerImpl(base::Closure(), - arg0, - arg1, - arg2, - arg3, - arg4); + return new sync_driver::DataTypeManagerImpl(arg0, arg1, arg2, arg3, arg4); } namespace browser_sync {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 42718b9..8811af5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -94,6 +94,7 @@ "//chrome/installer/util", "//components/autofill/content/browser:risk_proto", "//components/bubble:bubble", + "//components/crash/core/browser", "//components/net_log", "//components/page_load_metrics/browser", "//components/power",
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc index 01c7ba5..730e924 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_types.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc
@@ -102,7 +102,7 @@ return type_ == DialogNotification::WALLET_USAGE_CONFIRMATION; } -SkColor const kWarningColor = gfx::kErrorRed; +SkColor const kWarningColor = gfx::kGoogleRed700; SkColor const kLightShadingColor = SkColorSetARGB(7, 0, 0, 0); SkColor const kSubtleBorderColor = SkColorSetARGB(10, 0, 0, 0);
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index 957ba0c5..e438e18b 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -172,6 +172,11 @@ // in visible state when the following is |YES|. BOOL barVisibilityUpdatesEnabled_; + // If this ivar is set to YES, layoutSubviews calls will be ignored. This is + // used in fullscreen transition to prevent spurious resize messages from + // being sent to the renderer, which causes the transition to be janky. + BOOL blockLayoutSubviews_; + // When going fullscreen for a tab, we need to store the URL and the // fullscreen type, since we can't show the bubble until // -windowDidEnterFullScreen: gets called.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index a0154399..67fb9bf 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -421,6 +421,8 @@ extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS, windowShim_.get())); + blockLayoutSubviews_ = NO; + // We are done initializing now. initializing_ = NO; } @@ -691,6 +693,10 @@ // Called when we have been unminimized. - (void)windowDidDeminiaturize:(NSNotification *)notification { + // Make sure the window's show_state (which is now ui::SHOW_STATE_NORMAL) + // gets saved. + [self saveWindowPositionIfNeeded]; + // Let the selected RenderWidgetHostView know, so that it can tell plugins. if (WebContents* contents = [self webContents]) { if (RenderWidgetHostView* rwhv = contents->GetRenderWidgetHostView()) @@ -1966,7 +1972,13 @@ - (void)enterWebContentFullscreenForURL:(const GURL&)url bubbleType:(ExclusiveAccessBubbleType)bubbleType { - [self enterImmersiveFullscreen]; + // HTML5 Fullscreen should only use AppKit fullscreen in 10.10+. + if (chrome::mac::SupportsSystemFullscreen() && + base::mac::IsOSYosemiteOrLater()) + [self enterAppKitFullscreen]; + else + [self enterImmersiveFullscreen]; + if (!url.is_empty()) [self updateFullscreenExitBubbleURL:url bubbleType:bubbleType]; }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index f87ccea..b096a20 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -179,6 +179,14 @@ - (void)windowDidEnterFullScreen:(NSNotification*)notification; - (void)windowDidExitFullScreen:(NSNotification*)notification; - (void)windowWillExitFullScreen:(NSNotification*)notification; + +// Adjusts the UI and destroys the exit bubble when we are exiting fullscreen. +- (void)adjustUIForExitingFullscreen; + +// Determines the appropriate sliding fullscreen style and adjusts the UI to +// it when we are entering fullscreen. +- (void)adjustUIForEnteringFullscreen; + #endif @end // @interface BrowserWindowController(Private)
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 876f3dc..4bf62acc 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -6,6 +6,7 @@ #include <cmath> +#import "base/auto_reset.h" #include "base/command_line.h" #include "base/mac/bind_objc_block.h" #include "base/mac/foundation_util.h" @@ -216,6 +217,9 @@ } - (void)layoutSubviews { + if (blockLayoutSubviews_) + return; + // Suppress title drawing if necessary. if ([self.window respondsToSelector:@selector(setShouldHideTitle:)]) [(id)self.window setShouldHideTitle:![self hasTitleBar]]; @@ -684,21 +688,18 @@ enteringAppKitFullscreenOnPrimaryScreen_ = [[[self window] screen] isEqual:[[NSScreen screens] firstObject]]; - fullscreen_mac::SlidingStyle style; - if (browser_->exclusive_access_manager() - ->fullscreen_controller() - ->IsWindowFullscreenForTabOrPending()) { - style = fullscreen_mac::OMNIBOX_TABS_NONE; - } else if (enteringPresentationMode_) { - style = fullscreen_mac::OMNIBOX_TABS_HIDDEN; - } else { - style = fullscreen_mac::OMNIBOX_TABS_PRESENT; - } - - [self adjustUIForSlidingFullscreenStyle:style]; + // If we are using custom fullscreen animations, the layout will resize + // in startCustomAnimationToEnterFullScreenWithDuration. In order to prevent + // multiple resizing messages from being sent to the renderer, we should call + // adjustUIForEnteringFullscreen after the layout gets resized. + if ([self shouldUseCustomAppKitFullscreenTransition:YES]) + blockLayoutSubviews_ = YES; + else + [self adjustUIForEnteringFullscreen]; } - (void)windowDidEnterFullScreen:(NSNotification*)notification { + blockLayoutSubviews_ = NO; fullscreenTransition_.reset(); // In Yosemite, some combination of the titlebar and toolbar always show in @@ -755,8 +756,13 @@ [self registerForContentViewResizeNotifications]; exitingAppKitFullscreen_ = YES; - [self destroyFullscreenExitBubbleIfNecessary]; - [self adjustUIForExitingFullscreenAndStopOmniboxSliding]; + // Like windowWillEnterFullScreen, if we use custom animations, + // adjustUIForExitingFullscreen should be called after the layout resizes in + // startCustomAnimationToExitFullScreenWithDuration. + if ([self shouldUseCustomAppKitFullscreenTransition:NO]) + blockLayoutSubviews_ = YES; + else + [self adjustUIForExitingFullscreen]; } - (void)windowDidExitFullScreen:(NSNotification*)notification { @@ -765,19 +771,19 @@ if (notification) // For System Fullscreen when non-nil. [self deregisterForContentViewResizeNotifications]; - // Since the content view was forcefully resized during the transition, we - // want to ensure that the subviews are layout correctly after it ended. - [self layoutSubviews]; browser_->WindowFullscreenStateChanged(); exitingAppKitFullscreen_ = NO; fullscreenTransition_.reset(); + + blockLayoutSubviews_ = NO; } - (void)windowDidFailToEnterFullScreen:(NSWindow*)window { [self deregisterForContentViewResizeNotifications]; enteringAppKitFullscreen_ = NO; fullscreenTransition_.reset(); + blockLayoutSubviews_ = NO; [self adjustUIForExitingFullscreenAndStopOmniboxSliding]; } @@ -785,10 +791,31 @@ [self deregisterForContentViewResizeNotifications]; exitingAppKitFullscreen_ = NO; fullscreenTransition_.reset(); + blockLayoutSubviews_ = NO; // Force a relayout to try and get the window back into a reasonable state. [self layoutSubviews]; } +- (void)adjustUIForExitingFullscreen { + [self destroyFullscreenExitBubbleIfNecessary]; + [self adjustUIForExitingFullscreenAndStopOmniboxSliding]; +} + +- (void)adjustUIForEnteringFullscreen { + fullscreen_mac::SlidingStyle style; + if (browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()) { + style = fullscreen_mac::OMNIBOX_TABS_NONE; + } else if (enteringPresentationMode_) { + style = fullscreen_mac::OMNIBOX_TABS_HIDDEN; + } else { + style = fullscreen_mac::OMNIBOX_TABS_PRESENT; + } + + [self adjustUIForSlidingFullscreenStyle:style]; +} + - (void)enableBarVisibilityUpdates { // Early escape if there's nothing to do. if (barVisibilityUpdatesEnabled_) @@ -1137,6 +1164,9 @@ startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration { DCHECK([window isEqual:self.window]); [fullscreenTransition_ startCustomFullScreenAnimationWithDuration:duration]; + + base::AutoReset<BOOL> autoReset(&blockLayoutSubviews_, NO); + [self adjustUIForEnteringFullscreen]; } - (void)window:(NSWindow*)window @@ -1144,6 +1174,9 @@ DCHECK([window isEqual:self.window]); [fullscreenTransition_ startCustomFullScreenAnimationWithDuration:duration]; + + base::AutoReset<BOOL> autoReset(&blockLayoutSubviews_, NO); + [self adjustUIForExitingFullscreen]; } - (BOOL)shouldConstrainFrameRect {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index 9fe0804d..4ba29c1 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -56,6 +56,7 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/user_metrics.h" #include "content/public/browser/web_contents.h" +#include "grit/components_scaled_resources.h" #include "grit/theme_resources.h" #include "skia/ext/skia_utils_mac.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h" @@ -1578,8 +1579,9 @@ ResourceBundle::GetSharedInstance().GetNativeImageNamed( IDR_THROBBER).CopyNSImage(); static NSImage* sadFaviconImage = - ResourceBundle::GetSharedInstance().GetNativeImageNamed( - IDR_SAD_FAVICON).CopyNSImage(); + ResourceBundle::GetSharedInstance() + .GetNativeImageNamed(IDR_CRASH_SAD_FAVICON) + .CopyNSImage(); // Take closing tabs into account. NSInteger index = [self indexFromModelIndex:modelIndex];
diff --git a/chrome/browser/ui/global_error/global_error.cc b/chrome/browser/ui/global_error/global_error.cc index ca4b11e..098d99b0 100644 --- a/chrome/browser/ui/global_error/global_error.cc +++ b/chrome/browser/ui/global_error/global_error.cc
@@ -29,8 +29,8 @@ return ResourceBundle::GetSharedInstance().GetNativeImageNamed( IDR_INPUT_ALERT_MENU); #else - return gfx::Image( - gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 18, gfx::kAmber)); + return gfx::Image(gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 18, + gfx::kGoogleYellow700)); #endif }
diff --git a/chrome/browser/ui/passwords/manage_passwords_icon.h b/chrome/browser/ui/passwords/manage_passwords_icon.h index d4760d4..e9329c7e 100644 --- a/chrome/browser/ui/passwords/manage_passwords_icon.h +++ b/chrome/browser/ui/passwords/manage_passwords_icon.h
@@ -6,18 +6,20 @@ #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_H_ #include "base/basictypes.h" +#include "chrome/browser/ui/passwords/manage_passwords_icon_view.h" #include "components/password_manager/core/common/password_manager_ui.h" -// Abstract base class for platform-specific password management icon views. -class ManagePasswordsIcon { +// Base class for platform-specific password management icon views. +// TODO(estade): remove this class from Cocoa as it has been from Views. +class ManagePasswordsIcon : public ManagePasswordsIconView { public: // Get/set the icon's state. Implementations of this class must implement // SetStateInternal to do reasonable platform-specific things to represent // the icon's state to the user. - void SetState(password_manager::ui::State state); + void SetState(password_manager::ui::State state) override; password_manager::ui::State state() const { return state_; } - void SetActive(bool active); + void SetActive(bool active) override; bool active() const { return active_; } protected:
diff --git a/chrome/browser/ui/passwords/manage_passwords_icon_mock.cc b/chrome/browser/ui/passwords/manage_passwords_icon_mock.cc deleted file mode 100644 index 1b96561..0000000 --- a/chrome/browser/ui/passwords/manage_passwords_icon_mock.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/passwords/manage_passwords_icon_mock.h" - -ManagePasswordsIconMock::ManagePasswordsIconMock() { -} - -ManagePasswordsIconMock::~ManagePasswordsIconMock() { -} - -void ManagePasswordsIconMock::UpdateVisibleUI() { -} - -void ManagePasswordsIconMock::OnChangingState() { -}
diff --git a/chrome/browser/ui/passwords/manage_passwords_icon_mock.h b/chrome/browser/ui/passwords/manage_passwords_icon_mock.h deleted file mode 100644 index 3801a45..0000000 --- a/chrome/browser/ui/passwords/manage_passwords_icon_mock.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_MOCK_H_ -#define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_MOCK_H_ - -#include "chrome/browser/ui/passwords/manage_passwords_icon.h" - -// Mock ManagePasswordsIcon, for testing purposes only. -class ManagePasswordsIconMock : public ManagePasswordsIcon { - public: - ManagePasswordsIconMock(); - virtual ~ManagePasswordsIconMock(); - - protected: - // ManagePasswordsIcon: - void UpdateVisibleUI() override; - void OnChangingState() override; - - private: - DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconMock); -}; - -#endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_MOCK_H_
diff --git a/chrome/browser/ui/passwords/manage_passwords_icon_view.h b/chrome/browser/ui/passwords/manage_passwords_icon_view.h new file mode 100644 index 0000000..7645742 --- /dev/null +++ b/chrome/browser/ui/passwords/manage_passwords_icon_view.h
@@ -0,0 +1,23 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_ +#define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_ + +#include "base/basictypes.h" +#include "components/password_manager/core/common/password_manager_ui.h" + +// An interface for updating the passwords icon in the location bar. +class ManagePasswordsIconView { + public: + ManagePasswordsIconView() {} + + virtual void SetState(password_manager::ui::State state) = 0; + virtual void SetActive(bool active) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconView); +}; + +#endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.h b/chrome/browser/ui/passwords/manage_passwords_test.h index b9e8e07e..a17a2e5 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.h +++ b/chrome/browser/ui/passwords/manage_passwords_test.h
@@ -15,7 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" class ManagePasswordsUIController; -class ManagePasswordsIcon; +class ManagePasswordsIconView; class GURL; // Test class for the various password management view bits and pieces. Sets @@ -30,7 +30,7 @@ void SetUpOnMainThread() override; // Get the icon view for the current WebContents. - virtual ManagePasswordsIcon* view() = 0; + virtual ManagePasswordsIconView* view() = 0; // Execute the browser command to open the manage passwords bubble. void ExecuteManagePasswordsCommand();
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 40dec22..bac8325 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -30,7 +30,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/password_manager/account_chooser_dialog_android.h" #else -#include "chrome/browser/ui/passwords/manage_passwords_icon.h" +#include "chrome/browser/ui/passwords/manage_passwords_icon_view.h" #endif using autofill::PasswordFormMap; @@ -364,7 +364,7 @@ #if !defined(OS_ANDROID) void ManagePasswordsUIController::UpdateIconAndBubbleState( - ManagePasswordsIcon* icon) { + ManagePasswordsIconView* icon) { if (should_pop_up_bubble_) { // We must display the icon before showing the bubble, as the bubble would // be otherwise unanchored.
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h index c482ffbe..924a996 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -24,7 +24,7 @@ class PasswordFormManager; } -class ManagePasswordsIcon; +class ManagePasswordsIconView; // Per-tab class to control the Omnibox password icon and bubble. class ManagePasswordsUIController @@ -119,7 +119,7 @@ #if !defined(OS_ANDROID) // Set the state of the Omnibox icon, and possibly show the associated bubble // without user interaction. - virtual void UpdateIconAndBubbleState(ManagePasswordsIcon* icon); + virtual void UpdateIconAndBubbleState(ManagePasswordsIconView* icon); #endif // Called from the model when the bubble is displayed.
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index 1732760f..4be1ec6 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -24,8 +24,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if !defined(OS_ANDROID) -#include "chrome/browser/ui/passwords/manage_passwords_icon.h" -#include "chrome/browser/ui/passwords/manage_passwords_icon_mock.h" +#include "chrome/browser/ui/passwords/manage_passwords_icon_view.h" #endif using ::testing::ElementsAre; @@ -36,6 +35,28 @@ const int64 kSlowNavigationDelayInMS = 6000; const int64 kQuickNavigationDelayInMS = 500; +#if !defined(OS_ANDROID) +class TestManagePasswordsIconView : public ManagePasswordsIconView { + public: + TestManagePasswordsIconView() {} + + void SetState(password_manager::ui::State state) override { + state_ = state; + } + password_manager::ui::State state() { return state_; } + void SetActive(bool active) override { + active_ = active; + } + bool active() { return active_; } + + private: + password_manager::ui::State state_; + bool active_; + + DISALLOW_COPY_AND_ASSIGN(TestManagePasswordsIconView); +}; +#endif + // This sublass is used to disable some code paths which are not essential for // testing. class TestManagePasswordsUIController : public ManagePasswordsUIController { @@ -134,9 +155,9 @@ void ExpectIconStateIs(password_manager::ui::State state) { // No op on Android, where there is no icon. #if !defined(OS_ANDROID) - ManagePasswordsIconMock mock; - controller()->UpdateIconAndBubbleState(&mock); - EXPECT_EQ(state, mock.state()); + TestManagePasswordsIconView view; + controller()->UpdateIconAndBubbleState(&view); + EXPECT_EQ(state, view.state()); #endif }
diff --git a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc index 4d3b560..52813e92 100644 --- a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc +++ b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
@@ -90,9 +90,7 @@ GenerateKeywordIfNecessary(params); } -bool SearchEngineTabHelper::OnMessageReceived( - const IPC::Message& message, - content::RenderFrameHost* render_frame_host) { +bool SearchEngineTabHelper::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(SearchEngineTabHelper, message) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PageHasOSDD, OnPageHasOSDD) @@ -102,6 +100,12 @@ return handled; } +bool SearchEngineTabHelper::OnMessageReceived( + const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { + return OnMessageReceived(message); +} + SearchEngineTabHelper::SearchEngineTabHelper(WebContents* web_contents) : content::WebContentsObserver(web_contents), delegate_(nullptr),
diff --git a/chrome/browser/ui/search_engines/search_engine_tab_helper.h b/chrome/browser/ui/search_engines/search_engine_tab_helper.h index cab3cb8..bedd64bc 100644 --- a/chrome/browser/ui/search_engines/search_engine_tab_helper.h +++ b/chrome/browser/ui/search_engines/search_engine_tab_helper.h
@@ -30,6 +30,7 @@ void DidNavigateMainFrame( const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) override; + bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* rfh) override;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc index b93105c1..0388890 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -109,7 +109,7 @@ bool IsTabStripVisible() const override { return window_title_.empty(); } int GetTabStripHeight() const override { - return IsTabStripVisible() ? Tab::GetMinimumUnselectedSize().height() : 0; + return IsTabStripVisible() ? Tab::GetMinimumInactiveSize().height() : 0; } gfx::Size GetTabstripPreferredSize() const override {
diff --git a/chrome/browser/ui/views/location_bar/bubble_icon_view.cc b/chrome/browser/ui/views/location_bar/bubble_icon_view.cc index 8d49ced..218f46c 100644 --- a/chrome/browser/ui/views/location_bar/bubble_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/bubble_icon_view.cc
@@ -6,7 +6,10 @@ #include "chrome/browser/command_updater.h" #include "ui/accessibility/ax_view_state.h" +#include "ui/base/resource/material_design/material_design_controller.h" #include "ui/events/event.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/paint_vector_icon.h" #include "ui/views/bubble/bubble_delegate.h" BubbleIconView::BubbleIconView(CommandUpdater* command_updater, int command_id) @@ -87,3 +90,12 @@ if (bubble) bubble->OnAnchorBoundsChanged(); } + +// static +gfx::ImageSkia BubbleIconView::GetVectorIcon(gfx::VectorIconId id, + bool active) { + const int icon_size = + ui::MaterialDesignController::IsModeMaterial() ? 16 : 18; + SkColor icon_color = active ? gfx::kGoogleBlue : gfx::kChromeIconGrey; + return gfx::CreateVectorIcon(id, icon_size, icon_color); +}
diff --git a/chrome/browser/ui/views/location_bar/bubble_icon_view.h b/chrome/browser/ui/views/location_bar/bubble_icon_view.h index 94e6143..c1afd84 100644 --- a/chrome/browser/ui/views/location_bar/bubble_icon_view.h +++ b/chrome/browser/ui/views/location_bar/bubble_icon_view.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_BUBBLE_ICON_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_BUBBLE_ICON_VIEW_H_ +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/vector_icons_public.h" #include "ui/views/controls/image_view.h" class CommandUpdater; @@ -52,6 +54,10 @@ // views::View: void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + // Gets the given vector icon in the correct color and size based on |active| + // and whether Chrome's in material design mode. + static gfx::ImageSkia GetVectorIcon(gfx::VectorIconId id, bool active); + private: // The CommandUpdater for the Browser object that owns the location bar. CommandUpdater* command_updater_;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index c39d2fc..2b82fa3 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/ui/browser_instant_controller.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h" -#include "chrome/browser/ui/passwords/manage_passwords_icon.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/view_ids.h" @@ -52,7 +51,7 @@ #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" #include "chrome/browser/ui/views/location_bar/zoom_view.h" #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" +#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" #include "chrome/browser/ui/views/translate/translate_bubble_view.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" @@ -305,7 +304,7 @@ open_pdf_in_reader_view_ = new OpenPDFInReaderView(); AddChildView(open_pdf_in_reader_view_); - manage_passwords_icon_view_ = new ManagePasswordsIconView(command_updater()); + manage_passwords_icon_view_ = new ManagePasswordsIconViews(command_updater()); AddChildView(manage_passwords_icon_view_); translate_icon_view_ = new TranslateIconView(command_updater());
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index a88a1d64..42b4f1bf 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -40,7 +40,7 @@ class KeywordHintView; class LocationIconView; class OpenPDFInReaderView; -class ManagePasswordsIconView; +class ManagePasswordsIconViews; class PageActionWithBadgeView; class PageActionImageView; class Profile; @@ -154,7 +154,7 @@ ZoomView* zoom_view() { return zoom_view_; } // The passwords icon. It may not be visible. - ManagePasswordsIconView* manage_passwords_icon_view() { + ManagePasswordsIconViews* manage_passwords_icon_view() { return manage_passwords_icon_view_; } @@ -447,7 +447,7 @@ OpenPDFInReaderView* open_pdf_in_reader_view_; // The manage passwords icon. - ManagePasswordsIconView* manage_passwords_icon_view_; + ManagePasswordsIconViews* manage_passwords_icon_view_; // The page action icon views. PageActionViews page_action_views_;
diff --git a/chrome/browser/ui/views/location_bar/translate_icon_view.cc b/chrome/browser/ui/views/location_bar/translate_icon_view.cc index 6d138d2..089c0012 100644 --- a/chrome/browser/ui/views/location_bar/translate_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/translate_icon_view.cc
@@ -13,8 +13,6 @@ #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/vector_icons_public.h" TranslateIconView::TranslateIconView(CommandUpdater* command_updater) @@ -28,8 +26,7 @@ } void TranslateIconView::SetToggled(bool on) { - SetImage(gfx::CreateVectorIcon(gfx::VectorIconId::TRANSLATE, 16, - on ? gfx::kGoogleBlue : gfx::kChromeIconGrey)); + SetImage(GetVectorIcon(gfx::VectorIconId::TRANSLATE, on)); } void TranslateIconView::OnExecuting(
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index 1786e45..82b5b3a 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/ui/views/passwords/credentials_item_view.h" #include "chrome/browser/ui/views/passwords/credentials_selection_view.h" #include "chrome/browser/ui/views/passwords/manage_password_items_view.h" -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" +#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/render_view_host.h" #include "ui/base/l10n/l10n_util.h" @@ -861,7 +861,7 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); bool is_fullscreen = browser_view->IsFullscreen(); - ManagePasswordsIconView* anchor_view = + ManagePasswordsIconViews* anchor_view = is_fullscreen ? NULL : browser_view->GetLocationBarView()->manage_passwords_icon_view(); @@ -903,7 +903,7 @@ ManagePasswordsBubbleView::ManagePasswordsBubbleView( content::WebContents* web_contents, - ManagePasswordsIconView* anchor_view, + ManagePasswordsIconViews* anchor_view, ManagePasswordsBubbleModel::DisplayReason reason) : ManagedFullScreenBubbleDelegateView(anchor_view, web_contents), model_(web_contents, reason),
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h index a064629..24d1cdad 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h
@@ -8,7 +8,7 @@ #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.h" -class ManagePasswordsIconView; +class ManagePasswordsIconViews; namespace content { class WebContents; @@ -64,7 +64,7 @@ class WebContentMouseHandler; ManagePasswordsBubbleView(content::WebContents* web_contents, - ManagePasswordsIconView* anchor_view, + ManagePasswordsIconViews* anchor_view, ManagePasswordsBubbleModel::DisplayReason reason); ~ManagePasswordsBubbleView() override; @@ -99,7 +99,7 @@ ManagePasswordsBubbleModel model_; - ManagePasswordsIconView* anchor_view_; + ManagePasswordsIconViews* anchor_view_; views::View* initially_focused_view_;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc index a7bb61b..118ae9d 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" +#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/test/base/interactive_test_utils.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" @@ -64,7 +64,7 @@ ManagePasswordsBubbleViewTest() {} ~ManagePasswordsBubbleViewTest() override {} - ManagePasswordsIcon* view() override { + ManagePasswordsIconView* view() override { BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); return browser_view->GetToolbarView() ->location_bar()
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_view.cc deleted file mode 100644 index 2527a88..0000000 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_view.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" - -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/command_updater.h" -#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" -#include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" -#include "components/password_manager/core/common/password_manager_ui.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" - -ManagePasswordsIconView::ManagePasswordsIconView(CommandUpdater* updater) - : BubbleIconView(updater, IDC_MANAGE_PASSWORDS_FOR_PAGE) { - SetFocusable(true); - UpdateVisibleUI(); -} - -ManagePasswordsIconView::~ManagePasswordsIconView() {} - -void ManagePasswordsIconView::UpdateVisibleUI() { - if (state() == password_manager::ui::INACTIVE_STATE) { - SetVisible(false); - return; - } - - SetVisible(true); - SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(icon_id_)); - SetTooltipText(l10n_util::GetStringUTF16(tooltip_text_id_)); - - // We may be about to automatically pop up a ManagePasswordsBubbleView. - // Force layout of the icon's parent now; the bubble will be incorrectly - // positioned otherwise, as the icon won't have been drawn into position. - parent()->Layout(); -} - -void ManagePasswordsIconView::OnChangingState() { - // If there is an opened bubble for the current icon it should go away. - if (active()) - ManagePasswordsBubbleView::CloseBubble(); -} - -void ManagePasswordsIconView::OnExecuting( - BubbleIconView::ExecuteSource source) { -} - -bool ManagePasswordsIconView::OnMousePressed(const ui::MouseEvent& event) { - bool result = BubbleIconView::OnMousePressed(event); - if (IsBubbleShowing()) - ManagePasswordsBubbleView::CloseBubble(); - return result; -} - -bool ManagePasswordsIconView::OnKeyPressed(const ui::KeyEvent& event) { - // Space is always ignored because otherwise the bubble appears with the - // default button down. Releasing the space is equivalent to clicking this - // button. - if (event.key_code() == ui::VKEY_SPACE) - return true; - if (event.key_code() == ui::VKEY_RETURN && active()) { - // If the icon is active, it should transfer its focus to the bubble. - // If it still somehow got this key event, the bubble shouldn't be reopened. - return true; - } - return BubbleIconView::OnKeyPressed(event); -} - -void ManagePasswordsIconView::AboutToRequestFocusFromTabTraversal( - bool reverse) { - if (active()) - ManagePasswordsBubbleView::ActivateBubble(); -} - -views::BubbleDelegateView* ManagePasswordsIconView::GetBubble() const { - return ManagePasswordsBubbleView::manage_password_bubble(); -}
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_browsertest.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_browsertest.cc index 46dd4dc..c3fa3f3 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_browsertest.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_browsertest.cc
@@ -2,20 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" - #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/passwords/manage_passwords_icon.h" #include "chrome/browser/ui/passwords/manage_passwords_test.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" +#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/grit/generated_resources.h" #include "components/password_manager/core/common/password_manager_ui.h" #include "content/public/test/test_utils.h" #include "grit/theme_resources.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/events/event_utils.h" class ManagePasswordsIconViewTest : public ManagePasswordsTest { @@ -25,59 +24,76 @@ ManagePasswordsIconView* view() override { BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); - return static_cast<ManagePasswordsIconView*>( + return static_cast<ManagePasswordsIconViews*>( browser_view->GetToolbarView() ->location_bar() ->manage_passwords_icon_view()); } + password_manager::ui::State ViewState() { return GetView()->state_; } + bool ViewIsActive() { return GetView()->active_; } + + ManagePasswordsIconViews* GetView() { + return static_cast<ManagePasswordsIconViews*>(view()); + } + + base::string16 GetTooltipText() { + base::string16 tooltip; + GetView()->GetTooltipText(gfx::Point(), &tooltip); + return tooltip; + } + private: DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconViewTest); }; IN_PROC_BROWSER_TEST_F(ManagePasswordsIconViewTest, DefaultStateIsInactive) { - EXPECT_EQ(password_manager::ui::INACTIVE_STATE, view()->state()); - EXPECT_FALSE(view()->visible()); - EXPECT_EQ(0, view()->icon_id()); - EXPECT_EQ(0, view()->tooltip_text_id()); - view()->SetActive(true); - EXPECT_EQ(0, view()->icon_id()); - view()->SetActive(false); - EXPECT_EQ(0, view()->icon_id()); + EXPECT_EQ(password_manager::ui::INACTIVE_STATE, ViewState()); + EXPECT_FALSE(GetView()->visible()); } IN_PROC_BROWSER_TEST_F(ManagePasswordsIconViewTest, PendingState) { SetupPendingPassword(); - EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, view()->state()); - EXPECT_TRUE(view()->visible()); - EXPECT_TRUE(view()->active()); - EXPECT_EQ(IDR_SAVE_PASSWORD_ACTIVE, view()->icon_id()); - EXPECT_EQ(IDS_PASSWORD_MANAGER_TOOLTIP_SAVE, view()->tooltip_text_id()); - view()->SetActive(false); - EXPECT_EQ(IDR_SAVE_PASSWORD_INACTIVE, view()->icon_id()); + EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, ViewState()); + EXPECT_TRUE(GetView()->visible()); + EXPECT_TRUE(ViewIsActive()); + // No tooltip because the bubble is showing. + EXPECT_EQ(base::string16(), GetTooltipText()); + const gfx::ImageSkia active_image = GetView()->GetImage(); + + GetView()->SetActive(false); + EXPECT_FALSE(active_image.BackedBySameObjectAs(GetView()->GetImage())); + EXPECT_FALSE(ViewIsActive()); } IN_PROC_BROWSER_TEST_F(ManagePasswordsIconViewTest, ManageState) { SetupManagingPasswords(); - EXPECT_EQ(password_manager::ui::MANAGE_STATE, view()->state()); - EXPECT_TRUE(view()->visible()); - EXPECT_EQ(IDR_SAVE_PASSWORD_INACTIVE, view()->icon_id()); - EXPECT_EQ(IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE, view()->tooltip_text_id()); - view()->SetActive(true); - EXPECT_EQ(IDR_SAVE_PASSWORD_ACTIVE, view()->icon_id()); - view()->SetActive(false); - EXPECT_EQ(IDR_SAVE_PASSWORD_INACTIVE, view()->icon_id()); + EXPECT_EQ(password_manager::ui::MANAGE_STATE, ViewState()); + EXPECT_TRUE(GetView()->visible()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE), + GetTooltipText()); + const gfx::ImageSkia inactive_image = GetView()->GetImage(); + + GetView()->SetActive(true); + const gfx::ImageSkia active_image = GetView()->GetImage(); + EXPECT_FALSE(active_image.BackedBySameObjectAs(inactive_image)); + EXPECT_TRUE(ViewIsActive()); + + GetView()->SetActive(false); + EXPECT_FALSE(active_image.BackedBySameObjectAs(GetView()->GetImage())); + EXPECT_TRUE(inactive_image.BackedBySameObjectAs(GetView()->GetImage())); + EXPECT_FALSE(ViewIsActive()); } IN_PROC_BROWSER_TEST_F(ManagePasswordsIconViewTest, CloseOnClick) { SetupPendingPassword(); - EXPECT_TRUE(view()->visible()); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->visible()); + EXPECT_TRUE(ViewIsActive()); ui::MouseEvent mouse_down(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(900, 60), ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - view()->OnMousePressed(mouse_down); + GetView()->OnMousePressed(mouse_down); // Wait for the command execution to close the bubble. content::RunAllPendingInMessageLoop(); - EXPECT_FALSE(view()->active()); + EXPECT_FALSE(ViewIsActive()); }
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc new file mode 100644 index 0000000..3fbe202 --- /dev/null +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
@@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" + +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/command_updater.h" +#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" +#include "chrome/grit/generated_resources.h" +#include "components/password_manager/core/common/password_manager_ui.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/material_design/material_design_controller.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/vector_icons_public.h" + +ManagePasswordsIconViews::ManagePasswordsIconViews(CommandUpdater* updater) + : BubbleIconView(updater, IDC_MANAGE_PASSWORDS_FOR_PAGE), + state_(password_manager::ui::INACTIVE_STATE), + active_(false) { + SetFocusable(true); + UpdateVisibleUI(); +} + +ManagePasswordsIconViews::~ManagePasswordsIconViews() {} + +void ManagePasswordsIconViews::SetActive(bool active) { + if (active_ == active) + return; + active_ = active; + UpdateVisibleUI(); +} + +void ManagePasswordsIconViews::SetState(password_manager::ui::State state) { + if (state_ == state) + return; + // If there is an opened bubble for the current icon it should go away. + if (active_) + ManagePasswordsBubbleView::CloseBubble(); + state_ = state; + UpdateVisibleUI(); +} + +void ManagePasswordsIconViews::UpdateVisibleUI() { + if (state_ == password_manager::ui::INACTIVE_STATE) { + SetVisible(false); + return; + } + + SetImage(GetVectorIcon(gfx::VectorIconId::AUTOLOGIN, active_)); + SetTooltipText(l10n_util::GetStringUTF16( + state_ == password_manager::ui::PENDING_PASSWORD_STATE + ? IDS_PASSWORD_MANAGER_TOOLTIP_SAVE + : IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE)); + + SetVisible(true); + + // We may be about to automatically pop up a ManagePasswordsBubbleView. + // Force layout of the icon's parent now; the bubble will be incorrectly + // positioned otherwise, as the icon won't have been drawn into position. + parent()->Layout(); +} + +void ManagePasswordsIconViews::OnExecuting( + BubbleIconView::ExecuteSource source) {} + +bool ManagePasswordsIconViews::OnMousePressed(const ui::MouseEvent& event) { + bool result = BubbleIconView::OnMousePressed(event); + if (IsBubbleShowing()) + ManagePasswordsBubbleView::CloseBubble(); + return result; +} + +bool ManagePasswordsIconViews::OnKeyPressed(const ui::KeyEvent& event) { + // Space is always ignored because otherwise the bubble appears with the + // default button down. Releasing the space is equivalent to clicking this + // button. + if (event.key_code() == ui::VKEY_SPACE) + return true; + if (event.key_code() == ui::VKEY_RETURN && active_) { + // If the icon is active, it should transfer its focus to the bubble. + // If it still somehow got this key event, the bubble shouldn't be reopened. + return true; + } + return BubbleIconView::OnKeyPressed(event); +} + +void ManagePasswordsIconViews::AboutToRequestFocusFromTabTraversal( + bool reverse) { + if (active_) + ManagePasswordsBubbleView::ActivateBubble(); +} + +views::BubbleDelegateView* ManagePasswordsIconViews::GetBubble() const { + return ManagePasswordsBubbleView::manage_password_bubble(); +}
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_view.h b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h similarity index 63% rename from chrome/browser/ui/views/passwords/manage_passwords_icon_view.h rename to chrome/browser/ui/views/passwords/manage_passwords_icon_views.h index 0b901c1..5ca41427 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_view.h +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEWS_H_ +#define CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEWS_H_ #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" -#include "chrome/browser/ui/passwords/manage_passwords_icon.h" +#include "chrome/browser/ui/passwords/manage_passwords_icon_view.h" #include "chrome/browser/ui/views/location_bar/bubble_icon_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "ui/views/controls/image_view.h" @@ -15,11 +15,15 @@ class ManagePasswordsUIController; // View for the password icon in the Omnibox. -class ManagePasswordsIconView : public ManagePasswordsIcon, - public BubbleIconView { +class ManagePasswordsIconViews : public ManagePasswordsIconView, + public BubbleIconView { public: - explicit ManagePasswordsIconView(CommandUpdater* updater); - ~ManagePasswordsIconView() override; + explicit ManagePasswordsIconViews(CommandUpdater* updater); + ~ManagePasswordsIconViews() override; + + // ManagePasswordsIconView: + void SetState(password_manager::ui::State state) override; + void SetActive(bool active) override; // BubbleIconView: void OnExecuting(BubbleIconView::ExecuteSource source) override; @@ -29,22 +33,18 @@ // views::View: void AboutToRequestFocusFromTabTraversal(bool reverse) override; -#if defined(UNIT_TEST) - int icon_id() const { return icon_id_; } - int tooltip_text_id() const { return tooltip_text_id_; } -#endif - - protected: - // ManagePasswordsIcon: - void UpdateVisibleUI() override; - void OnChangingState() override; - // BubbleIconView: views::BubbleDelegateView* GetBubble() const override; private: + friend class ManagePasswordsIconViewTest; - DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconView); + void UpdateVisibleUI(); + + password_manager::ui::State state_; + bool active_; + + DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconViews); }; -#endif // CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEW_H_ +#endif // CHROME_BROWSER_UI_VIEWS_PASSWORDS_MANAGE_PASSWORDS_ICON_VIEWS_H_
diff --git a/chrome/browser/ui/views/profiles/new_avatar_button.cc b/chrome/browser/ui/views/profiles/new_avatar_button.cc index 16fef6bb..5faaa7dd 100644 --- a/chrome/browser/ui/views/profiles/new_avatar_button.cc +++ b/chrome/browser/ui/views/profiles/new_avatar_button.cc
@@ -209,9 +209,9 @@ if (use_generic_button) { SetImage(views::Button::STATE_NORMAL, generic_avatar_); } else if (has_auth_error_) { - SetImage( - views::Button::STATE_NORMAL, - gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13, gfx::kAmber)); + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13, + gfx::kGoogleYellow700)); } else { SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); }
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 6d0d78a..9ed70f2b 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -23,6 +23,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/user_metrics.h" +#include "grit/components_scaled_resources.h" #include "grit/theme_resources.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "ui/accessibility/ax_view_state.h" @@ -613,7 +614,7 @@ return std::min(indicator_left, close_button_left); } -gfx::Size Tab::GetMinimumUnselectedSize() { +gfx::Size Tab::GetMinimumInactiveSize() { // Since we use images, the real minimum height of the image is // defined most accurately by the height of the end cap images. InitTabResources(); @@ -622,15 +623,15 @@ } // static -gfx::Size Tab::GetMinimumSelectedSize() { - gfx::Size minimum_size = GetMinimumUnselectedSize(); +gfx::Size Tab::GetMinimumActiveSize() { + gfx::Size minimum_size = GetMinimumInactiveSize(); minimum_size.Enlarge(gfx::kFaviconSize, 0); return minimum_size; } // static gfx::Size Tab::GetStandardSize() { - gfx::Size standard_size = GetMinimumUnselectedSize(); + gfx::Size standard_size = GetMinimumInactiveSize(); const int title_spacing = GetLayoutConstant(TAB_FAVICON_TITLE_SPACING); const int title_width = GetLayoutConstant(TAB_MAXIMUM_TITLE_WIDTH); standard_size.Enlarge(title_spacing + title_width, 0); @@ -644,8 +645,8 @@ // static int Tab::GetPinnedWidth() { - return GetMinimumUnselectedSize().width() + - GetLayoutConstant(TAB_PINNED_CONTENT_WIDTH); + return GetMinimumInactiveSize().width() + + GetLayoutConstant(TAB_PINNED_CONTENT_WIDTH); } // static @@ -749,7 +750,7 @@ void Tab::OnPaint(gfx::Canvas* canvas) { // Don't paint if we're narrower than we can render correctly. (This should // only happen during animations). - if (width() < GetMinimumUnselectedSize().width() && !data().pinned) + if (width() < GetMinimumInactiveSize().width() && !data().pinned) return; gfx::Rect clip; @@ -1372,7 +1373,8 @@ } else if (should_display_crashed_favicon_) { // Paint crash favicon. ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); + gfx::ImageSkia crashed_favicon( + *rb.GetImageSkiaNamed(IDR_CRASH_SAD_FAVICON)); bounds.set_y(bounds.y() + favicon_hiding_offset_); DrawIconCenter(canvas, crashed_favicon, 0, crashed_favicon.width(), @@ -1411,7 +1413,7 @@ } int Tab::IconCapacity() const { - const gfx::Size min_size(GetMinimumUnselectedSize()); + const gfx::Size min_size(GetMinimumInactiveSize()); if (height() < min_size.height()) return 0; const int available_width = std::max(0, width() - min_size.width());
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 45dcae6a..950c410 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -135,11 +135,12 @@ static int leading_width_for_drag() { return 16; } // Returns the minimum possible size of a single unselected Tab. - static gfx::Size GetMinimumUnselectedSize(); + static gfx::Size GetMinimumInactiveSize(); + // Returns the minimum possible size of a selected Tab. Selected tabs must // always show a close button and have a larger minimum size than unselected // tabs. - static gfx::Size GetMinimumSelectedSize(); + static gfx::Size GetMinimumActiveSize(); // Returns the preferred size of a single Tab, assuming space is // available. static gfx::Size GetStandardSize();
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 2152b7e..78cfc8f 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -701,9 +701,9 @@ // the threshold. int threshold = kHorizontalMoveThreshold; if (!attached_tabstrip_->touch_layout_.get()) { - double unselected, selected; - attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected); - double ratio = unselected / Tab::GetStandardSize().width(); + double ratio = + static_cast<double>(attached_tabstrip_->current_inactive_width()) / + Tab::GetStandardSize().width(); threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); } // else case: touch tabs never shrink. @@ -1288,10 +1288,8 @@ source_tab_drag_data()->attached_tab->height()); } - double sel_width, unselected_width; - attached_tabstrip_->GetCurrentTabWidths(&sel_width, &unselected_width); return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), - static_cast<int>(sel_width), + attached_tabstrip_->current_active_width(), Tab::GetStandardSize().height()); }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index eaf7d65..65125ee 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" +#include "chrome/browser/ui/views/tabs/tab_strip_layout.h" #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" #include "chrome/browser/ui/views/touch_uma/touch_uma.h" #include "chrome/common/chrome_switches.h" @@ -94,11 +95,6 @@ static int drop_indicator_width; static int drop_indicator_height; -static inline int Round(double x) { - // Why oh why is this not in a standard header? - return static_cast<int>(floor(x + 0.5)); -} - // Max number of stacked tabs. static const int kMaxStackedCount = 4; @@ -120,6 +116,12 @@ // Amount to adjust the clip by when the tab is stacked after the active index. const int kStackedTabRightClip = 20; +#if defined(OS_MACOSX) +const int kPinnedToNonPinnedOffset = 2; +#else +const int kPinnedToNonPinnedOffset = 3; +#endif + base::string16 GetClipboardText() { if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) return base::string16(); @@ -225,6 +227,21 @@ TabDragController::EVENT_SOURCE_MOUSE; } +const TabSizeInfo& GetTabSizeInfo() { + static TabSizeInfo* tab_size_info = nullptr; + if (tab_size_info) + return *tab_size_info; + + tab_size_info = new TabSizeInfo; + tab_size_info->pinned_tab_width = Tab::GetPinnedWidth(); + tab_size_info->min_active_width = Tab::GetMinimumActiveSize().width(); + tab_size_info->min_inactive_width = Tab::GetMinimumInactiveSize().width(); + tab_size_info->max_size = Tab::GetStandardSize(); + tab_size_info->tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); + tab_size_info->pinned_to_normal_offset = kPinnedToNonPinnedOffset; + return *tab_size_info; +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -525,17 +542,15 @@ const int TabStrip::kNewTabButtonAssetHeight = 18; #if defined(OS_MACOSX) const int TabStrip::kNewTabButtonHorizontalOffset = -8; -const int TabStrip::kPinnedToNonPinnedGap = 2; #else const int TabStrip::kNewTabButtonHorizontalOffset = -11; -const int TabStrip::kPinnedToNonPinnedGap = 3; #endif TabStrip::TabStrip(TabStripController* controller) : controller_(controller), newtab_button_(NULL), - current_unselected_width_(Tab::GetStandardSize().width()), - current_selected_width_(Tab::GetStandardSize().width()), + current_inactive_width_(Tab::GetStandardSize().width()), + current_active_width_(Tab::GetStandardSize().width()), available_width_for_tabs_(-1), in_tab_close_(false), animation_container_(new gfx::AnimationContainer()), @@ -781,8 +796,8 @@ // We need to check what would happen if the active tab were to move to this // tab or before. - return (right_edge + current_selected_width_ - current_unselected_width_) <= - tab_area_width(); + return (right_edge + current_active_width_ - current_inactive_width_) <= + tab_area_width(); } void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { @@ -807,7 +822,7 @@ tab_being_removed->width() + GetLayoutConstant(TABSTRIP_TAB_OVERLAP); if (model_index == 0 && tab_being_removed->data().pinned && !tab_at(1)->data().pinned) { - available_width_for_tabs_ -= kPinnedToNonPinnedGap; + available_width_for_tabs_ -= kPinnedToNonPinnedOffset; } } @@ -840,7 +855,7 @@ } else { // We have "tiny tabs" if the tabs are so tiny that the unselected ones are // a different size to the selected ones. - bool tiny_tabs = current_unselected_width_ != current_selected_width_; + bool tiny_tabs = current_inactive_width_ != current_active_width_; if (!IsAnimating() && (!in_tab_close_ || tiny_tabs)) { DoLayout(); } else { @@ -1376,11 +1391,11 @@ const int pinned_tab_count = GetPinnedTabCount(); needed_tab_width = pinned_tab_count * Tab::GetPinnedWidth(); const int remaining_tab_count = tab_count() - pinned_tab_count; - const int min_selected_width = Tab::GetMinimumSelectedSize().width(); - const int min_unselected_width = Tab::GetMinimumUnselectedSize().width(); + const int min_selected_width = Tab::GetMinimumActiveSize().width(); + const int min_unselected_width = Tab::GetMinimumInactiveSize().width(); if (remaining_tab_count > 0) { - needed_tab_width += kPinnedToNonPinnedGap + min_selected_width + - ((remaining_tab_count - 1) * min_unselected_width); + needed_tab_width += kPinnedToNonPinnedOffset + min_selected_width + + ((remaining_tab_count - 1) * min_unselected_width); } const int tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); if (tab_count() > 1) @@ -1393,10 +1408,9 @@ needed_tab_width = std::min( std::max(needed_tab_width, min_selected_width), largest_min_tab_width); } - return gfx::Size( - needed_tab_width + new_tab_button_width(), - immersive_style_ ? - Tab::GetImmersiveHeight() : Tab::GetMinimumUnselectedSize().height()); + return gfx::Size(needed_tab_width + new_tab_button_width(), + immersive_style_ ? Tab::GetImmersiveHeight() + : Tab::GetMinimumInactiveSize().height()); } void TabStrip::OnDragEntered(const DropTargetEvent& event) { @@ -1797,7 +1811,7 @@ for (size_t i = 0; i < tabs.size(); ++i) { Tab* tab = tabs[i]; if (i > 0 && tab->data().pinned != tabs[i - 1]->data().pinned) - x += kPinnedToNonPinnedGap; + x += kPinnedToNonPinnedOffset; gfx::Rect new_bounds = tab->bounds(); new_bounds.set_origin(gfx::Point(x, 0)); bounds->push_back(new_bounds); @@ -1811,7 +1825,7 @@ Tab* tab = tabs[i]; width += tab->width(); if (i > 0 && tab->data().pinned != tabs[i - 1]->data().pinned) - width += kPinnedToNonPinnedGap; + width += kPinnedToNonPinnedOffset; } if (!tabs.empty()) width -= GetLayoutConstant(TABSTRIP_TAB_OVERLAP) * (tabs.size() - 1); @@ -2078,74 +2092,6 @@ } } -void TabStrip::GetCurrentTabWidths(double* unselected_width, - double* selected_width) const { - *unselected_width = current_unselected_width_; - *selected_width = current_selected_width_; -} - -void TabStrip::GetDesiredTabWidths(int tab_count, - int pinned_tab_count, - double* unselected_width, - double* selected_width) const { - DCHECK(tab_count >= 0 && pinned_tab_count >= 0 && - pinned_tab_count <= tab_count); - const double min_unselected_width = Tab::GetMinimumUnselectedSize().width(); - const double min_selected_width = Tab::GetMinimumSelectedSize().width(); - - *unselected_width = min_unselected_width; - *selected_width = min_selected_width; - - if (tab_count == 0) { - // Return immediately to avoid divide-by-zero below. - return; - } - - // Determine how much space we can actually allocate to tabs. - int available_width = (available_width_for_tabs_ < 0) ? - tab_area_width() : available_width_for_tabs_; - const int tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); - if (pinned_tab_count > 0) { - available_width -= - pinned_tab_count * (Tab::GetPinnedWidth() - tab_overlap); - tab_count -= pinned_tab_count; - if (tab_count == 0) { - *selected_width = *unselected_width = Tab::GetStandardSize().width(); - return; - } - // Account for gap between the last pinned tab and first non-pinned tab. - available_width -= kPinnedToNonPinnedGap; - } - - // Calculate the desired tab widths by dividing the available space into equal - // portions. Don't let tabs get larger than the "standard width" or smaller - // than the minimum width for each type, respectively. - const int total_overlap = tab_overlap * (tab_count - 1); - const double desired_tab_width = std::min((static_cast<double>( - available_width + total_overlap) / static_cast<double>(tab_count)), - static_cast<double>(Tab::GetStandardSize().width())); - *unselected_width = std::max(desired_tab_width, min_unselected_width); - *selected_width = std::max(desired_tab_width, min_selected_width); - - // When there are multiple tabs, we'll have one selected and some unselected - // tabs. If the desired width was between the minimum sizes of these types, - // try to shrink the tabs with the smaller minimum. For example, if we have - // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If - // selected tabs have a minimum width of 4 and unselected tabs have a minimum - // width of 1, the above code would set *unselected_width = 2.5, - // *selected_width = 4, which results in a total width of 11.5. Instead, we - // want to set *unselected_width = 2, *selected_width = 4, for a total width - // of 10. - if (tab_count > 1) { - if (desired_tab_width < min_selected_width) { - // Unselected width = (total width - selected width) / (num_tabs - 1) - *unselected_width = std::max(static_cast<double>( - available_width + total_overlap - min_selected_width) / - static_cast<double>(tab_count - 1), min_unselected_width); - } - } -} - void TabStrip::ResizeLayoutTabs() { // We've been called back after the TabStrip has been emptied out (probably // just prior to the window being destroyed). We need to do nothing here or @@ -2363,71 +2309,46 @@ } void TabStrip::GenerateIdealBounds() { - int new_tab_y = 0; + if (tab_count() == 0) + return; // Should only happen during creation/destruction, ignore. - if (touch_layout_) { - if (tabs_.view_size() == 0) - return; + if (!touch_layout_) { + const int available_width = (available_width_for_tabs_ < 0) + ? tab_area_width() + : available_width_for_tabs_; + const std::vector<gfx::Rect> tabs_bounds = + CalculateBounds(GetTabSizeInfo(), GetPinnedTabCount(), tab_count(), + controller_->GetActiveIndex(), available_width, + ¤t_active_width_, ¤t_inactive_width_); + DCHECK_EQ(static_cast<size_t>(tab_count()), tabs_bounds.size()); - int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() + - kNewTabButtonHorizontalOffset; - newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); - return; + for (size_t i = 0; i < tabs_bounds.size(); ++i) + tabs_.set_ideal_bounds(i, tabs_bounds[i]); } - GetDesiredTabWidths(tab_count(), GetPinnedTabCount(), - ¤t_unselected_width_, ¤t_selected_width_); - - // NOTE: This currently assumes a tab's height doesn't differ based on - // selected state or the number of tabs in the strip! - int tab_height = Tab::GetStandardSize().height(); - int first_non_pinned_index = 0; - double tab_x = GenerateIdealBoundsForPinnedTabs(&first_non_pinned_index); - const int tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); - for (int i = first_non_pinned_index; i < tab_count(); ++i) { - Tab* tab = tab_at(i); - DCHECK(!tab->data().pinned); - double tab_width = - tab->IsActive() ? current_selected_width_ : current_unselected_width_; - double end_of_tab = tab_x + tab_width; - int rounded_tab_x = Round(tab_x); - tabs_.set_ideal_bounds( - i, - gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, - tab_height)); - tab_x = end_of_tab - tab_overlap; - } - - // Update bounds of new tab button. - int new_tab_x; - if ((Tab::GetStandardSize().width() - Round(current_unselected_width_)) > 1 && - !in_tab_close_) { - // We're shrinking tabs, so we need to anchor the New Tab button to the - // right edge of the TabStrip's bounds, rather than the right edge of the - // right-most Tab, otherwise it'll bounce when animating. - new_tab_x = width() - newtab_button_bounds_.width(); - } else { - new_tab_x = Round(tab_x + tab_overlap) + - kNewTabButtonHorizontalOffset; - } - newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); + const int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() + + kNewTabButtonHorizontalOffset; + newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, 0)); } int TabStrip::GenerateIdealBoundsForPinnedTabs(int* first_non_pinned_index) { - int next_x = 0; - int pinned_width = Tab::GetPinnedWidth(); - int tab_height = Tab::GetStandardSize().height(); - int index = 0; - for (; index < tab_count() && tab_at(index)->data().pinned; ++index) { - tabs_.set_ideal_bounds(index, - gfx::Rect(next_x, 0, pinned_width, tab_height)); - next_x += pinned_width - GetLayoutConstant(TABSTRIP_TAB_OVERLAP); - } - if (index > 0 && index < tab_count()) - next_x += kPinnedToNonPinnedGap; + const int num_pinned_tabs = GetPinnedTabCount(); + if (first_non_pinned_index) - *first_non_pinned_index = index; - return next_x; + *first_non_pinned_index = num_pinned_tabs; + + if (num_pinned_tabs == 0) + return 0; + + std::vector<gfx::Rect> tab_bounds(tab_count()); + CalculateBoundsForPinnedTabs(GetTabSizeInfo(), num_pinned_tabs, tab_count(), + &tab_bounds); + for (int i = 0; i < num_pinned_tabs; ++i) + tabs_.set_ideal_bounds(i, tab_bounds[i]); + return (num_pinned_tabs < tab_count()) + ? tab_bounds[num_pinned_tabs].x() + : tab_bounds[num_pinned_tabs - 1].right() - + GetLayoutConstant(TABSTRIP_TAB_OVERLAP); } void TabStrip::StartResizeLayoutAnimation() { @@ -2455,7 +2376,7 @@ // to add the extra padding. DCHECK_LT(model_index, tab_count() - 1); if (tab_closing->data().pinned && !tab_at(model_index + 1)->data().pinned) - delta += kPinnedToNonPinnedGap; + delta += kPinnedToNonPinnedOffset; for (int i = model_index + 1; i < tab_count(); ++i) { gfx::Rect bounds = ideal_bounds(i); @@ -2505,7 +2426,7 @@ return 0; const int overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); return pinned_tab_count * (Tab::GetPinnedWidth() - overlap) + - kPinnedToNonPinnedGap; + kPinnedToNonPinnedOffset; } Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { @@ -2571,7 +2492,7 @@ return; if (needs_touch) { - gfx::Size tab_size(Tab::GetMinimumSelectedSize()); + gfx::Size tab_size(Tab::GetMinimumActiveSize()); tab_size.set_width(Tab::GetTouchWidth()); touch_layout_.reset(new StackedTabStripLayout( tab_size,
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index ebf0975c..68656d5 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -311,9 +311,6 @@ DISALLOW_COPY_AND_ASSIGN(DropInfo); }; - // Horizontal gap between pinned and non-pinned tabs. - static const int kPinnedToNonPinnedGap; - void Init(); // Creates and returns a new tab. The caller owners the returned tab. @@ -441,20 +438,11 @@ // -- Tab Resize Layout ----------------------------------------------------- - // Returns the exact (unrounded) current width of each tab. - void GetCurrentTabWidths(double* unselected_width, - double* selected_width) const; - - // Returns the exact (unrounded) desired width of each tab, based on the - // desired strip width and number of tabs. If - // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in - // calculating the desired strip width; otherwise we use the current width. - // |pinned_tab_count| gives the number of pinned tabs and |tab_count| the - // number of pinned and non-pinned tabs. - void GetDesiredTabWidths(int tab_count, - int pinned_tab_count, - double* unselected_width, - double* selected_width) const; + // Returns the current width of each tab. If the space for tabs is not evenly + // divisible into these widths, the initial tabs in the strip will be 1 px + // larger. + int current_inactive_width() const { return current_inactive_width_; } + int current_active_width() const { return current_active_width_; } // Perform an animated resize-relayout of the TabStrip immediately. void ResizeLayoutTabs(); @@ -599,20 +587,18 @@ // Ideal bounds of the new tab button. gfx::Rect newtab_button_bounds_; - // The current widths of various types of tabs. We save these so that, as - // users close tabs while we're holding them at the same size, we can lay out - // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving - // them all at their existing, rounded widths. - double current_unselected_width_; - double current_selected_width_; + // Returns the current widths of each type of tab. If the tabstrip width is + // not evenly divisible into these widths, the initial tabs in the strip will + // be 1 px larger. + int current_inactive_width_; + int current_active_width_; - // If this value is nonnegative, it is used in GetDesiredTabWidths() to - // calculate how much space in the tab strip to use for tabs. Most of the - // time this will be -1, but while we're handling closing a tab via the mouse, - // we'll set this to the edge of the last tab before closing, so that if we - // are closing the last tab and need to resize immediately, we'll resize only - // back to this width, thus once again placing the last tab under the mouse - // cursor. + // If this value is nonnegative, it is used as the width to lay out tabs + // (instead of tab_area_width()). Most of the time this will be -1, but while + // we're handling closing a tab via the mouse, we'll set this to the edge of + // the last tab before closing, so that if we are closing the last tab and + // need to resize immediately, we'll resize only back to this width, thus + // once again placing the last tab under the mouse cursor. int available_width_for_tabs_; // True if PrepareForCloseAt has been invoked. When true remove animations
diff --git a/chrome/browser/ui/views/tabs/tab_strip_layout.cc b/chrome/browser/ui/views/tabs/tab_strip_layout.cc new file mode 100644 index 0000000..b69a1cfa --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_strip_layout.cc
@@ -0,0 +1,131 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/tabs/tab_strip_layout.h" + +#include <algorithm> + +#include "base/logging.h" +#include "ui/gfx/geometry/rect.h" + +namespace { + +// Calculates the size for normal tabs. +// |is_active_tab_normal| is true if the active tab is a normal tab, if false +// the active tab is not in the set of normal tabs. +// |normal_width| is the available width for normal tabs. +void CalculateNormalTabWidths(const TabSizeInfo& tab_size_info, + bool is_active_tab_normal, + int num_normal_tabs, + int normal_width, + int* active_width, + int* inactive_width) { + DCHECK_NE(0, num_normal_tabs); + + *inactive_width = tab_size_info.min_inactive_width; + *active_width = tab_size_info.min_active_width; + + // Calculate the desired tab widths by dividing the available space into equal + // portions. Don't let tabs get larger than the "standard width" or smaller + // than the minimum width for each type, respectively. + const int total_overlap = tab_size_info.tab_overlap * (num_normal_tabs - 1); + const int desired_tab_width = + std::min((normal_width + total_overlap) / num_normal_tabs, + tab_size_info.max_size.width()); + *inactive_width = + std::max(desired_tab_width, tab_size_info.min_inactive_width); + *active_width = std::max(desired_tab_width, tab_size_info.min_active_width); + + // |desired_tab_width| was calculated assuming the active and inactive tabs + // get the same width. If this isn't the case, then we need to recalculate + // the size for inactive tabs based on how big the active tab is. + if (*inactive_width != *active_width && is_active_tab_normal && + num_normal_tabs > 1) { + *inactive_width = std::max( + (normal_width + total_overlap - *active_width) / (num_normal_tabs - 1), + tab_size_info.min_inactive_width); + } +} + +} // namespace + +void CalculateBoundsForPinnedTabs(const TabSizeInfo& tab_size_info, + int num_pinned_tabs, + int num_tabs, + std::vector<gfx::Rect>* tabs_bounds) { + DCHECK_EQ(static_cast<size_t>(num_tabs), tabs_bounds->size()); + int index = 0; + int next_x = 0; + for (; index < num_pinned_tabs; ++index) { + (*tabs_bounds)[index].SetRect(next_x, 0, tab_size_info.pinned_tab_width, + tab_size_info.max_size.height()); + next_x += tab_size_info.pinned_tab_width - tab_size_info.tab_overlap; + } + if (index > 0 && index < num_tabs) { + (*tabs_bounds)[index].set_x(next_x + tab_size_info.pinned_to_normal_offset); + } +} + +std::vector<gfx::Rect> CalculateBounds(const TabSizeInfo& tab_size_info, + int num_pinned_tabs, + int num_tabs, + int active_index, + int width, + int* active_width, + int* inactive_width) { + DCHECK_NE(0, num_tabs); + + std::vector<gfx::Rect> tabs_bounds(num_tabs); + + *active_width = *inactive_width = tab_size_info.max_size.width(); + + int next_x = 0; + if (num_pinned_tabs) { + CalculateBoundsForPinnedTabs(tab_size_info, num_pinned_tabs, num_tabs, + &tabs_bounds); + if (num_pinned_tabs == num_tabs) + return tabs_bounds; + + // CalculateBoundsForPinnedTabs() sets the x location of the first normal + // tab. + width -= tabs_bounds[num_pinned_tabs].x(); + next_x = tabs_bounds[num_pinned_tabs].x(); + } + + const bool is_active_tab_normal = active_index >= num_pinned_tabs; + const int num_normal_tabs = num_tabs - num_pinned_tabs; + CalculateNormalTabWidths(tab_size_info, is_active_tab_normal, num_normal_tabs, + width, active_width, inactive_width); + + // As CalculateNormalTabWidths() calculates sizes using ints there may be a + // bit of extra space (due to the available width not being an integer + // multiple of these sizes). Give the extra space to the first tabs, and only + // give extra space to the active tab if it is the same size as the inactive + // tabs (the active tab may already be bigger). + int expand_width_count = 0; + bool give_extra_space_to_active = false; + if (*inactive_width != tab_size_info.max_size.width()) { + give_extra_space_to_active = *active_width == *inactive_width; + expand_width_count = + width - + ((*inactive_width - tab_size_info.tab_overlap) * (num_normal_tabs - 1)); + expand_width_count -= + (is_active_tab_normal ? *active_width : *inactive_width); + } + + // Set the ideal bounds of the normal tabs. + // GenerateIdealBoundsForPinnedTabs() set the ideal bounds of the pinned tabs. + for (int i = num_pinned_tabs; i < num_tabs; ++i) { + const bool is_active = i == active_index; + int width = is_active ? *active_width : *inactive_width; + if (expand_width_count > 0 && (!is_active || give_extra_space_to_active)) { + ++width; + --expand_width_count; + } + tabs_bounds[i].SetRect(next_x, 0, width, tab_size_info.max_size.height()); + next_x += tabs_bounds[i].width() - tab_size_info.tab_overlap; + } + + return tabs_bounds; +}
diff --git a/chrome/browser/ui/views/tabs/tab_strip_layout.h b/chrome/browser/ui/views/tabs/tab_strip_layout.h new file mode 100644 index 0000000..508de75 --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_strip_layout.h
@@ -0,0 +1,56 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_H_ +#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_H_ + +#include <vector> + +#include "ui/gfx/geometry/size.h" + +namespace gfx { +class Rect; +} + +struct TabSizeInfo { + // The width of pinned tabs. + int pinned_tab_width; + + // The min width of active/inactive tabs. + int min_active_width; + int min_inactive_width; + + // The max size of tabs. Active and inactive tabs have the same max width. + gfx::Size max_size; + + // The overlap between adjacent tabs. When positioning tabs the x-coordinate + // of a tab is calculated as the x-coordinate of the previous tab plus the + // previous tab's width minus the |tab_overlap|, e.g. + // next_tab_x = previous_tab.max_x() - tab_overlap. + int tab_overlap; + + // Additional offset between the last pinned tab and the first normal tab. + int pinned_to_normal_offset; +}; + +// Calculates the bounds of the pinned tabs. This assumes |tabs_bounds| is the +// same size as |num_tabs|. In addition to setting the bounds of the pinned +// tabs this sets the x-coordinate of the first normal tab (as long as there is +// a normal tab). +void CalculateBoundsForPinnedTabs(const TabSizeInfo& tab_size_info, + int num_pinned_tabs, + int num_tabs, + std::vector<gfx::Rect>* tabs_bounds); + +// Calculates and returns the bounds of the tabs. |width| is the available +// width to use for tab layout. +std::vector<gfx::Rect> CalculateBounds(const TabSizeInfo& tab_size_info, + int num_pinned_tabs, + int num_tabs, + int active_index, + int width, + int* active_width, + int* inactive_width); + +#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_H_
diff --git a/chrome/browser/ui/views/tabs/tab_strip_layout_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_layout_unittest.cc new file mode 100644 index 0000000..bbe888c --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_strip_layout_unittest.cc
@@ -0,0 +1,109 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/tabs/tab_strip_layout.h" + +#include "base/strings/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" + +namespace { + +// Returns a string with the x-coordinate and width of each gfx::Rect in +// |tabs_bounds|. Each gfx::Rect is separated by a ','. +std::string TabsBoundsToString(const std::vector<gfx::Rect>& tabs_bounds) { + std::string result; + for (const auto& bounds : tabs_bounds) { + if (!result.empty()) + result += ", "; + result += + base::IntToString(bounds.x()) + " " + base::IntToString(bounds.width()); + } + return result; +} + +} // namespace + +TEST(TabStripLayoutTest, Tests) { + TabSizeInfo tab_size_info; + tab_size_info.pinned_tab_width = 10; + tab_size_info.min_active_width = 20; + tab_size_info.min_inactive_width = 14; + tab_size_info.max_size = gfx::Size(100, 10); + tab_size_info.tab_overlap = 4; + tab_size_info.pinned_to_normal_offset = 6; + + struct TestCases { + int num_pinned_tabs; + int num_tabs; + int active_index; + int width; + const char* expected_sizes; + int expected_active_width; + int expected_inactive_width; + } test_cases[] = { + // Ample space, all normal tabs. + {0, 3, 0, 1000, "0 100, 96 100, 192 100", 100, 100}, + + // Ample space, all pinned. + {3, 3, 0, 1000, "0 10, 6 10, 12 10", 100, 100}, + + // Ample space, one pinned and two normal tabs. + {1, 3, 0, 1000, "0 10, 12 100, 108 100", 100, 100}, + + // Resize between min and max, no pinned and no rounding. + {0, 4, 0, 100, "0 28, 24 28, 48 28, 72 28", 28, 28}, + + // Resize between min and max, pinned and no rounding. + {1, 3, 0, 100, "0 10, 12 46, 54 46", 46, 46}, + + // Resize between min and max, no pinned, rounding. + {0, 4, 0, 102, "0 29, 25 29, 50 28, 74 28", 28, 28}, + + // Resize between min and max, pinned and rounding. + {1, 3, 0, 101, "0 10, 12 47, 55 46", 46, 46}, + + // Resize between active/inactive width, only one tab. + {0, 1, 0, 15, "0 20", 20, 15}, + + // Resize between active/inactive width and no rounding. + {0, 6, 0, 90, "0 20, 16 18, 30 18, 44 18, 58 18, 72 18", 20, 18}, + + // Resize between active/inactive width, rounding. + {0, 6, 0, 93, "0 20, 16 19, 31 19, 46 19, 61 18, 75 18", 20, 18}, + + // Resize between active/inactive width, one pinned and active, no + // rounding. + {1, 6, 0, 91, "0 10, 12 19, 27 19, 42 19, 57 19, 72 19", 20, 19}, + + // Resize between active/inactive width, one pinned and active, rounding. + {1, 6, 0, 92, "0 10, 12 20, 28 19, 43 19, 58 19, 73 19", 20, 19}, + + // Not enough space, all pinned. + {3, 3, 0, 10, "0 10, 6 10, 12 10", 100, 100}, + + // Not enough space (for minimum widths), all normal. + {0, 3, 0, 10, "0 20, 16 14, 26 14", 20, 14}, + + // Not enough space (for minimum widths), one pinned and two normal. + {1, 3, 0, 10, "0 10, 12 14, 22 14", 20, 14}, + }; + + for (size_t i = 0; i < arraysize(test_cases); ++i) { + int active_width; + int inactive_width; + std::vector<gfx::Rect> tabs_bounds = + CalculateBounds(tab_size_info, test_cases[i].num_pinned_tabs, + test_cases[i].num_tabs, test_cases[i].active_index, + test_cases[i].width, &active_width, &inactive_width); + EXPECT_EQ(test_cases[i].expected_sizes, TabsBoundsToString(tabs_bounds)) + << i; + EXPECT_EQ(test_cases[i].expected_active_width, active_width) << i; + EXPECT_EQ(test_cases[i].expected_inactive_width, inactive_width) << i; + for (const auto& bounds : tabs_bounds) { + EXPECT_EQ(0, bounds.y()) << i; + EXPECT_EQ(tab_size_info.max_size.height(), bounds.height()) << i; + } + } +}
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 9600799..b471d4fbc 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -311,7 +311,7 @@ EXPECT_FALSE(tab_strip_->IsImmersiveStyle()); // Tab strip defaults to normal tab height. - int normal_height = Tab::GetMinimumUnselectedSize().height(); + int normal_height = Tab::GetMinimumInactiveSize().height(); EXPECT_EQ(normal_height, tab_strip_->GetPreferredSize().height()); // Tab strip can toggle immersive mode.
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 42f30a4..d5641ad4 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -303,8 +303,8 @@ bounds.set_width(Tab::GetPinnedWidth()); min_width = Tab::GetPinnedWidth(); } else { - min_width = is_active_tab ? Tab::GetMinimumSelectedSize().width() : - Tab::GetMinimumUnselectedSize().width(); + min_width = is_active_tab ? Tab::GetMinimumActiveSize().width() + : Tab::GetMinimumInactiveSize().width(); } while (bounds.width() >= min_width) { SCOPED_TRACE(::testing::Message() << "bounds=" << bounds.ToString());
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index ae4bd50..b40b5fc8 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -787,10 +787,7 @@ home_->SetImage(views::Button::STATE_NORMAL, gfx::CreateVectorIcon(gfx::VectorIconId::NAVIGATE_HOME, kButtonSize, normal_color)); - app_menu_button_->SetImage(views::Button::STATE_NORMAL, - gfx::CreateVectorIcon( - gfx::VectorIconId::BROWSER_TOOLS, - kButtonSize, normal_color)); + app_menu_button_->UpdateIcon(); } else { back_->SetImage(views::Button::STATE_NORMAL, *(tp->GetImageSkiaNamed(IDR_BACK)));
diff --git a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc index 5ee206ed..ff2638f 100644 --- a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc
@@ -8,6 +8,7 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/time/time.h" +#include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/toolbar/wrench_menu_model.h" #include "chrome/browser/ui/views/extensions/browser_action_drag_data.h" @@ -19,6 +20,9 @@ #include "ui/base/resource/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icons_public.h" #include "ui/keyboard/keyboard_controller.h" #include "ui/views/controls/button/label_button_border.h" #include "ui/views/controls/menu/menu_listener.h" @@ -30,7 +34,7 @@ WrenchToolbarButton::WrenchToolbarButton(ToolbarView* toolbar_view) : views::MenuButton(NULL, base::string16(), toolbar_view, false), - wrench_icon_painter_(nullptr), + severity_(WrenchIconPainter::SEVERITY_NONE), toolbar_view_(toolbar_view), allow_extension_dragging_( extensions::FeatureSwitch::extension_action_redesign() @@ -45,8 +49,11 @@ void WrenchToolbarButton::SetSeverity(WrenchIconPainter::Severity severity, bool animate) { - if (ui::MaterialDesignController::IsModeMaterial()) + if (ui::MaterialDesignController::IsModeMaterial()) { + severity_ = severity; + UpdateIcon(); return; + } wrench_icon_painter_->SetSeverity(severity, animate); SchedulePaint(); @@ -113,6 +120,32 @@ SchedulePaint(); } +void WrenchToolbarButton::UpdateIcon() { + DCHECK(ui::MaterialDesignController::IsModeMaterial()); + SkColor color = SK_ColorRED; + switch (severity_) { + case WrenchIconPainter::SEVERITY_NONE: + color = GetThemeProvider()->GetColor( + ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON); + break; + case WrenchIconPainter::SEVERITY_LOW: + color = gfx::kGoogleGreen700; + break; + case WrenchIconPainter::SEVERITY_MEDIUM: + color = gfx::kGoogleYellow700; + break; + case WrenchIconPainter::SEVERITY_HIGH: + color = gfx::kGoogleRed700; + break; + } + + // TODO(estade): find a home for this constant. + const int kButtonSize = 16; + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(gfx::VectorIconId::BROWSER_TOOLS, kButtonSize, + color)); +} + const char* WrenchToolbarButton::GetClassName() const { return "WrenchToolbarButton"; }
diff --git a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h index c8cf28e..49bd103 100644 --- a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h
@@ -56,6 +56,10 @@ // WrenchIconPainter::Delegate: void ScheduleWrenchIconPaint() override; + // Updates the presentation according to |severity_| and the theme provider. + // Only used in MD. + void UpdateIcon(); + // Opens the app menu immediately during a drag-and-drop operation. // Used only in testing. static bool g_open_app_immediately_for_testing; @@ -74,8 +78,12 @@ int OnPerformDrop(const ui::DropTargetEvent& event) override; void OnPaint(gfx::Canvas* canvas) override; + // Only used in pre-MD. scoped_ptr<WrenchIconPainter> wrench_icon_painter_; + // Only used in MD. + WrenchIconPainter::Severity severity_; + // Our owning toolbar view. ToolbarView* toolbar_view_;
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc index 14dd729..5961b224 100644 --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -4,11 +4,8 @@ #include "chrome/browser/ui/webui/crashes_ui.h" -#include <vector> - #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/i18n/time_formatting.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -19,6 +16,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/google_chrome_strings.h" +#include "components/crash/core/browser/crashes_ui_util.h" #include "components/version_info/version_info.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" @@ -28,8 +26,8 @@ #include "grit/components_chromium_strings.h" #include "grit/components_google_chrome_strings.h" #include "grit/components_resources.h" +#include "grit/components_scaled_resources.h" #include "grit/components_strings.h" -#include "grit/theme_resources.h" #include "ui/base/resource/resource_bundle.h" #if defined(OS_CHROMEOS) @@ -46,22 +44,16 @@ content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUICrashesHost); - source->AddLocalizedString("shortProductName", IDS_SHORT_PRODUCT_NAME); - source->AddLocalizedString("crashesTitle", IDS_CRASH_TITLE); - source->AddLocalizedString("crashCountFormat", - IDS_CRASH_CRASH_COUNT_BANNER_FORMAT); - source->AddLocalizedString("crashHeaderFormat", - IDS_CRASH_CRASH_HEADER_FORMAT); - source->AddLocalizedString("crashTimeFormat", IDS_CRASH_CRASH_TIME_FORMAT); - source->AddLocalizedString("bugLinkText", IDS_CRASH_BUG_LINK_LABEL); - source->AddLocalizedString("noCrashesMessage", - IDS_CRASH_NO_CRASHES_MESSAGE); - source->AddLocalizedString("disabledHeader", IDS_CRASH_DISABLED_HEADER); - source->AddLocalizedString("disabledMessage", IDS_CRASH_DISABLED_MESSAGE); - source->AddLocalizedString("uploadCrashesLinkText", - IDS_CRASH_UPLOAD_MESSAGE); + for (size_t i = 0; i < crash::kCrashesUILocalizedStringsCount; ++i) { + source->AddLocalizedString( + crash::kCrashesUILocalizedStrings[i].name, + crash::kCrashesUILocalizedStrings[i].resource_id); + } + + source->AddLocalizedString(crash::kCrashesUIShortProductName, + IDS_SHORT_PRODUCT_NAME); source->SetJsonPath("strings.js"); - source->AddResourcePath("crashes.js", IDR_CRASH_CRASHES_JS); + source->AddResourcePath(crash::kCrashesUICrashesJS, IDR_CRASH_CRASHES_JS); source->SetDefaultResource(IDR_CRASH_CRASHES_HTML); return source; } @@ -115,12 +107,14 @@ void CrashesDOMHandler::RegisterMessages() { upload_list_->LoadUploadListAsynchronously(); - web_ui()->RegisterMessageCallback("requestCrashList", + web_ui()->RegisterMessageCallback( + crash::kCrashesUIRequestCrashList, base::Bind(&CrashesDOMHandler::HandleRequestCrashes, base::Unretained(this))); #if defined(OS_CHROMEOS) - web_ui()->RegisterMessageCallback("requestCrashUpload", + web_ui()->RegisterMessageCallback( + crash::kCrashesUIRequestCrashUpload, base::Bind(&CrashesDOMHandler::HandleRequestUploads, base::Unretained(this))); #endif @@ -156,35 +150,22 @@ void CrashesDOMHandler::UpdateUI() { bool crash_reporting_enabled = ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled(); - base::ListValue crash_list; - bool system_crash_reporter = false; + bool system_crash_reporter = false; #if defined(OS_CHROMEOS) // Chrome OS has a system crash reporter. system_crash_reporter = true; #endif - if (crash_reporting_enabled) { - std::vector<CrashUploadList::UploadInfo> crashes; - upload_list_->GetUploads(50, &crashes); - - for (std::vector<CrashUploadList::UploadInfo>::iterator i = crashes.begin(); - i != crashes.end(); ++i) { - base::DictionaryValue* crash = new base::DictionaryValue(); - crash->SetString("id", i->id); - crash->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time)); - crash->SetString("local_id", i->local_id); - crash_list.Append(crash); - } - } + base::ListValue crash_list; + if (crash_reporting_enabled) + crash::UploadListToValue(upload_list_.get(), &crash_list); base::FundamentalValue enabled(crash_reporting_enabled); base::FundamentalValue dynamic_backend(system_crash_reporter); - base::StringValue version(version_info::GetVersionNumber()); - - web_ui()->CallJavascriptFunction("updateCrashList", enabled, dynamic_backend, - crash_list, version); + web_ui()->CallJavascriptFunction(crash::kCrashesUIUpdateCrashList, enabled, + dynamic_backend, crash_list, version); } } // namespace @@ -206,6 +187,6 @@ // static base::RefCountedMemory* CrashesUI::GetFaviconResourceBytes( ui::ScaleFactor scale_factor) { - return ResourceBundle::GetSharedInstance(). - LoadDataResourceBytesForScale(IDR_SAD_FAVICON, scale_factor); + return ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( + IDR_CRASH_SAD_FAVICON, scale_factor); }
diff --git a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc index 4f4e26b..c6a109c7 100644 --- a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
@@ -24,9 +24,11 @@ IDS_MEDIA_ROUTER_STOP_CASTING_BUTTON); } -void AddIssuesActionsStrings(content::WebUIDataSource* html_source) { +void AddIssuesStrings(content::WebUIDataSource* html_source) { html_source->AddLocalizedString("dismissButton", IDS_MEDIA_ROUTER_DISMISS_BUTTON); + html_source->AddLocalizedString("issueHeader", + IDS_MEDIA_ROUTER_ISSUE_HEADER); html_source->AddLocalizedString("learnMoreButton", IDS_MEDIA_ROUTER_LEARN_MORE_BUTTON); } @@ -47,7 +49,7 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source) { AddMediaRouterStrings(html_source); AddRouteDetailsStrings(html_source); - AddIssuesActionsStrings(html_source); + AddIssuesStrings(html_source); AddMediaRouterContainerStrings(html_source); html_source->SetJsonPath(kLocalizedStringsFile); }
diff --git a/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js b/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js index e8a5b0fa..5a134ec 100644 --- a/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js +++ b/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN('#include "chrome/browser/ui/webui/options/' + + 'single_language_options_browsertest.h"'); + /** * TestFixture for testing messages of dictionary download progress in language * options WebUI. @@ -18,6 +21,9 @@ */ browsePreload: 'chrome://settings-frame/languages', + /** @override */ + typedefCppFixture: 'SingleLanguageOptionsBrowserTest', + /** * Register a mock dictionary handler. */
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc index da869f57..2ce5747 100644 --- a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc +++ b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc
@@ -38,12 +38,6 @@ std::string()); } -void MultilanguageOptionsBrowserTest::SetUpCommandLine( - base::CommandLine* command_line) { - WebUIBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kEnableMultilingualSpellChecker); -} - void MultilanguageOptionsBrowserTest::SetDictionariesPref( const base::ListValue& value) { browser()->profile()->GetPrefs()->Set(prefs::kSpellCheckDictionaries, value);
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h index 7f19e17..2ea4c66e 100644 --- a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h +++ b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h
@@ -19,7 +19,7 @@ void ClearSpellcheckDictionaries(); private: - void SetUpCommandLine(base::CommandLine* command_line) override; + // WebUIBrowserTest implementation. void SetUpOnMainThread() override; void SetDictionariesPref(const base::ListValue& value);
diff --git a/chrome/browser/ui/webui/options/single_language_options_browsertest.cc b/chrome/browser/ui/webui/options/single_language_options_browsertest.cc new file mode 100644 index 0000000..50e384e1 --- /dev/null +++ b/chrome/browser/ui/webui/options/single_language_options_browsertest.cc
@@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/options/single_language_options_browsertest.h" + +#include "base/command_line.h" +#include "chrome/common/chrome_switches.h" + +SingleLanguageOptionsBrowserTest::SingleLanguageOptionsBrowserTest() {} + +SingleLanguageOptionsBrowserTest::~SingleLanguageOptionsBrowserTest() {} + +void SingleLanguageOptionsBrowserTest::SetUpCommandLine( + base::CommandLine* command_line) { + WebUIBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(switches::kDisableMultilingualSpellChecker); +}
diff --git a/chrome/browser/ui/webui/options/single_language_options_browsertest.h b/chrome/browser/ui/webui/options/single_language_options_browsertest.h new file mode 100644 index 0000000..c992c16c --- /dev/null +++ b/chrome/browser/ui/webui/options/single_language_options_browsertest.h
@@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_SINGLE_LANGUAGE_OPTIONS_BROWSERTEST_H_ +#define CHROME_BROWSER_UI_WEBUI_OPTIONS_SINGLE_LANGUAGE_OPTIONS_BROWSERTEST_H_ + +#include "base/macros.h" +#include "chrome/test/base/web_ui_browser_test.h" + +// This is a helper class for language_options_webui_browsertest.js to disable +// multilingual-spellchecker. +class SingleLanguageOptionsBrowserTest : public WebUIBrowserTest { + public: + SingleLanguageOptionsBrowserTest(); + ~SingleLanguageOptionsBrowserTest() override; + + private: + // WebUIBrowserTest implementation. + void SetUpCommandLine(base::CommandLine* command_line) override; + + DISALLOW_COPY_AND_ASSIGN(SingleLanguageOptionsBrowserTest); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_SINGLE_LANGUAGE_OPTIONS_BROWSERTEST_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index c16a2917..149226f7 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -545,6 +545,8 @@ 'browser/install_verification/win/module_list.h', 'browser/install_verification/win/module_verification_common.cc', 'browser/install_verification/win/module_verification_common.h', + 'browser/interests/android/interests_service.cc', + 'browser/interests/android/interests_service.h', 'browser/interests/interests_fetcher.cc', 'browser/interests/interests_fetcher.h', 'browser/internal_auth.cc', @@ -1783,6 +1785,7 @@ 'android/java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java', 'android/java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java', 'android/java/src/org/chromium/chrome/browser/ntp/LogoBridge.java', + 'android/java/src/org/chromium/chrome/browser/ntp/InterestsService.java', 'android/java/src/org/chromium/chrome/browser/ntp/NewTabPagePrefs.java', 'android/java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java', 'android/java/src/org/chromium/chrome/browser/infobar/DownloadOverwriteInfoBar.java', @@ -2854,22 +2857,12 @@ 'browser/sync/glue/autofill_data_type_controller.h', 'browser/sync/glue/autofill_profile_data_type_controller.cc', 'browser/sync/glue/autofill_profile_data_type_controller.h', - 'browser/sync/glue/bookmark_change_processor.cc', - 'browser/sync/glue/bookmark_change_processor.h', - 'browser/sync/glue/bookmark_data_type_controller.cc', - 'browser/sync/glue/bookmark_data_type_controller.h', - 'browser/sync/glue/bookmark_model_associator.cc', - 'browser/sync/glue/bookmark_model_associator.h', - 'browser/sync/glue/chrome_report_unrecoverable_error.cc', - 'browser/sync/glue/chrome_report_unrecoverable_error.h', 'browser/sync/glue/extensions_activity_monitor.cc', 'browser/sync/glue/extensions_activity_monitor.h', 'browser/sync/glue/history_delete_directives_data_type_controller.cc', 'browser/sync/glue/history_delete_directives_data_type_controller.h', 'browser/sync/glue/local_device_info_provider_impl.cc', 'browser/sync/glue/local_device_info_provider_impl.h', - 'browser/sync/glue/non_frontend_data_type_controller.cc', - 'browser/sync/glue/non_frontend_data_type_controller.h', 'browser/sync/glue/password_data_type_controller.cc', 'browser/sync/glue/password_data_type_controller.h', 'browser/sync/glue/search_engine_data_type_controller.cc', @@ -3108,6 +3101,7 @@ '../components/components.gyp:content_settings_core_common', '../components/components.gyp:crx_file', '../components/components.gyp:data_reduction_proxy_core_browser', + '../components/components.gyp:data_usage_core', '../components/components.gyp:data_use_measurement_core', '../components/components.gyp:domain_reliability', '../components/components.gyp:enhanced_bookmarks', @@ -3143,6 +3137,7 @@ '../components/components.gyp:suggestions', '../components/components.gyp:signin_core_browser', '../components/components.gyp:startup_metric_utils', + '../components/components.gyp:sync_bookmarks', '../components/components.gyp:sync_driver', '../components/components.gyp:translate_core_browser', '../components/components.gyp:translate_core_common',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index ce1ee3ab0..a12430c7 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -1429,6 +1429,10 @@ 'browser/ui/cocoa/ui_localizer.mm', 'browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.h', 'browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.mm', + # TODO(estade): this class should be folded into + # manage_passwords_decoration.mm + 'browser/ui/passwords/manage_passwords_icon.cc', + 'browser/ui/passwords/manage_passwords_icon.h', 'browser/ui/startup/autolaunch_prompt.cc', 'browser/ui/web_contents_sizer.mm', ], @@ -1617,8 +1621,7 @@ 'browser/ui/panels/stacked_panel_drag_handler.h', 'browser/ui/passwords/manage_passwords_bubble_model.cc', 'browser/ui/passwords/manage_passwords_bubble_model.h', - 'browser/ui/passwords/manage_passwords_icon.cc', - 'browser/ui/passwords/manage_passwords_icon.h', + 'browser/ui/passwords/manage_passwords_icon_view.h', 'browser/ui/passwords/manage_passwords_view_utils_desktop.cc', 'browser/ui/passwords/manage_passwords_view_utils_desktop.h', 'browser/ui/pdf/adobe_reader_info_win.cc', @@ -2305,8 +2308,8 @@ 'browser/ui/views/passwords/manage_password_items_view.h', 'browser/ui/views/passwords/manage_passwords_bubble_view.cc', 'browser/ui/views/passwords/manage_passwords_bubble_view.h', - 'browser/ui/views/passwords/manage_passwords_icon_view.cc', - 'browser/ui/views/passwords/manage_passwords_icon_view.h', + 'browser/ui/views/passwords/manage_passwords_icon_views.cc', + 'browser/ui/views/passwords/manage_passwords_icon_views.h', 'browser/ui/views/process_singleton_dialog_linux.cc', 'browser/ui/views/profiles/avatar_menu_button.cc', 'browser/ui/views/profiles/avatar_menu_button.h', @@ -2361,6 +2364,8 @@ 'browser/ui/views/tabs/tab_strip.cc', 'browser/ui/views/tabs/tab_strip.h', 'browser/ui/views/tabs/tab_strip_controller.h', + 'browser/ui/views/tabs/tab_strip_layout.cc', + 'browser/ui/views/tabs/tab_strip_layout.h', 'browser/ui/views/tabs/window_finder.h', 'browser/ui/views/tabs/window_finder_chromeos.cc', 'browser/ui/views/tabs/window_finder_mac.mm', @@ -2816,6 +2821,7 @@ 'installer_util', '../components/components.gyp:app_modal', '../components/components.gyp:autofill_content_risk_proto', + '../components/components.gyp:crash_core_browser', '../components/components.gyp:flags_ui', '../components/components.gyp:net_log', '../components/components.gyp:page_load_metrics_browser',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 4fd9894..de1cde48 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi
@@ -119,6 +119,8 @@ 'common/variations/variations_util.h', 'common/web_application_info.cc', 'common/web_application_info.h', + 'common/widevine_cdm_constants.cc', + 'common/widevine_cdm_constants.h', 'common/worker_thread_ticker.cc', 'common/worker_thread_ticker.h', ],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 672373dc..4668ad15 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -564,6 +564,8 @@ 'browser/ui/webui/options/options_browsertest.cc', 'browser/ui/webui/options/options_ui_browsertest.cc', 'browser/ui/webui/options/options_ui_browsertest.h', + 'browser/ui/webui/options/single_language_options_browsertest.cc', + 'browser/ui/webui/options/single_language_options_browsertest.h', 'browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc', 'browser/ui/webui/print_preview/print_preview_ui_browsertest.cc', 'browser/ui/webui/signin/inline_login_ui_browsertest.cc', @@ -701,6 +703,7 @@ 'browser/chromeos/file_manager/zip_file_creator_browsertest.cc', 'browser/chromeos/first_run/chromeos_first_run_browsertest.cc', 'browser/chromeos/first_run/drive_first_run_browsertest.cc', + 'browser/chromeos/first_run/goodies_displayer_browsertest.cc', 'browser/chromeos/input_method/input_method_engine_browsertests.cc', 'browser/chromeos/input_method/mode_indicator_browsertest.cc', 'browser/chromeos/login/crash_restore_browsertest.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 59b77d7..80ea4f73 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -227,8 +227,6 @@ 'browser/sync/glue/browser_thread_model_worker_unittest.cc', 'browser/sync/glue/frontend_data_type_controller_unittest.cc', 'browser/sync/glue/local_device_info_provider_unittest.cc', - 'browser/sync/glue/non_frontend_data_type_controller_mock.cc', - 'browser/sync/glue/non_frontend_data_type_controller_mock.h', 'browser/sync/glue/non_frontend_data_type_controller_unittest.cc', 'browser/sync/glue/search_engine_data_type_controller_unittest.cc', 'browser/sync/glue/sync_backend_host_impl_unittest.cc', @@ -570,6 +568,7 @@ 'browser/spellchecker/spellcheck_service_unittest.cc', 'browser/spellchecker/spelling_service_client_unittest.cc', 'browser/spellchecker/word_trimmer_unittest.cc', + 'common/spellcheck_common_unittest.cc', 'renderer/spellchecker/custom_dictionary_engine_unittest.cc', 'renderer/spellchecker/spellcheck_multilingual_unittest.cc', 'renderer/spellchecker/spellcheck_provider_hunspell_unittest.cc', @@ -1384,6 +1383,7 @@ 'browser/ui/views/tabs/fake_base_tab_strip_controller.cc', 'browser/ui/views/tabs/fake_base_tab_strip_controller.h', 'browser/ui/views/tabs/stacked_tab_strip_layout_unittest.cc', + 'browser/ui/views/tabs/tab_strip_layout_unittest.cc', 'browser/ui/views/tabs/tab_strip_unittest.cc', 'browser/ui/views/tabs/tab_unittest.cc', 'browser/ui/views/toolbar/reload_button_unittest.cc', @@ -1539,8 +1539,6 @@ 'browser/ui/omnibox/omnibox_edit_unittest.cc', 'browser/ui/panels/panel_mouse_watcher_unittest.cc', 'browser/ui/passwords/manage_passwords_bubble_model_unittest.cc', - 'browser/ui/passwords/manage_passwords_icon_mock.cc', - 'browser/ui/passwords/manage_passwords_icon_mock.h', 'browser/ui/passwords/manage_passwords_view_utils_desktop_unittest.cc', 'browser/ui/search/instant_page_unittest.cc', 'browser/ui/search/instant_search_prerenderer_unittest.cc', @@ -2672,6 +2670,7 @@ '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput', ], 'sources!': [ + 'common/spellcheck_common_unittest.cc', 'renderer/spellchecker/spellcheck_multilingual_unittest.cc', 'renderer/spellchecker/spellcheck_provider_hunspell_unittest.cc', 'renderer/spellchecker/spellcheck_unittest.cc',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index c3d345d..2d819521 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -282,8 +282,6 @@ "pref_font_webkit_names.h", "pref_names.cc", "pref_names.h", - "widevine_cdm_constants.cc", - "widevine_cdm_constants.h", ] public_deps = [ @@ -300,6 +298,20 @@ if (enable_nacl) { deps += [ "//components/nacl:nacl_switches" ] } + + if (is_android) { + # This dependency must only be added for Android. + # + # On Windows, //chrome/installer/util depends on this target to get + # constants. That target is in turn used in a number of installer helper + # targets independent of Chrome that we want to keep small. So we don't + # want something large like //ui/base. + # + # Android doesn't have this structure and corresponding size limitation + # on this target. On that platform one of the Chrome paths forwards to one + # implemented in //ui/base, so we need that dependency. + deps += [ "//ui/base" ] + } } source_set("test_support") {
diff --git a/chrome/common/OWNERS b/chrome/common/OWNERS index 3a447e2..a6396e5 100644 --- a/chrome/common/OWNERS +++ b/chrome/common/OWNERS
@@ -27,8 +27,8 @@ # Spellcheck files. Not using spellcheck* since it covers IPC messages too. per-file spellcheck_bdict_language.h=groby@chromium.org per-file spellcheck_bdict_language.h=rouslan@chromium.org -per-file spellcheck_common.*=groby@chromium.org -per-file spellcheck_common.*=rouslan@chromium.org +per-file spellcheck_common*=groby@chromium.org +per-file spellcheck_common*=rouslan@chromium.org per-file spellcheck_marker.h=groby@chromium.org per-file spellcheck_marker.h=rouslan@chromium.org per-file spellcheck_result.h=groby@chromium.org
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 1ecb0a0..f28a320 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc
@@ -15,12 +15,12 @@ #include "base/version.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths_internal.h" -#include "chrome/common/widevine_cdm_constants.h" -#include "ui/base/ui_base_paths.h" #if defined(OS_ANDROID) #include "base/android/path_utils.h" #include "base/base_paths_android.h" +// ui/base must only be used on Android. See BUILD.gn for dependency info. +#include "ui/base/ui_base_paths.h" // nogncheck #endif #if defined(OS_MACOSX) @@ -364,7 +364,7 @@ case chrome::DIR_COMPONENT_WIDEVINE_CDM: if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) return false; - cur = cur.Append(kWidevineCdmBaseDirectory); + cur = cur.Append(FILE_PATH_LITERAL("WidevineCDM")); break; #endif // defined(WIDEVINE_CDM_IS_COMPONENT) // TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings.
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 843bbac..189ab43 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -1027,6 +1027,10 @@ const char kEnableAndroidSpellChecker[] = "enable-android-spellchecker"; #endif +// Disables the multilingual spellchecker. +const char kDisableMultilingualSpellChecker[] = + "disable-multilingual-spellchecker"; + // Enables the multilingual spellchecker. const char kEnableMultilingualSpellChecker[] = "enable-multilingual-spellchecker"; @@ -1358,11 +1362,17 @@ bool MediaRouterEnabled() { #if defined(ENABLE_MEDIA_ROUTER) + +#if defined(OS_ANDROID) + return true; +#else return base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableMediaRouter); +#endif // defined(OS_ANDROID). + #else return false; -#endif +#endif // defined(ENABLE_MEDIA_ROUTER) } bool PdfMaterialUIEnabled() {
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f66b3d3f..7c5691d 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -286,6 +286,7 @@ #if defined(OS_ANDROID) extern const char kEnableAndroidSpellChecker[]; #endif +extern const char kDisableMultilingualSpellChecker[]; extern const char kEnableMultilingualSpellChecker[]; extern const char kEnableSpellingAutoCorrect[]; extern const char kEnableSpellingFeedbackFieldTrial[];
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl index f35b25c..fa189aee 100644 --- a/chrome/common/extensions/api/notifications.idl +++ b/chrome/common/extensions/api/notifications.idl
@@ -181,11 +181,12 @@ // The user pressed a button in the notification. static void onButtonClicked(DOMString notificationId, long buttonIndex); - // The user changes the permission level. + // The user changes the permission level. As of Chrome 47, only ChromeOS + // has UI that dispatches this event. static void onPermissionLevelChanged(PermissionLevel level); - // The user clicked on a link for the app's notification settings. + // The user clicked on a link for the app's notification settings. As of + // Chrome 47, only ChromeOS has UI that dispatches this event. static void onShowSettings(); }; - };
diff --git a/chrome/common/spellcheck_common.cc b/chrome/common/spellcheck_common.cc index 9aa3a02..cee0883 100644 --- a/chrome/common/spellcheck_common.cc +++ b/chrome/common/spellcheck_common.cc
@@ -8,6 +8,8 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/macros.h" +#include "base/metrics/field_trial.h" +#include "base/strings/string_util.h" #include "chrome/common/chrome_switches.h" #include "third_party/icu/source/common/unicode/uloc.h" #include "third_party/icu/source/common/unicode/urename.h" @@ -16,6 +18,8 @@ namespace chrome { namespace spellcheck_common { +const char kMultilingualSpellcheckFieldTrial[] = "MultilingualSpellcheck"; + struct LanguageRegion { const char* language; // The language. const char* language_region; // language & region, used by dictionaries. @@ -184,8 +188,21 @@ } bool IsMultilingualSpellcheckEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableMultilingualSpellChecker); + // TODO(rouslan): Remove field trial and command line flags when M49 is + // stable. + const std::string& group_name = + base::FieldTrialList::FindFullName(kMultilingualSpellcheckFieldTrial); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableMultilingualSpellChecker)) { + return false; + } + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableMultilingualSpellChecker)) { + return true; + } + // Enabled by default, but can be disabled in field trial. + return !base::StartsWith(group_name, "Disabled", + base::CompareCase::INSENSITIVE_ASCII); } } // namespace spellcheck_common
diff --git a/chrome/common/spellcheck_common.h b/chrome/common/spellcheck_common.h index 7254c8c..deb3617 100644 --- a/chrome/common/spellcheck_common.h +++ b/chrome/common/spellcheck_common.h
@@ -39,6 +39,9 @@ // dictionary. static const size_t MAX_CUSTOM_DICTIONARY_WORD_BYTES = 99; +// The name of the field trial for multilingual spellchecker. +extern const char kMultilingualSpellcheckFieldTrial[]; + base::FilePath GetVersionedFileName(const std::string& input_language, const base::FilePath& dict_dir);
diff --git a/chrome/common/spellcheck_common_unittest.cc b/chrome/common/spellcheck_common_unittest.cc new file mode 100644 index 0000000..4f877c55 --- /dev/null +++ b/chrome/common/spellcheck_common_unittest.cc
@@ -0,0 +1,51 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/spellcheck_common.h" + +#include "base/command_line.h" +#include "base/metrics/field_trial.h" +#include "chrome/common/chrome_switches.h" +#include "components/variations/entropy_provider.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +using chrome::spellcheck_common::IsMultilingualSpellcheckEnabled; +using chrome::spellcheck_common::kMultilingualSpellcheckFieldTrial; + +TEST(SpellcheckCommonTest, MultilingualByDefault) { + EXPECT_TRUE(IsMultilingualSpellcheckEnabled()); +} + +TEST(SpellcheckCommonTest, CanDisableMultlingualInFieldTrial) { + base::FieldTrialList trials(new metrics::SHA1EntropyProvider("foo")); + scoped_refptr<base::FieldTrial> trial = + base::FieldTrialList::CreateFieldTrial(kMultilingualSpellcheckFieldTrial, + "Disabled"); + trial->group(); + + EXPECT_FALSE(IsMultilingualSpellcheckEnabled()); +} + +TEST(SpellcheckCommonTest, CanDisableMultlingualFromCommandLine) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableMultilingualSpellChecker); + + EXPECT_FALSE(IsMultilingualSpellcheckEnabled()); +} + +TEST(SpellcheckCommonTest, CanForceMultlingualFromCommandLine) { + base::FieldTrialList trials(new metrics::SHA1EntropyProvider("foo")); + scoped_refptr<base::FieldTrial> trial = + base::FieldTrialList::CreateFieldTrial(kMultilingualSpellcheckFieldTrial, + "Disabled"); + trial->group(); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableMultilingualSpellChecker); + + EXPECT_TRUE(IsMultilingualSpellcheckEnabled()); +} + +} // namespace
diff --git a/chrome/common/widevine_cdm_constants.cc b/chrome/common/widevine_cdm_constants.cc index 60f487e..44f0b7d 100644 --- a/chrome/common/widevine_cdm_constants.cc +++ b/chrome/common/widevine_cdm_constants.cc
@@ -7,9 +7,6 @@ #include "build/build_config.h" #include "ppapi/shared_impl/ppapi_permissions.h" -const base::FilePath::CharType kWidevineCdmBaseDirectory[] = - FILE_PATH_LITERAL("WidevineCDM"); - const char kWidevineCdmPluginExtension[] = ""; const int32 kWidevineCdmPluginPermissions = ppapi::PERMISSION_DEV |
diff --git a/chrome/common_constants.gyp b/chrome/common_constants.gyp index ce5c0143..4e79cdd 100644 --- a/chrome/common_constants.gyp +++ b/chrome/common_constants.gyp
@@ -32,8 +32,6 @@ 'common/pref_font_webkit_names.h', 'common/pref_names.cc', 'common/pref_names.h', - 'common/widevine_cdm_constants.cc', - 'common/widevine_cdm_constants.h', ], 'actions': [ {
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn index f64186c..e1578f1b 100644 --- a/chrome/installer/util/BUILD.gn +++ b/chrome/installer/util/BUILD.gn
@@ -14,6 +14,10 @@ "//content/public/common:result_codes", ] + # The constants target checks the Chrome distribution from this target. Both + # targets have to be linked together in practice. + allow_circular_includes_from = [ "//chrome/common:constants" ] + if (is_win) { # TODO(GYP) installer_util on Windows. # This is a bit tricky. It seems that what's currently called
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 7dda2788..227e244 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -42,6 +42,7 @@ using blink::WebVector; namespace autofill { +namespace form_util { namespace { @@ -4128,4 +4129,5 @@ &form, nullptr)); } +} // namespace form_util } // namespace autofill
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 04b5bb4..66a939cd 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -748,19 +748,19 @@ frame = GetMainFrame(); frame->document().forms(forms1); ASSERT_EQ(1u, forms1.size()); - EXPECT_TRUE(IsWebNodeVisible(forms1[0])); + EXPECT_TRUE(form_util::IsWebNodeVisible(forms1[0])); LoadHTML(kEmptyFormHTML); frame = GetMainFrame(); frame->document().forms(forms2); ASSERT_EQ(1u, forms2.size()); - EXPECT_FALSE(IsWebNodeVisible(forms2[0])); + EXPECT_FALSE(form_util::IsWebNodeVisible(forms2[0])); LoadHTML(kNonVisibleFormHTML); frame = GetMainFrame(); frame->document().forms(forms3); ASSERT_EQ(1u, forms3.size()); - EXPECT_FALSE(IsWebNodeVisible(forms3[0])); + EXPECT_FALSE(form_util::IsWebNodeVisible(forms3[0])); } TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) { @@ -1754,9 +1754,9 @@ // Find FormData for visible password form. blink::WebFormElement form_element = username_element_.form(); FormData form_data; - ASSERT_TRUE(WebFormElementToFormData(form_element, - blink::WebFormControlElement(), - EXTRACT_NONE, &form_data, nullptr)); + ASSERT_TRUE( + WebFormElementToFormData(form_element, blink::WebFormControlElement(), + form_util::EXTRACT_NONE, &form_data, nullptr)); // Simulate Autofill predictions: the first field is username, the third // one is password. std::map<autofill::FormData, PasswordFormFieldPredictionMap> predictions; @@ -2012,9 +2012,9 @@ // Find FormData for visible form. blink::WebFormElement form_element = credit_card_number_element.form(); FormData form_data; - ASSERT_TRUE(WebFormElementToFormData(form_element, - blink::WebFormControlElement(), - EXTRACT_NONE, &form_data, nullptr)); + ASSERT_TRUE( + WebFormElementToFormData(form_element, blink::WebFormControlElement(), + form_util::EXTRACT_NONE, &form_data, nullptr)); // Simulate Autofill predictions: the third field is not a password. std::map<autofill::FormData, PasswordFormFieldPredictionMap> predictions; predictions[form_data][form_data.fields[2]] = PREDICTION_NOT_PASSWORD; @@ -2207,7 +2207,7 @@ document.forms(forms); blink::WebFormElement form_element = forms[0]; std::vector<blink::WebFormControlElement> control_elements = - ExtractAutofillableElementsInForm(form_element); + form_util::ExtractAutofillableElementsInForm(form_element); bool has_fillable_username = (kEmpty != test_case.fill_data_username_field_name); if (has_fillable_username) {
diff --git a/chrome/renderer/autofill/password_generation_test_utils.cc b/chrome/renderer/autofill/password_generation_test_utils.cc index 4f2f38e..339dfe3 100644 --- a/chrome/renderer/autofill/password_generation_test_utils.cc +++ b/chrome/renderer/autofill/password_generation_test_utils.cc
@@ -34,11 +34,9 @@ document.forms(web_forms); autofill::FormData form_data; - WebFormElementToFormData(web_forms[form_index], - blink::WebFormControlElement(), - EXTRACT_NONE, - &form_data, - nullptr /* FormFieldData */); + WebFormElementToFormData( + web_forms[form_index], blink::WebFormControlElement(), + form_util::EXTRACT_NONE, &form_data, nullptr /* FormFieldData */); std::vector<autofill::FormData> forms; forms.push_back(form_data);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 9d36c566..bf23141 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -640,6 +640,61 @@ # TODO(GYP): Delete this after we've converted everything to GN. # The _run targets exist only for compatibility w/ GYP. + group("telemetry_perf_unittests_run") { + testonly = true + deps = [ + ":telemetry_perf_unittests", + ] + } + + group("telemetry_chrome_deps") { + data_deps = [ + # TODO(kbr): this used to be "//chrome". Had to change this to + # chrome_initial temporarily to work around crbug.com/536192. + "//chrome:chrome_initial", + "//tools/telemetry:bitmaptools", + ] + + if (is_linux) { + data_deps += [ "//tools/xdisplaycheck" ] + } + } + + group("telemetry_perf_unittests") { + deps = [ + "//tools/telemetry:telemetry_test_support", + ":telemetry_chrome_deps", + ":telemetry_binary_deps", + ] + + data = [ + "//tools/perf/", + + # Field trial config + "//tools/variations/", + + # For isolate contract. + "//testing/scripts/common.py", + "//testing/xvfb.py", + "//testing/scripts/run_telemetry_as_googletest.py", + ] + + if (is_win && (symbol_level == 1 || symbol_level == 2)) { + # TODO(GYP): These should be provided automatically through data_deps. + data += [ "$root_out_dir/chrome.exe.pdb" ] + if (is_component_build) { + data += [ + "$root_out_dir/base.dll.pdb", + "$root_out_dir/blink_platform.dll.pdb", + "$root_out_dir/blink_web.dll.pdb", + "$root_out_dir/content.dll.pdb", + ] + } + } + } + + # TODO(GYP): Delete this after we've converted everything to GN. + # The _run targets exist only for compatibility w/ GYP. group("telemetry_gpu_test_run") { testonly = true deps = [ @@ -651,12 +706,7 @@ deps = [ "//tools/telemetry:telemetry_test_support", ":telemetry_binary_deps", - ] - data_deps = [ - # TODO(kbr): this used to be "//chrome". Had to change this to - # chrome_initial temporarily to work around crbug.com/536192. - "//chrome:chrome_initial", - "//tools/telemetry:bitmaptools", + ":telemetry_chrome_deps", ] data = [ @@ -718,6 +768,7 @@ # From telemetry_gpu_unittests.isolate "//third_party/typ/", "//testing/scripts/common.py", + "//testing/xvfb.py", "//testing/scripts/run_telemetry_as_googletest.py", ] } @@ -1050,11 +1101,8 @@ ] } if (enable_media_router) { - sources += rebase_path( - chrome_tests_gypi_values.chrome_browser_tests_media_router_sources, - ".", - "//chrome") - deps += [ "//chrome/browser/media/router:test_support" ] + sources += [ "../browser/ui/webui/media_router/media_router_dialog_controller_impl_browsertest.cc" ] + deps += [ "//chrome/test/media_router:media_router_browsertests" ] } if (is_win) { deps += [ @@ -1153,6 +1201,7 @@ sources -= [ "../browser/policy/cloud/component_cloud_policy_browsertest.cc", "../browser/prefs/pref_hash_browsertest.cc", + "../common/spellcheck_common_unittest.cc", "../renderer/spellchecker/spellcheck_provider_hunspell_unittest.cc", "../renderer/spellchecker/spellcheck_unittest.cc", ]
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/OWNERS b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/OWNERS new file mode 100644 index 0000000..fbe7b0c --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/OWNERS
@@ -0,0 +1,5 @@ +maxbogue@chromium.org +nyquist@chromium.org +pvalenzuela@chromium.org +yfriedman@chromium.org +zea@chromium.org
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java index fd4e2132..26d9ea63 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java
@@ -15,17 +15,13 @@ import org.chromium.base.CommandLine; import org.chromium.base.ThreadUtils; -import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.test.util.TestHttpServerClient; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; -import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; -import org.chromium.sync.test.util.AccountHolder; -import org.chromium.sync.test.util.MockAccountManager; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -45,9 +41,6 @@ * Utility class for shared sync test functionality. */ public final class SyncTestUtil { - - public static final String DEFAULT_TEST_ACCOUNT = "test@gmail.com"; - public static final String DEFAULT_PASSWORD = "myPassword"; private static final String TAG = "SyncTestUtil"; public static final long UI_TIMEOUT_MS = scaleTimeout(20000); @@ -283,37 +276,6 @@ } /** - * Sets up a test Google account on the device with specified auth token types. - */ - public static Account setupTestAccount(MockAccountManager accountManager, String accountName, - String password, String... allowedAuthTokenTypes) { - Account account = AccountManagerHelper.createAccountFromName(accountName); - AccountHolder.Builder accountHolder = - AccountHolder.create().account(account).password(password); - if (allowedAuthTokenTypes != null) { - // Auto-allowing provided auth token types - for (String authTokenType : allowedAuthTokenTypes) { - accountHolder.hasBeenAccepted(authTokenType, true); - } - } - accountManager.addAccountHolderExplicitly(accountHolder.build()); - return account; - } - - /** - * Sets up a test Google account on the device, that accepts all auth tokens. - */ - public static Account setupTestAccountThatAcceptsAllAuthTokens( - MockAccountManager accountManager, - String accountName, String password) { - Account account = AccountManagerHelper.createAccountFromName(accountName); - AccountHolder.Builder accountHolder = - AccountHolder.create().account(account).password(password).alwaysAccept(true); - accountManager.addAccountHolderExplicitly(accountHolder.build()); - return account; - } - - /** * Returns whether the sync engine has keep everything synced set to true. */ public static boolean isSyncEverythingEnabled(final Context context) { @@ -496,23 +458,4 @@ return mAboutInfo; } } - - /** - * Helper class used to create a mock account on the device. - */ - public static class SyncTestContext extends AdvancedMockContext { - - public SyncTestContext(Context context) { - super(context); - } - - @Override - public Object getSystemService(String name) { - if (Context.ACCOUNT_SERVICE.equals(name)) { - throw new UnsupportedOperationException( - "Sync tests should not use system Account Manager."); - } - return super.getSystemService(name); - } - } }
diff --git a/chrome/test/chromedriver/VERSION b/chrome/test/chromedriver/VERSION index 15a3e92..a4b5a6f4a 100644 --- a/chrome/test/chromedriver/VERSION +++ b/chrome/test/chromedriver/VERSION
@@ -1 +1 @@ -2.19 +2.20
diff --git a/chrome/test/data/webrtc/peerconnection.js b/chrome/test/data/webrtc/peerconnection.js index 00c0306..5787188 100644 --- a/chrome/test/data/webrtc/peerconnection.js +++ b/chrome/test/data/webrtc/peerconnection.js
@@ -5,12 +5,6 @@ */ /** - * We need a STUN server for some API calls. - * @private - */ -var STUN_SERVER = 'stun.l.google.com:19302'; - -/** * The one and only peer connection in this page. * @private */ @@ -40,7 +34,7 @@ if (gPeerConnection != null) throw failTest('creating peer connection, but we already have one.'); - gPeerConnection = createPeerConnection_(STUN_SERVER); + gPeerConnection = createPeerConnection_(); returnToTest('ok-peerconnection-created'); } @@ -234,10 +228,9 @@ // Internals. /** @private */ -function createPeerConnection_(stun_server) { - servers = {iceServers: [{url: 'stun:' + stun_server}]}; +function createPeerConnection_() { try { - peerConnection = new RTCPeerConnection(servers, {}); + peerConnection = new RTCPeerConnection(null, {}); } catch (exception) { throw failTest('Failed to create peer connection: ' + exception); }
diff --git a/chrome/test/data/webui/media_router/issue_banner_tests.js b/chrome/test/data/webui/media_router/issue_banner_tests.js index 182956746..98c8ef37 100644 --- a/chrome/test/data/webui/media_router/issue_banner_tests.js +++ b/chrome/test/data/webui/media_router/issue_banner_tests.js
@@ -163,6 +163,15 @@ MockInteractions.tap(banner.$['opt-button']); }); + // Tests for 'close-button-click' event firing when the close button + // is clicked. + test('close button click', function(done) { + banner.addEventListener('close-button-click', function() { + done(); + }); + MockInteractions.tap(banner.$['close-button']); + }); + // Tests the issue text. While the UI will show only the blocking or // non-blocking interface, the issue's info will be set if specified. test('issue text', function() { @@ -186,18 +195,22 @@ // The blocking UI should be shown along with an optional action. banner.issue = fakeBlockingIssueOne; checkButtonVisibility(fakeBlockingIssueOne.secondaryActionType); + assertFalse(banner.$['issue-header'].hasAttribute('hidden')); // The blocking UI should be shown without an optional action. banner.issue = fakeBlockingIssueTwo; checkButtonVisibility(fakeBlockingIssueTwo.secondaryActionType); + assertFalse(banner.$['issue-header'].hasAttribute('hidden')); // The non-blocking UI should be shown along with an optional action. banner.issue = fakeNonBlockingIssueOne; checkButtonVisibility(fakeNonBlockingIssueOne.secondaryActionType); + assertTrue(banner.$['issue-header'].hasAttribute('hidden')); // The non-blocking UI should be shown without an optional action. banner.issue = fakeNonBlockingIssueTwo; checkButtonVisibility(fakeNonBlockingIssueTwo.secondaryActionType); + assertTrue(banner.$['issue-header'].hasAttribute('hidden')); }); }); }
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn new file mode 100644 index 0000000..01fd6edd --- /dev/null +++ b/chrome/test/media_router/BUILD.gn
@@ -0,0 +1,50 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Browser test resource files. +media_router_integration_test_resources = [ + "resources/basic_test.html", + "resources/common.js", + "resources/fail_create_route.html", + "resources/fail_create_route.json", + "resources/fail_reconnect_session.html", + "resources/fail_reconnect_session.json", + "resources/no_provider.html", + "resources/no_provider.json", +] + +# GYP version: chrome/test/media_router/media_router_tests.gypi: +# media_router_integration_test_files +copy("browser_tests_resource_files") { + # This list corresponds to media_router_integration_test_resources in + # media_router_integration_test_files target in GYP. + sources = media_router_integration_test_resources + outputs = [ + "$root_out_dir/media_router/browser_test_resources/{{source_file_part}}", + ] +} + +source_set("media_router_browsertests") { + testonly = true + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + sources = [ + "media_router_base_browsertest.cc", + "media_router_base_browsertest.h", + "media_router_e2e_browsertest.cc", + "media_router_e2e_browsertest.h", + "media_router_integration_browsertest.cc", + "media_router_integration_browsertest.h", + "media_router_integration_ui_browsertest.cc", + "test_media_sinks_observer.cc", + "test_media_sinks_observer.h", + ] + deps = [ + ":browser_tests_resource_files", + "//chrome/browser/media/router:test_support", + "//chrome/test:test_support", + "//chrome/test:test_support_ui", + "//skia", + "//testing/gtest", + ] +}
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc index 883dfd6..99beb38 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -18,14 +18,12 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/generated_resources.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" #include "net/base/filename_util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/l10n/l10n_util.h" namespace media_router { @@ -227,6 +225,36 @@ base::Unretained(this)))); } +bool MediaRouterIntegrationBrowserTest::IsUIShowingIssue() { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* dialog_contents = GetMRDialog(web_contents); + std::string script = base::StringPrintf( + "domAutomationController.send(window.document.getElementById(" + "'media-router-container').issue != undefined)"); + bool has_issue = false; + CHECK(content::ExecuteScriptAndExtractBool(dialog_contents, script, + &has_issue)); + return has_issue; +} + +void MediaRouterIntegrationBrowserTest::WaitUntilIssue() { + ASSERT_TRUE(ConditionalWait( + base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1), + base::Bind(&MediaRouterIntegrationBrowserTest::IsUIShowingIssue, + base::Unretained(this)))); +} + +std::string MediaRouterIntegrationBrowserTest::GetIssueTitle() { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* dialog_contents = GetMRDialog(web_contents); + std::string script = base::StringPrintf( + "domAutomationController.send(window.document.getElementById(" + "'media-router-container').issue.title)"); + return ExecuteScriptAndExtractString(dialog_contents, script); +} + bool MediaRouterIntegrationBrowserTest::AreRoutesClosedOnUI() { content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -246,13 +274,6 @@ base::Unretained(this)))); } -void MediaRouterIntegrationBrowserTest::WaitUntilRouteCreationTimeout() { - ASSERT_FALSE(ConditionalWait( - base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1), - base::Bind(&MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI, - base::Unretained(this)))); -} - IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Basic) { OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); content::WebContents* web_contents = @@ -284,18 +305,7 @@ ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript); StartSession(web_contents); ChooseSink(web_contents, kTestSinkName); - WaitUntilRouteCreationTimeout(); ExecuteJavaScriptAPI(web_contents, kCheckSessionFailedScript); - - content::WebContents* dialog_contents = GetMRDialog(web_contents); - std::string script = base::StringPrintf( - "domAutomationController.send(window.document.getElementById(" - "'media-router-container').issue.title)"); - std::string issue_title = ExecuteScriptAndExtractString( - dialog_contents, script); - ASSERT_EQ(l10n_util::GetStringUTF8( - IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT), - issue_title); } IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h index 72f6bb0..d8c4bef2 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.h +++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -77,9 +77,15 @@ // route did not show up before the timeout. void WaitUntilRouteCreated(); - // Wait for route creation to timeout. Fails if a route shows up before the - // timeout. - void WaitUntilRouteCreationTimeout(); + // Wait until there is an issue showing in the UI. + void WaitUntilIssue(); + + // Returns true if there is an issue showing in the UI. + bool IsUIShowingIssue(); + + // Returns the title of issue showing in UI. It is an error to call this if + // there are no issues showing in UI. + std::string GetIssueTitle(); private: // Get the full path of the resource file.
diff --git a/chrome/test/media_router/media_router_integration_ui_browsertest.cc b/chrome/test/media_router/media_router_integration_ui_browsertest.cc index 66025623..4d40c6a 100644 --- a/chrome/test/media_router/media_router_integration_ui_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
@@ -7,9 +7,10 @@ #include "base/files/file_util.h" #include "base/strings/stringprintf.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/grit/generated_resources.h" #include "content/public/test/browser_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" - +#include "ui/base/l10n/l10n_util.h" namespace media_router { @@ -56,4 +57,40 @@ CloseRouteOnUI(); } +IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, + MANUAL_Dialog_RouteCreationTimedOut) { + SetTestData(FILE_PATH_LITERAL("route_creation_timed_out.json")); + OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* dialog_contents = OpenMRDialog(web_contents); + + // Verify the sink list. + std::string sink_length_script = base::StringPrintf( + "domAutomationController.send(" + "window.document.getElementById('media-router-container')." + "sinkList.length)"); + ASSERT_EQ(2, ExecuteScriptAndExtractInt(dialog_contents, sink_length_script)); + + base::TimeTicks start_time(base::TimeTicks::Now()); + ChooseSink(web_contents, kTestSinkName); + WaitUntilIssue(); + + base::TimeDelta elapsed(base::TimeTicks::Now() - start_time); + // The hardcoded timeout route creation timeout for the UI. + // See kCreateRouteTimeoutSeconds in media_router_ui.cc. + base::TimeDelta expected_timeout(base::TimeDelta::FromSeconds(20)); + + EXPECT_GE(elapsed, expected_timeout); + EXPECT_LE(elapsed - expected_timeout, base::TimeDelta::FromSeconds(5)); + + std::string issue_title = GetIssueTitle(); + ASSERT_EQ(l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT_FOR_TAB), + issue_title); + + // Route will still get created, it just takes longer than usual. + WaitUntilRouteCreated(); +} + } // namespace media_router
diff --git a/chrome/test/media_router/media_router_tests.gypi b/chrome/test/media_router/media_router_tests.gypi index 3607e5b7..e58f4b6 100644 --- a/chrome/test/media_router/media_router_tests.gypi +++ b/chrome/test/media_router/media_router_tests.gypi
@@ -13,6 +13,7 @@ 'resources/fail_reconnect_session.json', 'resources/no_provider.html', 'resources/no_provider.json', + 'resources/route_creation_timed_out.json', ], }, # end of variables 'targets': [
diff --git a/chrome/test/media_router/resources/route_creation_timed_out.json b/chrome/test/media_router/resources/route_creation_timed_out.json new file mode 100644 index 0000000..7f99be2 --- /dev/null +++ b/chrome/test/media_router/resources/route_creation_timed_out.json
@@ -0,0 +1,3 @@ +{ + "createRoute": {"delayMillis": 25000} +}
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index 78e41dc..8094834 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -545,7 +545,8 @@ TEST_PPAPI_NACL(VarResource) -#if defined(__i386__) +#if defined(__i386__) && !defined(OS_WIN) +// TODO(mcgrathr): Why doesn't it work on Windows? (crbug.com/541336) TEST_PPAPI_NACL_NATIVE(NaClIRTStackAlignment) #endif
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp index c55c0fa..ef0027c3 100644 --- a/chromecast/chromecast.gyp +++ b/chromecast/chromecast.gyp
@@ -28,6 +28,18 @@ 'defines': ['DISABLE_DISPLAY'], }], ], + 'target_conditions': [ + ['_type=="executable"', { + 'ldflags': [ + # Allow OEMs to override default libraries that are shipped with + # cast receiver package by installed OEM-specific libraries in + # /oem_cast_shlib. + '-Wl,-rpath=/oem_cast_shlib', + # Some shlibs are built in same directory of executables. + '-Wl,-rpath=\$$ORIGIN', + ], + }], + ], }, 'targets': [ # Public API target for OEM partners to replace shlibs. @@ -740,16 +752,6 @@ 'sources': [ 'app/cast_main.cc', ], - 'ldflags': [ - # Allow OEMs to override default libraries that are shipped with - # cast receiver package by installed OEM-specific libraries in - # /oem_cast_shlib. - '-Wl,-rpath=/oem_cast_shlib', - # TODO(dougsteed): remove when Chromecast moves to boringssl. - # Allow the cast shell to find the NSS module in the same - # directory. - '-Wl,-rpath=\$$ORIGIN' - ], }, ], # end of targets }],
diff --git a/chromecast/chromecast_tests.gypi b/chromecast/chromecast_tests.gypi index 068d6de..7937060 100644 --- a/chromecast/chromecast_tests.gypi +++ b/chromecast/chromecast_tests.gypi
@@ -11,8 +11,8 @@ 'target_name': 'cast_base_unittests', 'type': '<(gtest_target_type)', 'dependencies': [ - 'chromecast.gyp:cast_base', - 'chromecast.gyp:cast_crypto', + 'cast_base', + 'cast_crypto', '../base/base.gyp:run_all_unittests', '../testing/gtest.gyp:gtest', ], @@ -36,8 +36,8 @@ 'target_name': 'cast_crash_test_support', 'type': '<(component)', 'dependencies': [ - 'chromecast.gyp:cast_crash', 'cast_base', + 'cast_crash', ], 'sources': [ 'crash/linux/crash_testing_utils.cc', @@ -48,8 +48,8 @@ 'target_name': 'cast_crash_unittests', 'type': '<(gtest_target_type)', 'dependencies': [ + 'cast_crash', 'cast_crash_test_support', - 'chromecast.gyp:cast_crash', '../base/base.gyp:run_all_unittests', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', @@ -345,8 +345,8 @@ 'target_name': 'cast_shell_unittests', 'type': '<(gtest_target_type)', 'dependencies': [ + 'cast_crash_client', 'cast_crash_test_support', - 'chromecast.gyp:cast_crash_client', '../base/base.gyp:run_all_unittests', '../testing/gtest.gyp:gtest', ],
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn index d9ea7c23..1607db8 100644 --- a/chromecast/media/base/BUILD.gn +++ b/chromecast/media/base/BUILD.gn
@@ -5,10 +5,6 @@ import("//build/config/crypto.gni") import("//chromecast/chromecast.gni") -declare_args() { - libcast_media_target = "" -} - source_set("message_loop") { sources = [ "media_message_loop.cc", @@ -85,8 +81,23 @@ } } +# Target for OEM partners to override media shared library, i.e. +# libcast_media_1.0.so. This target is only used to build executables +# with correct linkage information. shared_library("libcast_media_1.0") { sources = [ + "cast_media_dummy.cc", + ] + + public_deps = [ + "//chromecast/public", + ] +} + +# This target can be statically linked into unittests, but production +# binaries should not depend on this target. +source_set("libcast_media_1.0_default_core") { + sources = [ "cast_media_default.cc", ] @@ -102,3 +113,11 @@ "//chromecast/media/cma/backend", ] } + +# Default implementation of libcast_media_1.0.so. +# TODO(slan): Make this target a loadable_module (crbug/380327) +shared_library("libcast_media_1.0_default") { + deps = [ + ":libcast_media_1.0_default_core", + ] +}
diff --git a/chromecast/media/base/cast_media_dummy.cc b/chromecast/media/base/cast_media_dummy.cc new file mode 100644 index 0000000..52ebd479 --- /dev/null +++ b/chromecast/media/base/cast_media_dummy.cc
@@ -0,0 +1,32 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/public/cast_media_shlib.h" +#include "chromecast/public/media_codec_support_shlib.h" + +namespace chromecast { +namespace media { + +void CastMediaShlib::Initialize(const std::vector<std::string>& argv) { +} + +void CastMediaShlib::Finalize() { +} + +VideoPlane* CastMediaShlib::GetVideoPlane() { + return nullptr; +} + +MediaPipelineBackend* CastMediaShlib::CreateMediaPipelineBackend( + const MediaPipelineDeviceParams& params) { + return nullptr; +} + +MediaCodecSupportShlib::CodecSupport MediaCodecSupportShlib::IsSupported( + const std::string& codec) { + return kDefault; +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp index 820028def..727eca1 100644 --- a/chromecast/media/media.gyp +++ b/chromecast/media/media.gyp
@@ -9,7 +9,8 @@ }, 'target_defaults': { 'include_dirs': [ - '../public/', # Public APIs + '../..', # Root of Chromium checkout + '../public/', # Public APIs ], }, 'targets': [ @@ -314,6 +315,23 @@ 'cma/test/mock_frame_provider.h', 'cma/test/run_all_unittests.cc', ], + 'ldflags': [ + # Allow OEMs to override default libraries that are shipped with + # cast receiver package by installed OEM-specific libraries in + # /oem_cast_shlib. + '-Wl,-rpath=/oem_cast_shlib', + # Some shlibs are built in same directory of executables. + '-Wl,-rpath=\$$ORIGIN', + ], + 'conditions': [ + ['chromecast_branding=="public"', { + 'dependencies': [ + # Link default libcast_media_1.0 statically not to link dummy one + # dynamically for public unittests. + 'libcast_media_1.0_default_core', + ], + }], + ], }, { # Target for OEM partners to override media shared library, i.e. # libcast_media_1.0.so. This target is only used to build executables @@ -322,14 +340,29 @@ 'type': 'shared_library', 'dependencies': [ '../../chromecast/chromecast.gyp:cast_public_api', - 'default_cma_backend' ], - 'include_dirs': [ - '../..', + 'sources': [ + 'base/cast_media_dummy.cc', + ], + }, + { # This target can be statically linked into unittests, but production + # binaries should not depend on this target. + 'target_name': 'libcast_media_1.0_default_core', + 'type': '<(component)', + 'dependencies': [ + '../../chromecast/chromecast.gyp:cast_public_api', + 'default_cma_backend' ], 'sources': [ 'base/cast_media_default.cc', ], - } + }, + { # Default implementation of libcast_media_1.0.so. + 'target_name': 'libcast_media_1.0_default', + 'type': 'loadable_module', + 'dependencies': [ + 'libcast_media_1.0_default_core' + ], + }, ], # end of targets }
diff --git a/components/BUILD.gn b/components/BUILD.gn index f5d6c8b2..e973c380 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -30,6 +30,7 @@ "//components/google/core/browser", "//components/search", "//components/search_engines", + "//components/sync_bookmarks", "//components/undo", "//components/strings", "//components/leveldb_proto",
diff --git a/components/OWNERS b/components/OWNERS index ea4a8e2..3c0e8d7 100644 --- a/components/OWNERS +++ b/components/OWNERS
@@ -69,6 +69,9 @@ per-file data_reduction_proxy*=sclittle@chromium.org per-file data_reduction_proxy*=megjablon@chromium.org +per-file data_usage*=bengr@chromium.org +per-file data_usage*=sclittle@chromium.org + per-file data_use_measurement*=sclittle@chromium.org per-file data_use_measurement*=bengr@chromium.org
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 7e2f83ad..82f8dc55 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -133,8 +133,9 @@ bool ExtractFormDataOnSave(const WebFormElement& form_element, FormData* data) { return WebFormElementToFormData( form_element, WebFormControlElement(), - static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTION_TEXT), data, - NULL); + static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE | + form_util::EXTRACT_OPTION_TEXT), + data, NULL); } } // namespace @@ -327,14 +328,12 @@ } else if (!is_safe && !allow_unsafe) { error_message = "must use a secure connection or --reduce-security-for-testing."; - } else if (!WebFormElementToFormData(form, - WebFormControlElement(), - static_cast<ExtractMask>( - EXTRACT_VALUE | - EXTRACT_OPTION_TEXT | - EXTRACT_OPTIONS), - &form_data, - NULL)) { + } else if (!WebFormElementToFormData( + form, WebFormControlElement(), + static_cast<form_util::ExtractMask>( + form_util::EXTRACT_VALUE | form_util::EXTRACT_OPTION_TEXT | + form_util::EXTRACT_OPTIONS), + &form_data, NULL)) { error_message = "failed to parse form."; } @@ -369,7 +368,7 @@ return; const WebInputElement* input_element = toWebInputElement(&element); - if (!input_element && !IsTextAreaElement(element)) + if (!input_element && !form_util::IsTextAreaElement(element)) return; ShowSuggestionsOptions options; @@ -406,7 +405,7 @@ } void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) { - DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); + DCHECK(toWebInputElement(&element) || form_util::IsTextAreaElement(element)); if (ignore_text_changes_) return; @@ -458,7 +457,8 @@ FormData form; FormFieldData field; - if (FindFormAndFieldForFormControlElement(element, &form, &field)) { + if (form_util::FindFormAndFieldForFormControlElement(element, &form, + &field)) { Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field, base::TimeTicks::Now())); } @@ -536,7 +536,7 @@ return; was_query_node_autofilled_ = element_.isAutofilled(); - FillForm(form, element_); + form_util::FillForm(form, element_); if (!element_.form().isNull()) last_interacted_form_ = element_.form(); @@ -557,7 +557,7 @@ return; was_query_node_autofilled_ = element_.isAutofilled(); - PreviewForm(form, element_); + form_util::PreviewForm(form, element_); Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id())); } @@ -570,7 +570,8 @@ if (password_autofill_agent_->DidClearAutofillSelection(element_)) return; - ClearPreviewedFormWithElement(element_, was_query_node_autofilled_); + form_util::ClearPreviewedFormWithElement(element_, + was_query_node_autofilled_); } else { // TODO(isherman): There seem to be rare cases where this code *is* // reachable: see [ http://crbug.com/96321#c6 ]. Ideally we would @@ -630,7 +631,7 @@ const blink::WebFormElement& form = forms[i]; if (form_util::GetCanonicalActionForForm(last_interacted_form_) == form_util::GetCanonicalActionForForm(form) && - IsWebNodeVisible(form)) { + form_util::IsWebNodeVisible(form)) { // Found our candidate form, and it is still visible. return; } @@ -649,7 +650,8 @@ return; if (result == WebFormElement::AutocompleteResultSuccess) { - FillFormIncludingNonFocusableElements(form_data, in_flight_request_form_); + form_util::FillFormIncludingNonFocusableElements(form_data, + in_flight_request_form_); if (!in_flight_request_form_.checkValidity()) result = WebFormElement::AutocompleteResultErrorInvalid; } @@ -681,7 +683,7 @@ if (!options.datalist_only && !input_element->suggestedValue().isEmpty()) return; } else { - DCHECK(IsTextAreaElement(element)); + DCHECK(form_util::IsTextAreaElement(element)); if (!element.toConst<WebTextAreaElement>().suggestedValue().isEmpty()) return; } @@ -701,7 +703,7 @@ } element_ = element; - if (IsAutofillableInputElement(input_element) && + if (form_util::IsAutofillableInputElement(input_element) && password_autofill_agent_->ShowSuggestions( *input_element, options.show_full_suggestion_list, is_generation_popup_possibly_visible_)) { @@ -729,22 +731,23 @@ if (!element.document().frame()) return; - DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); + DCHECK(toWebInputElement(&element) || form_util::IsTextAreaElement(element)); static int query_counter = 0; autofill_query_id_ = query_counter++; FormData form; FormFieldData field; - if (!FindFormAndFieldForFormControlElement(element, &form, &field)) { + if (!form_util::FindFormAndFieldForFormControlElement(element, &form, + &field)) { // If we didn't find the cached form, at least let autocomplete have a shot // at providing suggestions. - WebFormControlElementToFormField(element, EXTRACT_VALUE, &field); + WebFormControlElementToFormField(element, form_util::EXTRACT_VALUE, &field); } if (datalist_only) field.should_autocomplete = false; - gfx::RectF bounding_box_scaled = GetScaledBoundingBox( + gfx::RectF bounding_box_scaled = form_util::GetScaledBoundingBox( render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(), &element_); @@ -781,7 +784,7 @@ was_query_node_autofilled_ = element_.isAutofilled(); node->setSuggestedValue(value.substr(0, node->maxLength())); node->setAutofilled(true); - PreviewSuggestion(node->suggestedValue(), node->value(), node); + form_util::PreviewSuggestion(node->suggestedValue(), node->value(), node); } void AutofillAgent::ProcessForms() {
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 9f1d765..699a72ad 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -52,6 +52,7 @@ using blink::WebVector; namespace autofill { +namespace form_util { const size_t kMaxParseableFields = 200; @@ -1091,8 +1092,6 @@ } // namespace -namespace form_util { - bool IsNamedElementVisible( const std::vector<blink::WebFormControlElement>& control_elements, const base::string16& name) { @@ -1170,8 +1169,6 @@ return StripAuthAndParams(full_origin); } -} // namespace form_util - bool IsMonthInput(const WebInputElement* element) { CR_DEFINE_STATIC_LOCAL(WebString, kMonth, ("month")); return element && !element->isNull() && element->formControlType() == kMonth; @@ -1629,4 +1626,5 @@ input_element->setSelectionRange(selection_start, suggestion.length()); } +} // namespace form_util } // namespace autofill
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h index 9ba7efb..04b1b7c 100644 --- a/components/autofill/content/renderer/form_autofill_util.h +++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -32,6 +32,8 @@ struct FormFieldData; struct WebElementDescriptor; +namespace form_util { + // A bit field mask to extract data from WebFormControlElement. // Copied to components/autofill/ios/browser/resources/autofill_controller.js. enum ExtractMask { @@ -54,9 +56,6 @@ // Copied to components/autofill/ios/browser/resources/autofill_controller.js. extern const size_t kMaxParseableFields; -namespace form_util { -// TODO(mathp): Move more functions in the form_util namespace. - // Returns true if |control_elements| contains an element named |name| and is // visible. bool IsNamedElementVisible( @@ -82,8 +81,6 @@ GURL GetCanonicalActionForForm(const blink::WebFormElement& form); GURL GetCanonicalOriginForDocument(const blink::WebDocument& document); -} // namespace form_util - // Returns true if |element| is a month input element. bool IsMonthInput(const blink::WebInputElement* element); @@ -235,6 +232,7 @@ const base::string16& user_input, blink::WebFormControlElement* input_element); +} // namespace form_util } // namespace autofill #endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_AUTOFILL_UTIL_H_
diff --git a/components/autofill/content/renderer/form_cache.cc b/components/autofill/content/renderer/form_cache.cc index b77137f..d513342 100644 --- a/components/autofill/content/renderer/form_cache.cc +++ b/components/autofill/content/renderer/form_cache.cc
@@ -91,15 +91,16 @@ // the form is parsed. bool log_deprecation_messages = parsed_forms_.empty(); - const ExtractMask extract_mask = - static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); + const form_util::ExtractMask extract_mask = + static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE | + form_util::EXTRACT_OPTIONS); size_t num_fields_seen = 0; for (size_t i = 0; i < web_forms.size(); ++i) { const WebFormElement& form_element = web_forms[i]; std::vector<WebFormControlElement> control_elements = - ExtractAutofillableElementsInForm(form_element); + form_util::ExtractAutofillableElementsInForm(form_element); size_t num_editable_elements = ScanFormControlElements(control_elements, log_deprecation_messages); @@ -113,7 +114,7 @@ } num_fields_seen += form.fields.size(); - if (num_fields_seen > kMaxParseableFields) + if (num_fields_seen > form_util::kMaxParseableFields) return forms; if (form.fields.size() >= kRequiredAutofillFields && @@ -134,7 +135,8 @@ // Look for more parseable fields outside of forms. std::vector<WebElement> fieldsets; std::vector<WebFormControlElement> control_elements = - GetUnownedAutofillableFormFieldElements(document.all(), &fieldsets); + form_util::GetUnownedAutofillableFormFieldElements(document.all(), + &fieldsets); size_t num_editable_elements = ScanFormControlElements(control_elements, log_deprecation_messages); @@ -150,7 +152,7 @@ } num_fields_seen += synthetic_form.fields.size(); - if (num_fields_seen > kMaxParseableFields) + if (num_fields_seen > form_util::kMaxParseableFields) return forms; if (synthetic_form.fields.size() >= kRequiredAutofillFields && @@ -175,10 +177,11 @@ WebFormElement form_element = element.form(); std::vector<WebFormControlElement> control_elements; if (form_element.isNull()) { - control_elements = GetUnownedAutofillableFormFieldElements( + control_elements = form_util::GetUnownedAutofillableFormFieldElements( element.document().all(), nullptr); } else { - control_elements = ExtractAutofillableElementsInForm(form_element); + control_elements = + form_util::ExtractAutofillableElementsInForm(form_element); } for (size_t i = 0; i < control_elements.size(); ++i) { WebFormControlElement control_element = control_elements[i]; @@ -193,7 +196,8 @@ control_element.setAutofilled(false); WebInputElement* input_element = toWebInputElement(&control_element); - if (IsTextInput(input_element) || IsMonthInput(input_element)) { + if (form_util::IsTextInput(input_element) || + form_util::IsMonthInput(input_element)) { input_element->setValue(base::string16(), true); // Clearing the value in the focused node (above) can cause selection @@ -202,9 +206,9 @@ int length = input_element->value().length(); input_element->setSelectionRange(length, length); } - } else if (IsTextAreaElement(control_element)) { + } else if (form_util::IsTextAreaElement(control_element)) { control_element.setValue(base::string16(), true); - } else if (IsSelectElement(control_element)) { + } else if (form_util::IsSelectElement(control_element)) { WebSelectElement select_element = control_element.to<WebSelectElement>(); std::map<const WebSelectElement, base::string16>::const_iterator @@ -215,7 +219,7 @@ } } else { WebInputElement input_element = control_element.to<WebInputElement>(); - DCHECK(IsCheckableElement(&input_element)); + DCHECK(form_util::IsCheckableElement(&input_element)); std::map<const WebInputElement, bool>::const_iterator it = initial_checked_state_.find(input_element); if (it != initial_checked_state_.end() && @@ -238,8 +242,8 @@ if (form.data.SameFormAs(synthetic_form_)) { found_synthetic_form = true; WebDocument document = frame_.document(); - control_elements = - GetUnownedAutofillableFormFieldElements(document.all(), nullptr); + control_elements = form_util::GetUnownedAutofillableFormFieldElements( + document.all(), nullptr); } if (!found_synthetic_form) { @@ -259,11 +263,12 @@ // to |true| -- WebKit distinguishes between a "null" string (lhs) and // an "empty" string (rhs). We don't want that distinction, so forcing // to string16. - base::string16 element_name = GetFormIdentifier(form_element); + base::string16 element_name = form_util::GetFormIdentifier(form_element); GURL action(form_element.document().completeURL(form_element.action())); if (element_name == form.data.name && action == form.data.action) { found_form = true; - control_elements = ExtractAutofillableElementsInForm(form_element); + control_elements = + form_util::ExtractAutofillableElementsInForm(form_element); break; } } @@ -314,11 +319,12 @@ // Save original values of <select> elements so we can restore them // when |ClearFormWithNode()| is invoked. - if (IsSelectElement(element) || IsTextAreaElement(element)) { + if (form_util::IsSelectElement(element) || + form_util::IsTextAreaElement(element)) { ++num_editable_elements; } else { const WebInputElement input_element = element.toConst<WebInputElement>(); - if (!IsCheckableElement(&input_element)) + if (!form_util::IsCheckableElement(&input_element)) ++num_editable_elements; } } @@ -328,14 +334,14 @@ void FormCache::SaveInitialValues( const std::vector<WebFormControlElement>& control_elements) { for (const WebFormControlElement& element : control_elements) { - if (IsSelectElement(element)) { + if (form_util::IsSelectElement(element)) { const WebSelectElement select_element = element.toConst<WebSelectElement>(); initial_select_values_.insert( std::make_pair(select_element, select_element.value())); } else { const WebInputElement* input_element = toWebInputElement(&element); - if (IsCheckableElement(input_element)) { + if (form_util::IsCheckableElement(input_element)) { initial_checked_state_.insert( std::make_pair(*input_element, input_element->isChecked())); }
diff --git a/components/autofill/content/renderer/page_click_tracker.cc b/components/autofill/content/renderer/page_click_tracker.cc index 4548d4e3..c65bd4e 100644 --- a/components/autofill/content/renderer/page_click_tracker.cc +++ b/components/autofill/content/renderer/page_click_tracker.cc
@@ -45,7 +45,7 @@ if (!element.hasHTMLTagName("input")) return WebInputElement(); const WebInputElement* input = blink::toWebInputElement(&element); - if (!IsTextInput(input)) + if (!form_util::IsTextInput(input)) return WebInputElement(); return *input; }
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index d515592..5f45a76b 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -128,7 +128,8 @@ CreatePasswordFormFromUnownedInputElements(*frame, nullptr, &form_predictions)); std::vector<blink::WebFormControlElement> control_elements = - GetUnownedAutofillableFormFieldElements(frame->document().all(), nullptr); + form_util::GetUnownedAutofillableFormFieldElements( + frame->document().all(), nullptr); if (unowned_password_form && form_util::IsNamedElementVisible( control_elements, unowned_password_form->username_element) && @@ -299,7 +300,7 @@ continue; std::vector<blink::WebFormControlElement> control_elements = - ExtractAutofillableElementsInForm(fe); + form_util::ExtractAutofillableElementsInForm(fe); FormInputElementMap cur_map; if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names, &cur_map)) @@ -311,7 +312,7 @@ return; std::vector<blink::WebFormControlElement> control_elements = - GetUnownedAutofillableFormFieldElements(doc.all(), nullptr); + form_util::GetUnownedAutofillableFormFieldElements(doc.all(), nullptr); FormInputElementMap unowned_elements_map; if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names, &unowned_elements_map)) @@ -491,8 +492,10 @@ username_element->setValue(username, true); (*nonscript_modified_values)[*username_element] = username; username_element->setAutofilled(true); - if (set_selection) - PreviewSuggestion(username, current_username, username_element); + if (set_selection) { + form_util::PreviewSuggestion(username, current_username, + username_element); + } } else if (current_username != username) { // If the username can't be filled and it doesn't match a saved password // as is, don't autofill a password. @@ -815,8 +818,8 @@ was_username_autofilled_ = username_element.isAutofilled(); username_element.setSuggestedValue(username); username_element.setAutofilled(true); - ::autofill::PreviewSuggestion(username_element.suggestedValue(), - username_query_prefix_, &username_element); + form_util::PreviewSuggestion(username_element.suggestedValue(), + username_query_prefix_, &username_element); was_password_autofilled_ = password_info->password_field.isAutofilled(); password_info->password_field.setSuggestedValue(password); password_info->password_field.setAutofilled(true); @@ -977,7 +980,7 @@ } // Checks whether the webpage is a redirect page or an empty page. - if (IsWebpageEmpty(frame)) { + if (form_util::IsWebpageEmpty(frame)) { if (logger) { logger->LogMessage(Logger::STRING_WEBPAGE_EMPTY); } @@ -993,7 +996,7 @@ for (size_t i = 0; i < forms.size(); ++i) { const blink::WebFormElement& form = forms[i]; if (only_visible) { - bool is_form_visible = IsWebNodeVisible(form); + bool is_form_visible = form_util::IsWebNodeVisible(form); if (logger) { LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form); logger->LogBoolean(Logger::STRING_FORM_IS_VISIBLE, is_form_visible); @@ -1387,7 +1390,7 @@ FormData form; FormFieldData field; - FindFormAndFieldForFormControlElement(user_input, &form, &field); + form_util::FindFormAndFieldForFormControlElement(user_input, &form, &field); blink::WebInputElement selected_element = user_input; if (show_on_password_field && !selected_element.isPasswordField()) {
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc index 62ade2b..30a0405b 100644 --- a/components/autofill/content/renderer/password_form_conversion_utils.cc +++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -132,8 +132,8 @@ void PopulateSyntheticFormFromWebForm(const WebFormElement& web_form, SyntheticForm* synthetic_form) { - synthetic_form->control_elements = ExtractAutofillableElementsInForm( - web_form); + synthetic_form->control_elements = + form_util::ExtractAutofillableElementsInForm(web_form); synthetic_form->action = web_form.action(); synthetic_form->document = web_form.document(); } @@ -258,7 +258,7 @@ return; std::vector<blink::WebFormControlElement> autofillable_elements = - ExtractAutofillableElementsFromSet(form.control_elements); + form_util::ExtractAutofillableElementsFromSet(form.control_elements); const PasswordFormFieldPredictionMap& field_predictions = predictions_iterator->second; @@ -589,10 +589,8 @@ SyntheticForm synthetic_form; PopulateSyntheticFormFromWebForm(web_form, &synthetic_form); - WebFormElementToFormData(web_form, - blink::WebFormControlElement(), - EXTRACT_NONE, - &password_form->form_data, + WebFormElementToFormData(web_form, blink::WebFormControlElement(), + form_util::EXTRACT_NONE, &password_form->form_data, NULL /* FormFieldData */); if (!GetPasswordForm(synthetic_form, password_form.get(), @@ -608,8 +606,8 @@ const FormsPredictionsMap* form_predictions) { SyntheticForm synthetic_form; synthetic_form.control_elements = - GetUnownedAutofillableFormFieldElements(frame.document().all(), - &synthetic_form.fieldsets); + form_util::GetUnownedAutofillableFormFieldElements( + frame.document().all(), &synthetic_form.fieldsets); synthetic_form.document = frame.document(); if (synthetic_form.control_elements.empty()) @@ -617,11 +615,8 @@ scoped_ptr<PasswordForm> password_form(new PasswordForm()); UnownedPasswordFormElementsAndFieldSetsToFormData( - synthetic_form.fieldsets, - synthetic_form.control_elements, - nullptr, frame.document(), - EXTRACT_NONE, - &password_form->form_data, + synthetic_form.fieldsets, synthetic_form.control_elements, nullptr, + frame.document(), form_util::EXTRACT_NONE, &password_form->form_data, nullptr /* FormFieldData */); if (!GetPasswordForm(synthetic_form, password_form.get(), nonscript_modified_values, form_predictions))
diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc index fe2a3920..c4c71e8 100644 --- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc +++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -170,8 +170,9 @@ LoadWebFormFromHTML(html, &form); FormData form_data; - ASSERT_TRUE(WebFormElementToFormData(form, WebFormControlElement(), - EXTRACT_NONE, &form_data, nullptr)); + ASSERT_TRUE(form_util::WebFormElementToFormData( + form, WebFormControlElement(), form_util::EXTRACT_NONE, &form_data, + nullptr)); FormStructure form_structure(form_data);
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index 4cd032c5..7db7205c 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -412,7 +412,7 @@ } void PasswordGenerationAgent::ShowGenerationPopup() { - gfx::RectF bounding_box_scaled = GetScaledBoundingBox( + gfx::RectF bounding_box_scaled = form_util::GetScaledBoundingBox( render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(), &generation_element_); @@ -426,7 +426,7 @@ } void PasswordGenerationAgent::ShowEditingPopup() { - gfx::RectF bounding_box_scaled = GetScaledBoundingBox( + gfx::RectF bounding_box_scaled = form_util::GetScaledBoundingBox( render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(), &generation_element_);
diff --git a/components/components.gyp b/components/components.gyp index 4838a70..6b30bc3 100644 --- a/components/components.gyp +++ b/components/components.gyp
@@ -25,6 +25,7 @@ 'cronet.gypi', 'crx_file.gypi', 'data_reduction_proxy.gypi', + 'data_usage.gypi', 'data_use_measurement.gypi', 'device_event_log.gypi', 'dom_distiller.gypi', @@ -77,6 +78,7 @@ 'ssl_errors.gypi', 'startup_metric_utils.gypi', 'suggestions.gypi', + 'sync_bookmarks.gypi', 'sync_driver.gypi', 'syncable_prefs.gypi', 'toolbar.gypi',
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index d1d3843..24df75ff 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -150,6 +150,9 @@ 'data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc', ], + 'data_usage_unittest_sources': [ + 'data_usage/core/data_use_aggregator_unittest.cc', + ], 'device_event_log_unittest_sources': [ 'device_event_log/device_event_log_impl_unittest.cc', ], @@ -512,7 +515,6 @@ 'proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc', 'proximity_auth/ble/bluetooth_low_energy_connection_unittest.cc', 'proximity_auth/ble/bluetooth_low_energy_device_whitelist_unittest.cc', - 'proximity_auth/ble/proximity_auth_ble_system_unittest.cc', 'proximity_auth/bluetooth_connection_finder_unittest.cc', 'proximity_auth/bluetooth_connection_unittest.cc', 'proximity_auth/bluetooth_throttler_impl_unittest.cc', @@ -820,6 +822,7 @@ '<@(crash_unittest_sources)', '<@(crx_file_unittest_sources)', '<@(data_reduction_proxy_unittest_sources)', + '<@(data_usage_unittest_sources)', '<@(data_use_measurement_unittest_sources)', '<@(device_event_log_unittest_sources)', '<@(dom_distiller_unittest_sources)', @@ -922,6 +925,7 @@ 'components.gyp:data_reduction_proxy_core_browser', 'components.gyp:data_reduction_proxy_core_common', 'components.gyp:data_reduction_proxy_test_support', + 'components.gyp:data_usage_core', 'components.gyp:data_use_measurement_core', 'components.gyp:device_event_log_component', 'components.gyp:dom_distiller_core',
diff --git a/components/crash.gypi b/components/crash.gypi index 6acfdfc..8ad506d 100644 --- a/components/crash.gypi +++ b/components/crash.gypi
@@ -5,6 +5,23 @@ { 'targets': [ { + # GN version: //components/crash/core/browser + 'target_name': 'crash_core_browser', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'dependencies': [ + 'upload_list', + '../base/base.gyp:base', + '../components/components_strings.gyp:components_strings', + ], + 'sources': [ + 'crash/core/browser/crashes_ui_util.cc', + 'crash/core/browser/crashes_ui_util.h', + ], + }, + { # GN version: //components/crash/core/common 'target_name': 'crash_core_common', 'type': 'static_library',
diff --git a/components/crash/core/browser/BUILD.gn b/components/crash/core/browser/BUILD.gn new file mode 100644 index 0000000..0ba13063 --- /dev/null +++ b/components/crash/core/browser/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("browser") { + sources = [ + "crashes_ui_util.cc", + "crashes_ui_util.h", + ] + deps = [ + "//base", + "//components/strings", + "//components/upload_list", + ] +}
diff --git a/components/crash/core/browser/DEPS b/components/crash/core/browser/DEPS new file mode 100644 index 0000000..00f4fc3 --- /dev/null +++ b/components/crash/core/browser/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+components/upload_list", + "+grit/components_chromium_strings.h", + "+grit/components_google_chrome_strings.h", + "+grit/components_strings.h", +]
diff --git a/components/crash/core/browser/crashes_ui_util.cc b/components/crash/core/browser/crashes_ui_util.cc new file mode 100644 index 0000000..bd74af60 --- /dev/null +++ b/components/crash/core/browser/crashes_ui_util.cc
@@ -0,0 +1,53 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/crash/core/browser/crashes_ui_util.h" + +#include <vector> + +#include "base/i18n/time_formatting.h" +#include "base/macros.h" +#include "base/values.h" +#include "components/upload_list/upload_list.h" +#include "grit/components_chromium_strings.h" +#include "grit/components_google_chrome_strings.h" +#include "grit/components_strings.h" + +namespace crash { + +const CrashesUILocalizedString kCrashesUILocalizedStrings[] = { + {"bugLinkText", IDS_CRASH_BUG_LINK_LABEL}, + {"crashCountFormat", IDS_CRASH_CRASH_COUNT_BANNER_FORMAT}, + {"crashHeaderFormat", IDS_CRASH_CRASH_HEADER_FORMAT}, + {"crashTimeFormat", IDS_CRASH_CRASH_TIME_FORMAT}, + {"crashesTitle", IDS_CRASH_TITLE}, + {"disabledHeader", IDS_CRASH_DISABLED_HEADER}, + {"disabledMessage", IDS_CRASH_DISABLED_MESSAGE}, + {"noCrashesMessage", IDS_CRASH_NO_CRASHES_MESSAGE}, + {"uploadCrashesLinkText", IDS_CRASH_UPLOAD_MESSAGE}, +}; + +const size_t kCrashesUILocalizedStringsCount = + arraysize(kCrashesUILocalizedStrings); + +const char kCrashesUICrashesJS[] = "crashes.js"; +const char kCrashesUIRequestCrashList[] = "requestCrashList"; +const char kCrashesUIRequestCrashUpload[] = "requestCrashUpload"; +const char kCrashesUIShortProductName[] = "shortProductName"; +const char kCrashesUIUpdateCrashList[] = "updateCrashList"; + +void UploadListToValue(UploadList* upload_list, base::ListValue* out_value) { + std::vector<UploadList::UploadInfo> crashes; + upload_list->GetUploads(50, &crashes); + + for (const auto& info : crashes) { + base::DictionaryValue* crash = new base::DictionaryValue(); + crash->SetString("id", info.id); + crash->SetString("time", base::TimeFormatFriendlyDateAndTime(info.time)); + crash->SetString("local_id", info.local_id); + out_value->Append(crash); + } +} + +} // namespace crash
diff --git a/components/crash/core/browser/crashes_ui_util.h b/components/crash/core/browser/crashes_ui_util.h new file mode 100644 index 0000000..d24f009 --- /dev/null +++ b/components/crash/core/browser/crashes_ui_util.h
@@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRASH_CORE_BROWSER_CRASHES_UI_UTIL_H_ +#define COMPONENTS_CRASH_CORE_BROWSER_CRASHES_UI_UTIL_H_ + +#include <stddef.h> + +namespace base { +class ListValue; +} + +class UploadList; + +namespace crash { + +// Mapping between a WebUI resource (identified by |name|) and a GRIT resource +// (identified by |resource_id|). +struct CrashesUILocalizedString { + const char* name; + int resource_id; +}; + +// List of localized strings that must be added to the WebUI. +extern const CrashesUILocalizedString kCrashesUILocalizedStrings[]; +extern const size_t kCrashesUILocalizedStringsCount; + +// Strings used by the WebUI resources. +// Must match the constants used in the resource files. +extern const char kCrashesUICrashesJS[]; +extern const char kCrashesUIRequestCrashList[]; +extern const char kCrashesUIRequestCrashUpload[]; +extern const char kCrashesUIShortProductName[]; +extern const char kCrashesUIUpdateCrashList[]; + +// Converts and appends the most recent uploads to |out_value|. +void UploadListToValue(UploadList* upload_list, base::ListValue* out_value); + +} // namespace crash + +#endif // COMPONENTS_CRASH_CORE_BROWSER_CRASHES_UI_UTIL_H_
diff --git a/components/cronet/README.md b/components/cronet/README.md index c917eb2d..4d23a544 100644 --- a/components/cronet/README.md +++ b/components/cronet/README.md
@@ -144,22 +144,25 @@ # Using the java.net.HttpURLConnection API Cronet offers an implementation of the [java.net.HttpURLConnection] API to make it easier for apps which rely on this API to use Cronet. -To use Cronet's implementation instead of the system's default implementation, -simply do the following: +To open individual connections using Cronet's implementation, do the following: - CronetURLStreamHandlerFactory streamHandlerFactory = - new CronetURLStreamHandlerFactory(engine); - URL.setURLStreamHandlerFactory(streamHandlerFactory); + HttpURLConnection connection = + (HttpURLConnection)engine.openConnection(url); + +To use Cronet's implementation instead of the system's default implementation +for all connections established using `URL.openConnection()` do the following: + + URL.setURLStreamHandlerFactory(engine.createURLStreamHandlerFactory()); Cronet's HttpURLConnection implementation has some limitations as compared to the system implementation, including not utilizing the default system HTTP cache (Please -see {@link org.chromium.net.urlconnection.CronetURLStreamHandlerFactory} for +see {@link org.chromium.net.CronetEngine#createURLStreamHandlerFactory} for more information). You can configure Cronet and control caching through the `CronetEngine.Builder` instance, `engineBuilder` -(See [Configuring Cronet](#configuring-cronet) section), before you pass it -into the `CronetURLStreamHandlerFactory` constructor. +(See [Configuring Cronet](#configuring-cronet) section), before you build the +`CronetEngine` and then call `CronetEngine.createURLStreamHandlerFactory()`. [ByteBuffer]: https://developer.android.com/reference/java/nio/ByteBuffer.html [chrome://net-internals#import]: chrome://net-internals#import
diff --git a/components/cronet/android/java/package-list b/components/cronet/android/java/package-list index 73958f7f..cba6220 100644 --- a/components/cronet/android/java/package-list +++ b/components/cronet/android/java/package-list
@@ -1,4 +1,5 @@ android.content +android.net.http android.util java java.io @@ -7,4 +8,5 @@ java.nio java.util java.util.concurrent +javax.net.ssl org.json
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetEngine.java b/components/cronet/android/java/src/org/chromium/net/CronetEngine.java index 2de7e8d0..31334aa 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetEngine.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetEngine.java
@@ -13,6 +13,10 @@ import java.io.File; import java.lang.reflect.Constructor; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandlerFactory; import java.util.concurrent.Executor; /** @@ -167,6 +171,8 @@ * proxy is allowed. * @return the builder to facilitate chaining. * @hide + * @deprecated Marked as deprecated because @hide doesn't properly hide but + * javadocs are built with nodeprecated="yes". */ public Builder setDataReductionProxyOptions( String primaryProxy, String fallbackProxy, String secureProxyCheckUrl) { @@ -371,7 +377,7 @@ * priorities see {@link #createRequest(String, UrlRequestListener, * Executor, int priority)}. * - * @param url {@link java.net.URL} for the request. + * @param url {@link URL} for the request. * @param listener callback class that gets called on different events. * @param executor {@link Executor} on which all callbacks will be called. * @return new request. @@ -387,7 +393,7 @@ * tasks on the current thread to prevent blocking networking operations * and causing exceptions during shutdown. * - * @param url {@link java.net.URL} for the request. + * @param url {@link URL} for the request. * @param listener callback class that gets called on different events. * @param executor {@link Executor} on which all callbacks will be called. * @param priority priority of the request which should be one of the @@ -517,6 +523,68 @@ public abstract void removeThroughputListener(NetworkQualityThroughputListener listener); /** + * Establishes a new connection to the resource specified by the {@link URL} {@code url}. + * <p> + * <b>Note:</b> Cronet's {@link java.net.HttpURLConnection} implementation is subject to certain + * limitations, see {@link #createURLStreamHandlerFactory} for details. + * + * @param url URL of resource to connect to. + * @return an {@link java.net.HttpURLConnection} instance implemented by this CronetEngine. + */ + public abstract URLConnection openConnection(URL url); + + /** + * Establishes a new connection to the resource specified by the {@link URL} {@code url} + * using the given proxy. + * <p> + * <b>Note:</b> Cronet's {@link java.net.HttpURLConnection} implementation is subject to certain + * limitations, see {@link #createURLStreamHandlerFactory} for details. + * + * @param url URL of resource to connect to. + * @param proxy proxy to use when establishing connection. + * @return an {@link java.net.HttpURLConnection} instance implemented by this CronetEngine. + * @hide + * @deprecated Marked as deprecated because @hide doesn't properly hide but + * javadocs are built with nodeprecated="yes". + * TODO(pauljensen): Expose once implemented, http://crbug.com/418111 + */ + public abstract URLConnection openConnection(URL url, Proxy proxy); + + /** + * Creates a {@link URLStreamHandlerFactory} to handle HTTP and HTTPS + * traffic. An instance of this class can be installed via + * {@link URL#setURLStreamHandlerFactory} thus using this CronetEngine by default for + * all requests created via {@link URL#openConnection}. + * <p> + * Cronet does not use certain HTTP features provided via the system: + * <ul> + * <li>the HTTP cache installed via + * {@link android.net.http.HttpResponseCache#install(java.io.File, long) + * HttpResponseCache.install()}</li> + * <li>the HTTP authentication method installed via + * {@link java.net.Authenticator#setDefault}</li> + * <li>the HTTP cookie storage installed via {@link java.net.CookieHandler#setDefault}</li> + * </ul> + * <p> + * While Cronet supports and encourages requests using the HTTPS protocol, + * Cronet does not provide support for the + * {@link javax.net.ssl.HttpsURLConnection} API. This lack of support also + * includes not using certain HTTPS features provided via the system: + * <ul> + * <li>the HTTPS hostname verifier installed via {@link + * javax.net.ssl.HttpsURLConnection#setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier) + * HttpsURLConnection.setDefaultHostnameVerifier()}</li> + * <li>the HTTPS socket factory installed via {@link + * javax.net.ssl.HttpsURLConnection#setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory) + * HttpsURLConnection.setDefaultSSLSocketFactory()}</li> + * </ul> + * + * @return an {@link URLStreamHandlerFactory} instance implemented by this + * CronetEngine. + */ + public abstract URLStreamHandlerFactory createURLStreamHandlerFactory(); + + /** * Creates a {@link CronetEngine} with the given {@link Builder}. * @param context Android {@link Context}. * @param config engine configuration.
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java index 7cdabde2..703aa993 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
@@ -17,7 +17,13 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeClassQualifiedName; import org.chromium.base.annotations.UsedByReflection; +import org.chromium.net.urlconnection.CronetHttpURLConnection; +import org.chromium.net.urlconnection.CronetURLStreamHandlerFactory; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandlerFactory; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; @@ -254,6 +260,28 @@ } } + @Override + public URLConnection openConnection(URL url) { + return openConnection(url, Proxy.NO_PROXY); + } + + @Override + public URLConnection openConnection(URL url, Proxy proxy) { + if (proxy.type() != Proxy.Type.DIRECT) { + throw new UnsupportedOperationException(); + } + String protocol = url.getProtocol(); + if ("http".equals(protocol) || "https".equals(protocol)) { + return new CronetHttpURLConnection(url, this); + } + throw new UnsupportedOperationException("Unexpected protocol:" + protocol); + } + + @Override + public URLStreamHandlerFactory createURLStreamHandlerFactory() { + return new CronetURLStreamHandlerFactory(this); + } + /** * Mark request as started to prevent shutdown when there are active * requests.
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java index 8726e2a..a41620e 100644 --- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java +++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java
@@ -32,8 +32,9 @@ /** * An implementation of {@link HttpURLConnection} that uses Cronet to send * requests and receive responses. + * @deprecated use {@link CronetEngine#openConnection}. */ -class CronetHttpURLConnection extends HttpURLConnection { +public class CronetHttpURLConnection extends HttpURLConnection { private static final String TAG = "cr.CronetHttpURLConn"; private static final String CONTENT_LENGTH = "Content-Length"; private final CronetEngine mCronetEngine;
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java index c962e74..8cf5ea73 100644 --- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java +++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java
@@ -22,7 +22,7 @@ * <b>Note:</b> Cronet's {@code HttpURLConnection} implementation is subject to some limitations * listed {@link CronetURLStreamHandlerFactory here}. */ -public class CronetHttpURLStreamHandler extends URLStreamHandler { +class CronetHttpURLStreamHandler extends URLStreamHandler { private final CronetEngine mCronetEngine; public CronetHttpURLStreamHandler(CronetEngine cronetEngine) { @@ -35,12 +35,7 @@ */ @Override public URLConnection openConnection(URL url) throws IOException { - String protocol = url.getProtocol(); - if ("http".equals(protocol) || "https".equals(protocol)) { - return new CronetHttpURLConnection(url, mCronetEngine); - } - throw new UnsupportedOperationException( - "Unexpected protocol:" + protocol); + return mCronetEngine.openConnection(url); } /** @@ -50,6 +45,6 @@ */ @Override public URLConnection openConnection(URL url, Proxy proxy) { - throw new UnsupportedOperationException(); + return mCronetEngine.openConnection(url, proxy); } }
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java index aadcd7b..b798f27 100644 --- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java +++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java
@@ -36,6 +36,8 @@ * javax.net.ssl.HttpsURLConnection#setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory) * HttpsURLConnection.setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory)}</li> * </ul> + * + * @deprecated use {@link CronetEngine#createURLStreamHandlerFactory}. */ public class CronetURLStreamHandlerFactory implements URLStreamHandlerFactory {
diff --git a/components/cronet/android/test/javaperftests/src/org/chromium/net/CronetPerfTestActivity.java b/components/cronet/android/test/javaperftests/src/org/chromium/net/CronetPerfTestActivity.java index 6d53f528..c7ad7364 100644 --- a/components/cronet/android/test/javaperftests/src/org/chromium/net/CronetPerfTestActivity.java +++ b/components/cronet/android/test/javaperftests/src/org/chromium/net/CronetPerfTestActivity.java
@@ -11,7 +11,6 @@ import android.os.Bundle; import android.os.Debug; -import org.chromium.net.urlconnection.CronetHttpURLStreamHandler; import org.json.JSONException; import org.json.JSONObject; @@ -292,17 +291,11 @@ // GET or POST to one particular URL using Cronet HttpURLConnection API private class CronetHttpURLConnectionFetchTask implements Callable<Boolean> { private final byte[] mBuffer = new byte[mBufferSize]; - private final CronetHttpURLStreamHandler mStreamHandler; - - public CronetHttpURLConnectionFetchTask( - CronetHttpURLStreamHandler cronetStreamHandler) { - mStreamHandler = cronetStreamHandler; - } @Override public Boolean call() { try { - return exerciseHttpURLConnection(mStreamHandler.openConnection(mUrl), mBuffer); + return exerciseHttpURLConnection(mCronetEngine.openConnection(mUrl), mBuffer); } catch (IOException e) { System.out.println("Cronet HttpURLConnection failed with " + e); return false; @@ -480,10 +473,8 @@ } break; case CRONET_HUC: { - final CronetHttpURLStreamHandler cronetStreamHandler = - new CronetHttpURLStreamHandler(mCronetEngine); for (int i = 0; i < mIterations; i++) { - tasks.add(new CronetHttpURLConnectionFetchTask(cronetStreamHandler)); + tasks.add(new CronetHttpURLConnectionFetchTask()); } break; }
diff --git a/components/data_usage.gypi b/components/data_usage.gypi new file mode 100644 index 0000000..8151539 --- /dev/null +++ b/components/data_usage.gypi
@@ -0,0 +1,22 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'data_usage_core', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../net/net.gyp:net', + '../url/url.gyp:url_lib', + ], + 'sources': [ + 'data_usage/core/data_use.cc', + 'data_usage/core/data_use.h', + 'data_usage/core/data_use_aggregator.cc', + 'data_usage/core/data_use_aggregator.h', + ] + }, + ] +}
diff --git a/components/data_usage/OWNERS b/components/data_usage/OWNERS new file mode 100644 index 0000000..38f02cc1 --- /dev/null +++ b/components/data_usage/OWNERS
@@ -0,0 +1,2 @@ +bengr@chromium.org +sclittle@chromium.org
diff --git a/components/data_usage/PRESUBMIT.py b/components/data_usage/PRESUBMIT.py new file mode 100644 index 0000000..60e8fdf --- /dev/null +++ b/components/data_usage/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Top-level presubmit script for the data_usage component. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/data_usage/core/BUILD.gn b/components/data_usage/core/BUILD.gn new file mode 100644 index 0000000..963e9e95 --- /dev/null +++ b/components/data_usage/core/BUILD.gn
@@ -0,0 +1,34 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("core") { + sources = [ + "data_use.cc", + "data_use.h", + "data_use_aggregator.cc", + "data_use_aggregator.h", + ] + deps = [ + "//base", + "//net", + "//url", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "data_use_aggregator_unittest.cc", + ] + + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + + deps = [ + ":core", + "//base", + "//base/test:test_support", + "//net:test_support", + "//testing/gtest", + ] +}
diff --git a/components/data_usage/core/DEPS b/components/data_usage/core/DEPS new file mode 100644 index 0000000..d97699df --- /dev/null +++ b/components/data_usage/core/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+net", + "+url", +]
diff --git a/components/data_usage/core/data_use.cc b/components/data_usage/core/data_use.cc new file mode 100644 index 0000000..f19262e --- /dev/null +++ b/components/data_usage/core/data_use.cc
@@ -0,0 +1,24 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/data_usage/core/data_use.h" + +namespace data_usage { + +DataUse::DataUse(const GURL& url, + const base::Time& request_time, + const GURL& first_party_for_cookies, + int32_t tab_id, + net::NetworkChangeNotifier::ConnectionType connection_type, + int64_t tx_bytes, + int64_t rx_bytes) + : url(url), + request_time(request_time), + first_party_for_cookies(first_party_for_cookies), + tab_id(tab_id), + connection_type(connection_type), + tx_bytes(tx_bytes), + rx_bytes(rx_bytes) {} + +} // namespace data_usage
diff --git a/components/data_usage/core/data_use.h b/components/data_usage/core/data_use.h new file mode 100644 index 0000000..4c0c5c1a --- /dev/null +++ b/components/data_usage/core/data_use.h
@@ -0,0 +1,40 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DATA_USAGE_CORE_DATA_USE_H_ +#define COMPONENTS_DATA_USAGE_CORE_DATA_USE_H_ + +#include <stdint.h> + +#include "base/time/time.h" +#include "net/base/network_change_notifier.h" +#include "url/gurl.h" + +namespace data_usage { + +struct DataUse { + DataUse(const GURL& url, + const base::Time& request_time, + const GURL& first_party_for_cookies, + int32_t tab_id, + net::NetworkChangeNotifier::ConnectionType connection_type, + int64_t tx_bytes, + int64_t rx_bytes); + + GURL url; + // The time when the request that is associated with these bytes was started. + base::Time request_time; + GURL first_party_for_cookies; + int32_t tab_id; + net::NetworkChangeNotifier::ConnectionType connection_type; + // TODO(sclittle): Add more network info here, e.g. for Android, SIM operator + // and whether the device is roaming. + + int64_t tx_bytes; + int64_t rx_bytes; +}; + +} // namespace data_usage + +#endif // COMPONENTS_DATA_USAGE_CORE_DATA_USE_H_
diff --git a/components/data_usage/core/data_use_aggregator.cc b/components/data_usage/core/data_use_aggregator.cc new file mode 100644 index 0000000..7613a01 --- /dev/null +++ b/components/data_usage/core/data_use_aggregator.cc
@@ -0,0 +1,57 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/data_usage/core/data_use_aggregator.h" + +#include "net/base/network_change_notifier.h" +#include "net/url_request/url_request.h" + +namespace data_usage { + +DataUseAggregator::DataUseAggregator() {} + +DataUseAggregator::~DataUseAggregator() {} + +void DataUseAggregator::AddObserver(Observer* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + observer_list_.AddObserver(observer); +} + +void DataUseAggregator::RemoveObserver(Observer* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + observer_list_.RemoveObserver(observer); +} + +void DataUseAggregator::ReportDataUse(const net::URLRequest& request, + int32_t tab_id, + int64_t tx_bytes, + int64_t rx_bytes) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // TODO(sclittle): Once actual buffering/aggregation is being done, consider + // combining consecutive data use entries from the same request. + DataUse data_use(request.url(), request.request_time(), + request.first_party_for_cookies(), tab_id, + net::NetworkChangeNotifier::GetConnectionType(), tx_bytes, + rx_bytes); + + // TODO(sclittle): Buffer and amortize data use on supported platforms. + NotifyDataUse(std::vector<DataUse>(1, data_use)); +} + +void DataUseAggregator::ReportOffTheRecordDataUse(int64_t tx_bytes, + int64_t rx_bytes) { + DCHECK(thread_checker_.CalledOnValidThread()); + // TODO(sclittle): Once data usage amortization is implemented, keep track of + // the off-the-record bytes so that they can be taken out of the amortized + // data usage calculations if applicable. +} + +void DataUseAggregator::NotifyDataUse( + const std::vector<DataUse>& data_use_sequence) { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(Observer, observer_list_, OnDataUse(data_use_sequence)); +} + +} // namespace data_usage
diff --git a/components/data_usage/core/data_use_aggregator.h b/components/data_usage/core/data_use_aggregator.h new file mode 100644 index 0000000..4c14ec1 --- /dev/null +++ b/components/data_usage/core/data_use_aggregator.h
@@ -0,0 +1,64 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DATA_USAGE_CORE_DATA_USE_AGGREGATOR_H_ +#define COMPONENTS_DATA_USAGE_CORE_DATA_USE_AGGREGATOR_H_ + +#include <stdint.h> + +#include <vector> + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/threading/thread_checker.h" +#include "components/data_usage/core/data_use.h" + +namespace net { +class URLRequest; +} + +namespace data_usage { + +// Class that collects and aggregates network usage, reporting the usage to +// observers. Should only be used on the IO thread. +class DataUseAggregator { + public: + class Observer { + public: + virtual ~Observer() {} + // TODO(sclittle): Consider performing some pre-aggregation on the data use. + virtual void OnDataUse(const std::vector<DataUse>& data_use_sequence) = 0; + }; + + DataUseAggregator(); + virtual ~DataUseAggregator(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Virtual for testing. + virtual void ReportDataUse(const net::URLRequest& request, + int32_t tab_id, + int64_t tx_bytes, + int64_t rx_bytes); + + // Account for off-the-record data use. This usage is only kept track of here + // so that it can be taken out of any amortized data usage calculations, and a + // per-request breakdown of off-the-record data usage will never leave the + // DataUseAggregator. + // Virtual for testing. + virtual void ReportOffTheRecordDataUse(int64_t tx_bytes, int64_t rx_bytes); + + private: + void NotifyDataUse(const std::vector<DataUse>& data_use_sequence); + + base::ThreadChecker thread_checker_; + base::ObserverList<Observer> observer_list_; + + DISALLOW_COPY_AND_ASSIGN(DataUseAggregator); +}; + +} // namespace data_usage + +#endif // COMPONENTS_DATA_USAGE_CORE_DATA_USE_AGGREGATOR_H_
diff --git a/components/data_usage/core/data_use_aggregator_unittest.cc b/components/data_usage/core/data_use_aggregator_unittest.cc new file mode 100644 index 0000000..daa80c82 --- /dev/null +++ b/components/data_usage/core/data_use_aggregator_unittest.cc
@@ -0,0 +1,234 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/data_usage/core/data_use_aggregator.h" + +#include <stdint.h> + +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "components/data_usage/core/data_use.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_delegate_impl.h" +#include "net/socket/socket_test_util.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace data_usage { + +namespace { + +// Override NetworkChangeNotifier to simulate connection type changes for tests. +class TestNetworkChangeNotifier : public net::NetworkChangeNotifier { + public: + TestNetworkChangeNotifier() + : net::NetworkChangeNotifier(), + connection_type_to_return_( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN) {} + + // Simulates a change of the connection type to |type|. + void SimulateNetworkConnectionChange(ConnectionType type) { + connection_type_to_return_ = type; + } + + private: + ConnectionType GetCurrentConnectionType() const override { + return connection_type_to_return_; + } + + // The currently simulated network connection type. + ConnectionType connection_type_to_return_; + + DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier); +}; + +// A network delegate that reports all received and sent network bytes to a +// DataUseAggregator. +class ReportingNetworkDelegate : public net::NetworkDelegateImpl { + public: + explicit ReportingNetworkDelegate(DataUseAggregator* data_use_aggregator) + : data_use_aggregator_(data_use_aggregator), tab_id_for_requests_(-1) {} + + ~ReportingNetworkDelegate() override {} + + void set_tab_id_for_requests(int32_t tab_id_for_requests) { + tab_id_for_requests_ = tab_id_for_requests; + } + + private: + void OnNetworkBytesReceived(const net::URLRequest& request, + int64_t bytes_received) override { + data_use_aggregator_->ReportDataUse(request, tab_id_for_requests_, + 0 /* tx_bytes */, bytes_received); + } + + void OnNetworkBytesSent(const net::URLRequest& request, + int64_t bytes_sent) override { + data_use_aggregator_->ReportDataUse(request, tab_id_for_requests_, + bytes_sent, 0 /* rx_bytes */); + } + + DataUseAggregator* data_use_aggregator_; + int32_t tab_id_for_requests_; + + DISALLOW_COPY_AND_ASSIGN(ReportingNetworkDelegate); +}; + +// An observer that keeps track of all the data use it observed. +class TestObserver : public DataUseAggregator::Observer { + public: + explicit TestObserver(DataUseAggregator* data_use_aggregator) + : data_use_aggregator_(data_use_aggregator) { + data_use_aggregator_->AddObserver(this); + } + + ~TestObserver() override { data_use_aggregator_->RemoveObserver(this); } + + void OnDataUse(const std::vector<DataUse>& data_use_sequence) override { + observed_data_use_.insert(observed_data_use_.end(), + data_use_sequence.begin(), + data_use_sequence.end()); + } + + const std::vector<DataUse>& observed_data_use() const { + return observed_data_use_; + } + + private: + DataUseAggregator* data_use_aggregator_; + std::vector<DataUse> observed_data_use_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + +class DataUseAggregatorTest : public testing::Test { + public: + DataUseAggregatorTest() + : reporting_network_delegate_(&data_use_aggregator_), + context_(true), + test_observer_(&data_use_aggregator_) { + context_.set_client_socket_factory(&mock_socket_factory_); + context_.set_network_delegate(&reporting_network_delegate_); + context_.Init(); + } + + ~DataUseAggregatorTest() override {} + + scoped_ptr<net::URLRequest> ExecuteRequest( + const GURL& url, + const GURL& first_party_for_cookies) { + net::MockRead reads[] = { + net::MockRead("HTTP/1.1 200 OK\r\n\r\n"), net::MockRead("hello world"), + net::MockRead(net::SYNCHRONOUS, net::OK), + }; + net::StaticSocketDataProvider socket(reads, arraysize(reads), nullptr, 0); + mock_socket_factory_.AddSocketDataProvider(&socket); + + net::TestDelegate delegate; + scoped_ptr<net::URLRequest> request = + context_.CreateRequest(url, net::IDLE, &delegate); + request->set_first_party_for_cookies(first_party_for_cookies); + request->Start(); + loop_.RunUntilIdle(); + + return request.Pass(); + } + + void SimulateNetworkConnectionChange( + net::NetworkChangeNotifier::ConnectionType connection_type) { + test_network_change_notifier_.SimulateNetworkConnectionChange( + connection_type); + } + + void set_tab_id_for_requests(int32_t tab_id_for_requests) { + reporting_network_delegate_.set_tab_id_for_requests(tab_id_for_requests); + } + + DataUseAggregator* data_use_aggregator() { return &data_use_aggregator_; } + + const std::vector<DataUse>& observed_data_use() const { + return test_observer_.observed_data_use(); + } + + private: + base::MessageLoopForIO loop_; + TestNetworkChangeNotifier test_network_change_notifier_; + + DataUseAggregator data_use_aggregator_; + net::MockClientSocketFactory mock_socket_factory_; + ReportingNetworkDelegate reporting_network_delegate_; + net::TestURLRequestContext context_; + TestObserver test_observer_; + + DISALLOW_COPY_AND_ASSIGN(DataUseAggregatorTest); +}; + +TEST_F(DataUseAggregatorTest, ReportDataUse) { + const net::NetworkChangeNotifier::ConnectionType kFooConnectionType = + net::NetworkChangeNotifier::CONNECTION_2G; + SimulateNetworkConnectionChange(kFooConnectionType); + const int32_t kFooTabId = 10; + set_tab_id_for_requests(kFooTabId); + const scoped_ptr<net::URLRequest> foo_request = + ExecuteRequest(GURL("http://foo.com"), GURL("http://foofirstparty.com")); + + const net::NetworkChangeNotifier::ConnectionType kBarConnectionType = + net::NetworkChangeNotifier::CONNECTION_WIFI; + SimulateNetworkConnectionChange(kBarConnectionType); + const int32_t kBarTabId = 20; + set_tab_id_for_requests(kBarTabId); + scoped_ptr<net::URLRequest> bar_request = + ExecuteRequest(GURL("http://bar.com"), GURL("http://barfirstparty.com")); + + auto data_use_it = observed_data_use().begin(); + + // First, the |foo_request| data use should have happened. + int64_t observed_foo_tx_bytes = 0, observed_foo_rx_bytes = 0; + while (data_use_it != observed_data_use().end() && + data_use_it->url == GURL("http://foo.com")) { + EXPECT_EQ(foo_request->request_time(), data_use_it->request_time); + EXPECT_EQ(GURL("http://foofirstparty.com"), + data_use_it->first_party_for_cookies); + EXPECT_EQ(kFooTabId, data_use_it->tab_id); + EXPECT_EQ(kFooConnectionType, data_use_it->connection_type); + + observed_foo_tx_bytes += data_use_it->tx_bytes; + observed_foo_rx_bytes += data_use_it->rx_bytes; + ++data_use_it; + } + EXPECT_EQ(foo_request->GetTotalSentBytes(), observed_foo_tx_bytes); + EXPECT_EQ(foo_request->GetTotalReceivedBytes(), observed_foo_rx_bytes); + + // Then, the |bar_request| data use should have happened. + int64_t observed_bar_tx_bytes = 0, observed_bar_rx_bytes = 0; + while (data_use_it != observed_data_use().end()) { + EXPECT_EQ(GURL("http://bar.com"), data_use_it->url); + EXPECT_EQ(bar_request->request_time(), data_use_it->request_time); + EXPECT_EQ(GURL("http://barfirstparty.com"), + data_use_it->first_party_for_cookies); + EXPECT_EQ(kBarTabId, data_use_it->tab_id); + EXPECT_EQ(kBarConnectionType, data_use_it->connection_type); + + observed_bar_tx_bytes += data_use_it->tx_bytes; + observed_bar_rx_bytes += data_use_it->rx_bytes; + ++data_use_it; + } + EXPECT_EQ(bar_request->GetTotalSentBytes(), observed_bar_tx_bytes); + EXPECT_EQ(bar_request->GetTotalReceivedBytes(), observed_bar_rx_bytes); +} + +TEST_F(DataUseAggregatorTest, ReportOffTheRecordDataUse) { + // Off the record data use should not be reported to observers. + data_use_aggregator()->ReportOffTheRecordDataUse(1000, 1000); + base::MessageLoop::current()->RunUntilIdle(); + EXPECT_EQ(static_cast<size_t>(0), observed_data_use().size()); +} + +} // namespace + +} // namespace data_usage
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc index 58c0c8cb..aea23c5 100644 --- a/components/favicon/core/favicon_handler.cc +++ b/components/favicon/core/favicon_handler.cc
@@ -151,6 +151,27 @@ return area1 > area2; } +// Sorts the entries in |image_urls| by icon size in descending order. +// Discards all but the largest size for each FaviconURL. +void SortAndPruneImageUrls(std::vector<FaviconURL>* image_urls) { + // Not using const-reference since the loop mutates FaviconURL::icon_sizes. + for (FaviconURL& image_url : *image_urls) { + if (image_url.icon_sizes.empty()) + continue; + + gfx::Size largest = + image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)]; + image_url.icon_sizes.clear(); + image_url.icon_sizes.push_back(largest); + } + std::stable_sort(image_urls->begin(), image_urls->end(), CompareIconSize); +} + +// Checks whether two FaviconURLs are equal ignoring the icon sizes. +bool FaviconURLsEqualIgnoringSizes(const FaviconURL& u1, const FaviconURL& u2) { + return u1.icon_type == u2.icon_type && u1.icon_url == u2.icon_url; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -199,7 +220,8 @@ icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), download_largest_icon_(download_largest_icon), service_(service), - driver_(driver) { + driver_(driver), + current_candidate_index_(0u) { DCHECK(driver_); } @@ -230,6 +252,7 @@ download_requests_.clear(); image_urls_.clear(); history_results_.clear(); + current_candidate_index_ = 0u; best_favicon_candidate_ = FaviconCandidate(); // Request the favicon from the history service. In parallel to this the @@ -266,11 +289,15 @@ // - next candidate has sizes attribute and it is not larger than largest, // - current candidate is maximal one we want. const int maximal_size = GetMaximalIconSize(icon_type); - exact_match = image_urls_.size() == 1 || - image_urls_[1].icon_sizes.empty() || - image_urls_[1].icon_sizes[0].GetArea() <= largest.GetArea() || - (image.Size().width() == maximal_size && - image.Size().height() == maximal_size); + if (current_candidate_index_ + 1 >= image_urls_.size()) { + exact_match = true; + } else { + FaviconURL next_image_url = image_urls_[current_candidate_index_ + 1]; + exact_match = next_image_url.icon_sizes.empty() || + next_image_url.icon_sizes[0].GetArea() <= largest.GetArea() || + (image.Size().width() == maximal_size && + image.Size().height() == maximal_size); + } } else { exact_match = score == 1 || preferred_icon_size() == 0; replace_best_favicon_candidate = @@ -326,32 +353,37 @@ if (page_url != url_) return; - download_requests_.clear(); - image_urls_.clear(); - best_favicon_candidate_ = FaviconCandidate(); - + std::vector<FaviconURL> pruned_candidates; for (const FaviconURL& candidate : candidates) { if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) - image_urls_.push_back(candidate); + pruned_candidates.push_back(candidate); } if (download_largest_icon_) - SortAndPruneImageUrls(); + SortAndPruneImageUrls(&pruned_candidates); + + // Ignore FaviconURL::icon_sizes because FaviconURL::icon_sizes is not stored + // in the history database. + if (image_urls_.size() == pruned_candidates.size() && + std::equal(pruned_candidates.begin(), pruned_candidates.end(), + image_urls_.begin(), FaviconURLsEqualIgnoringSizes)) { + return; + } + + download_requests_.clear(); + image_urls_ = pruned_candidates; + current_candidate_index_ = 0u; + best_favicon_candidate_ = FaviconCandidate(); // TODO(davemoore) Should clear on empty url. Currently we ignore it. // This appears to be what FF does as well. - if (!image_urls_.empty()) + if (current_candidate()) ProcessCurrentUrl(); } void FaviconHandler::ProcessCurrentUrl() { DCHECK(!image_urls_.empty()); - // current_candidate() may return NULL if download_largest_icon_ is true and - // all the sizes are larger than the max. - if (!current_candidate()) - return; - if (current_candidate()->icon_type == favicon_base::FAVICON && !download_largest_icon_) { if (!favicon_expired_or_incomplete_ && @@ -426,9 +458,9 @@ } } - if (request_next_icon && image_urls_.size() > 1) { - // Remove the first member of image_urls_ and process the remaining. - image_urls_.erase(image_urls_.begin()); + if (request_next_icon && current_candidate_index_ + 1 < image_urls_.size()) { + // Process the next candidate. + ++current_candidate_index_; ProcessCurrentUrl(); } else { // We have either found the ideal candidate or run out of candidates. @@ -439,8 +471,8 @@ best_favicon_candidate_.icon_type); } // Clear download related state. - image_urls_.clear(); download_requests_.clear(); + current_candidate_index_ = image_urls_.size(); best_favicon_candidate_ = FaviconCandidate(); } } @@ -664,19 +696,4 @@ } } -void FaviconHandler::SortAndPruneImageUrls() { - // Not using const-reference since the loop mutates FaviconURL::icon_sizes. - for (FaviconURL& image_url : image_urls_) { - if (image_url.icon_sizes.empty()) - continue; - - gfx::Size largest = - image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)]; - image_url.icon_sizes.clear(); - image_url.icon_sizes.push_back(largest); - } - std::stable_sort(image_urls_.begin(), image_urls_.end(), - CompareIconSize); -} - } // namespace favicon
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h index 4850f3c..48f45949 100644 --- a/components/favicon/core/favicon_handler.h +++ b/components/favicon/core/favicon_handler.h
@@ -231,7 +231,9 @@ // Return the current candidate if any. favicon::FaviconURL* current_candidate() { - return (!image_urls_.empty()) ? &image_urls_.front() : NULL; + return current_candidate_index_ < image_urls_.size() + ? &image_urls_[current_candidate_index_] + : nullptr; } // Returns the preferred size of the image. 0 means no preference (any size @@ -242,11 +244,6 @@ return handler_type_ == FAVICON ? gfx::kFaviconSize : 0; } - // Sorts the entries in |image_urls_| by icon size in descending order. - // Additionally removes any entries whose sizes are all greater than the max - // allowed size. - void SortAndPruneImageUrls(); - // Used for FaviconService requests. base::CancelableTaskTracker cancelable_task_tracker_; @@ -288,6 +285,10 @@ // This handler's driver, owns this object. FaviconDriver* driver_; + // The index of the favicon URL in |image_urls_| which is currently being + // requested from history or downloaded. + size_t current_candidate_index_; + // Best image we've seen so far. As images are downloaded from the page they // are stored here. When there is an exact match, or no more images are // available the favicon service and the current page are updated (assuming
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc index 69869039..ca89afaa 100644 --- a/components/favicon/core/favicon_handler_unittest.cc +++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -329,15 +329,14 @@ return download_handler_.get(); } - // Methods to access favicon internals. - const std::vector<FaviconURL>& urls() { - return image_urls_; - } - FaviconURL* current_candidate() { return FaviconHandler::current_candidate(); } + size_t current_candidate_index() const { + return current_candidate_index_; + } + const FaviconCandidate& best_favicon_candidate() { return best_favicon_candidate_; } @@ -555,7 +554,7 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.image_urls().size()); ASSERT_TRUE(helper.current_candidate()); ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::FAVICON, helper.current_candidate()->icon_type); @@ -597,7 +596,7 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.image_urls().size()); ASSERT_TRUE(helper.current_candidate()); ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::FAVICON, helper.current_candidate()->icon_type); @@ -666,7 +665,7 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status. - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.image_urls().size()); ASSERT_TRUE(helper.current_candidate()); ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::FAVICON, helper.current_candidate()->icon_type); @@ -814,7 +813,7 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status. - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.image_urls().size()); ASSERT_TRUE(helper.current_candidate()); ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::FAVICON, helper.current_candidate()->icon_type); @@ -883,7 +882,8 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status. - EXPECT_EQ(2U, helper.urls().size()); + EXPECT_EQ(2u, helper.image_urls().size()); + EXPECT_EQ(0u, helper.current_candidate_index()); ASSERT_TRUE(helper.current_candidate()); ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON, @@ -913,7 +913,7 @@ download_handler->InvokeCallback(); // Left 1 url. - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.current_candidate_index()); ASSERT_TRUE(helper.current_candidate()); EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url); EXPECT_EQ(favicon_base::TOUCH_ICON, helper.current_candidate()->icon_type); @@ -994,8 +994,8 @@ helper.OnUpdateFaviconURL(page_url, urls); // Verify FaviconHandler status. - EXPECT_EQ(2U, helper.urls().size()); - ASSERT_TRUE(helper.current_candidate()); + EXPECT_EQ(2u, helper.image_urls().size()); + ASSERT_EQ(0u, helper.current_candidate_index()); ASSERT_EQ(icon_url, helper.current_candidate()->icon_url); ASSERT_EQ(favicon_base::TOUCH_PRECOMPOSED_ICON, helper.current_candidate()->icon_type); @@ -1027,7 +1027,8 @@ latest_icon_url, favicon_base::TOUCH_ICON, std::vector<gfx::Size>())); helper.OnUpdateFaviconURL(page_url, latest_urls); - EXPECT_EQ(1U, helper.urls().size()); + EXPECT_EQ(1u, helper.image_urls().size()); + EXPECT_EQ(0u, helper.current_candidate_index()); EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url); EXPECT_EQ(favicon_base::TOUCH_ICON, helper.current_candidate()->icon_type); @@ -1065,6 +1066,59 @@ EXPECT_FALSE(download_handler->HasDownload()); } +// Test that sending an icon URL update identical to the previous icon URL +// update is a no-op. +TEST_F(FaviconHandlerTest, UpdateSameIconURLs) { + const GURL page_url("http://www.google.com"); + const GURL icon_url1("http://www.google.com/favicon1"); + const GURL icon_url2("http://www.google.com/favicon2"); + std::vector<FaviconURL> favicon_urls; + favicon_urls.push_back(FaviconURL(GURL("http://www.google.com/favicon1"), + favicon_base::FAVICON, + std::vector<gfx::Size>())); + favicon_urls.push_back(FaviconURL(GURL("http://www.google.com/favicon2"), + favicon_base::FAVICON, + std::vector<gfx::Size>())); + + TestFaviconDriver driver; + TestFaviconHandler helper(page_url, &driver, FaviconHandler::FAVICON, false); + + // Initiate a request for favicon data for |page_url|. History does not know + // about the page URL or the icon URLs. + helper.FetchFavicon(page_url); + helper.history_handler()->InvokeCallback(); + helper.set_history_handler(nullptr); + + // Got icon URLs. + helper.OnUpdateFaviconURL(page_url, favicon_urls); + + // There should be an ongoing history request for |icon_url1|. + ASSERT_EQ(2u, helper.image_urls().size()); + ASSERT_EQ(0u, helper.current_candidate_index()); + HistoryRequestHandler* history_handler = helper.history_handler(); + ASSERT_TRUE(history_handler); + + // Calling OnUpdateFaviconURL() with the same icon URLs should have no effect. + helper.OnUpdateFaviconURL(page_url, favicon_urls); + EXPECT_EQ(history_handler, helper.history_handler()); + + // Complete history request for |icon_url1| and do download. + helper.history_handler()->InvokeCallback(); + helper.set_history_handler(nullptr); + helper.download_handler()->SetImageSizes(std::vector<int>(1u, 10)); + helper.download_handler()->InvokeCallback(); + helper.download_handler()->Reset(); + + // There should now be an ongoing history request for |icon_url2|. + ASSERT_EQ(1u, helper.current_candidate_index()); + history_handler = helper.history_handler(); + ASSERT_TRUE(history_handler); + + // Calling OnUpdateFaviconURL() with the same icon URLs should have no effect. + helper.OnUpdateFaviconURL(page_url, favicon_urls); + EXPECT_EQ(history_handler, helper.history_handler()); +} + // Test the favicon which is selected when the web page provides several // favicons and none of the favicons are cached in history. // The goal of this test is to be more of an integration test than @@ -1107,7 +1161,7 @@ DownloadTillDoneIgnoringHistory( &driver1, &handler1, kPageURL, urls1, kSizes1); - EXPECT_EQ(0u, handler1.image_urls().size()); + EXPECT_EQ(nullptr, handler1.current_candidate()); EXPECT_TRUE(driver1.GetActiveFaviconValidity()); EXPECT_FALSE(driver1.GetActiveFaviconImage().IsEmpty()); EXPECT_EQ(gfx::kFaviconSize, driver1.GetActiveFaviconImage().Width()); @@ -1210,7 +1264,7 @@ DownloadTillDoneIgnoringHistory( &driver, &handler, kPageURL, urls2, kSizes2); - EXPECT_EQ(0u, handler.image_urls().size()); + EXPECT_EQ(nullptr, handler.current_candidate()); EXPECT_TRUE(driver.GetActiveFaviconValidity()); EXPECT_FALSE(driver.GetActiveFaviconImage().IsEmpty()); int expected_index = 2u; @@ -1262,7 +1316,7 @@ kFaviconURLs + arraysize(kFaviconURLs)); DownloadTillDoneIgnoringHistory(&driver, &handler, kPageURL, urls, kSizes); - EXPECT_EQ(0u, handler.image_urls().size()); + EXPECT_EQ(nullptr, handler.current_candidate()); EXPECT_FALSE(driver.GetActiveFaviconValidity()); EXPECT_TRUE(driver.GetActiveFaviconImage().IsEmpty()); } @@ -1389,23 +1443,20 @@ // Simulate the download failed, to check whether the icons were requested // to download according their size. struct ExpectedResult { - // The size of image_urls_. - size_t image_urls_size; // The favicon's index in kSourceIconURLs. size_t favicon_index; // Width of largest bitmap. int width; } results[] = { - {5, 0, 1024}, - {4, 2, 512}, - {3, 1, 15}, + {0, 1024}, + {2, 512}, + {1, 15}, // The rest of bitmaps come in order. - {2, 3, -1}, - {1, 4, -1}, + {3, -1}, + {4, -1}, }; for (int i = 0; i < 5; ++i) { - ASSERT_EQ(results[i].image_urls_size, handler1.image_urls().size()); EXPECT_EQ(kSourceIconURLs[results[i].favicon_index].icon_url, handler1.current_candidate()->icon_url); if (results[i].width != -1) { @@ -1450,7 +1501,7 @@ kSourceIconURLs + arraysize(kSourceIconURLs)); UpdateFaviconURL(&driver1, &handler1, kPageURL, urls1); - ASSERT_EQ(2u, handler1.urls().size()); + ASSERT_EQ(2u, handler1.image_urls().size()); // Index of largest favicon in kSourceIconURLs. size_t i = 1; @@ -1517,7 +1568,7 @@ kSourceIconURLs + arraysize(kSourceIconURLs)); UpdateFaviconURL(&driver1, &handler1, kPageURL, urls1); - ASSERT_EQ(2u, handler1.urls().size()); + ASSERT_EQ(2u, handler1.image_urls().size()); // Index of largest favicon in kSourceIconURLs. size_t i = 1; @@ -1577,7 +1628,7 @@ std::vector<FaviconURL> urls1(kSourceIconURLs, kSourceIconURLs + arraysize(kSourceIconURLs)); UpdateFaviconURL(&driver1, &handler1, kPageURL, urls1); - ASSERT_EQ(3u, handler1.urls().size()); + ASSERT_EQ(3u, handler1.image_urls().size()); // Simulate no favicon from history. handler1.history_handler()->history_results_.clear();
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn index f9a6217..618a149 100644 --- a/components/html_viewer/BUILD.gn +++ b/components/html_viewer/BUILD.gn
@@ -64,6 +64,8 @@ "blink_platform_impl.cc", "blink_platform_impl.h", "blink_resource_constants.h", + "blink_settings.cc", + "blink_settings.h", "blink_text_input_type_converters.cc", "blink_text_input_type_converters.h", "blink_url_request_type_converters.cc",
diff --git a/components/html_viewer/blink_settings.cc b/components/html_viewer/blink_settings.cc new file mode 100644 index 0000000..0973c9f --- /dev/null +++ b/components/html_viewer/blink_settings.cc
@@ -0,0 +1,869 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/html_viewer/blink_settings.h" + +#include <map> +#include <string> + +#include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" +#include "net/base/network_change_notifier.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h" +#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "third_party/WebKit/public/web/WebSettings.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/icu/source/common/unicode/uchar.h" +#include "third_party/icu/source/common/unicode/uscript.h" +#include "ui/base/touch/touch_device.h" +#include "ui/base/ui_base_switches_util.h" +#include "ui/gfx/font_render_params.h" + +#if defined(OS_ANDROID) +#include "url/gurl.h" +#endif + +#if defined(OS_LINUX) +#include "third_party/WebKit/public/web/linux/WebFontRendering.h" +#endif + +namespace html_viewer { + +// TODO(rjkroege): Update this code once http://crbug.com/481108 has been +// completed and the WebSettings parameter space has been reduced. +// +// The code inside the anonymous namespace has been copied from content +// and is largely unchanged here. My assumption is that this is a +// temporary measure until 481108 is resolved. +namespace { + +// Command line switch string to disable experimental WebGL. +const char kDisableWebGLSwitch[] = "disable-webgl"; +const char kEnableAccelerated2DCanvas[] = "enable-accelerated-2d-canvas"; + +// Map of ISO 15924 four-letter script code to font family. For example, +// "Arab" to "My Arabic Font". +typedef std::map<std::string, base::string16> ScriptFontFamilyMap; + +enum EditingBehavior { + EDITING_BEHAVIOR_MAC, + EDITING_BEHAVIOR_WIN, + EDITING_BEHAVIOR_UNIX, + EDITING_BEHAVIOR_ANDROID, + EDITING_BEHAVIOR_LAST = EDITING_BEHAVIOR_ANDROID +}; + +// Cache options for V8. See V8CacheOptions.h for information on the options. +enum V8CacheOptions { + V8_CACHE_OPTIONS_DEFAULT, + V8_CACHE_OPTIONS_NONE, + V8_CACHE_OPTIONS_PARSE, + V8_CACHE_OPTIONS_CODE, + V8_CACHE_OPTIONS_LAST = V8_CACHE_OPTIONS_CODE +}; + +// ImageAnimationPolicy is used for controlling image animation when +// image frame is rendered for animation. See +// third_party/WebKit/Source/platform/graphics/ImageAnimationPolicy.h for +// information on the options. +enum ImageAnimationPolicy { + IMAGE_ANIMATION_POLICY_ALLOWED, + IMAGE_ANIMATION_POLICY_ANIMATION_ONCE, + IMAGE_ANIMATION_POLICY_NO_ANIMATION +}; + +// A struct for managing blink's settings. +struct WebPreferences { + ScriptFontFamilyMap standard_font_family_map; + ScriptFontFamilyMap fixed_font_family_map; + ScriptFontFamilyMap serif_font_family_map; + ScriptFontFamilyMap sans_serif_font_family_map; + ScriptFontFamilyMap cursive_font_family_map; + ScriptFontFamilyMap fantasy_font_family_map; + ScriptFontFamilyMap pictograph_font_family_map; + int default_font_size; + int default_fixed_font_size; + int minimum_font_size; + int minimum_logical_font_size; + std::string default_encoding; + bool context_menu_on_mouse_up; + bool javascript_enabled; + bool web_security_enabled; + bool javascript_can_open_windows_automatically; + bool loads_images_automatically; + bool images_enabled; + bool plugins_enabled; + bool dom_paste_enabled; + bool shrinks_standalone_images_to_fit; + bool uses_universal_detector; + bool text_areas_are_resizable; + bool allow_scripts_to_close_windows; + bool remote_fonts_enabled; + bool javascript_can_access_clipboard; + bool xslt_enabled; + bool xss_auditor_enabled; + // We don't use dns_prefetching_enabled to disable DNS prefetching. Instead, + // we disable the feature at a lower layer so that we catch non-WebKit uses + // of DNS prefetch as well. + bool dns_prefetching_enabled; + bool local_storage_enabled; + bool databases_enabled; + bool application_cache_enabled; + bool tabs_to_links; + bool caret_browsing_enabled; + bool hyperlink_auditing_enabled; + bool is_online; + net::NetworkChangeNotifier::ConnectionType net_info_connection_type; + double net_info_max_bandwidth_mbps; + bool allow_universal_access_from_file_urls; + bool allow_file_access_from_file_urls; + bool webaudio_enabled; + bool experimental_webgl_enabled; + bool pepper_3d_enabled; + bool flash_3d_enabled; + bool flash_stage3d_enabled; + bool flash_stage3d_baseline_enabled; + bool gl_multisampling_enabled; + bool privileged_webgl_extensions_enabled; + bool webgl_errors_to_console_enabled; + bool mock_scrollbars_enabled; + bool asynchronous_spell_checking_enabled; + bool unified_textchecker_enabled; + bool accelerated_2d_canvas_enabled; + int minimum_accelerated_2d_canvas_size; + bool antialiased_2d_canvas_disabled; + bool antialiased_clips_2d_canvas_enabled; + int accelerated_2d_canvas_msaa_sample_count; + bool accelerated_filters_enabled; + bool deferred_filters_enabled; + bool container_culling_enabled; + bool allow_displaying_insecure_content; + bool allow_running_insecure_content; + // If true, taints all <canvas> elements, regardless of origin. + bool disable_reading_from_canvas; + // Strict mixed content checking disables both displaying and running insecure + // mixed content, and disables embedder notifications that such content was + // requested (thereby preventing user override). + bool strict_mixed_content_checking; + // Strict powerful feature restrictions block insecure usage of powerful + // features (like geolocation) that we haven't yet disabled for the web at + // large. + bool strict_powerful_feature_restrictions; + // Disallow user opt-in for blockable mixed content. + bool strictly_block_blockable_mixed_content; + bool block_mixed_plugin_content; + bool password_echo_enabled; + bool should_print_backgrounds; + bool should_clear_document_background; + bool enable_scroll_animator; + bool css_variables_enabled; + bool touch_enabled; + // TODO(mustaq): Nuke when the new API is ready + bool device_supports_touch; + // TODO(mustaq): Nuke when the new API is ready + bool device_supports_mouse; + bool touch_adjustment_enabled; + int pointer_events_max_touch_points; + int available_pointer_types; + ui::PointerType primary_pointer_type; + int available_hover_types; + ui::HoverType primary_hover_type; + bool sync_xhr_in_documents_enabled; + bool image_color_profiles_enabled; + bool should_respect_image_orientation; + int number_of_cpu_cores; + EditingBehavior editing_behavior; + bool supports_multiple_windows; + bool viewport_enabled; + bool viewport_meta_enabled; + bool main_frame_resizes_are_orientation_changes; + bool initialize_at_minimum_page_scale; + bool smart_insert_delete_enabled; + bool spatial_navigation_enabled; + int pinch_overlay_scrollbar_thickness; + bool use_solid_color_scrollbars; + bool navigate_on_drag_drop; + V8CacheOptions v8_cache_options; + bool slimming_paint_v2_enabled; + bool inert_visual_viewport; + + // This flags corresponds to a Page's Settings' setCookieEnabled state. It + // only controls whether or not the "document.cookie" field is properly + // connected to the backing store, for instance if you wanted to be able to + // define custom getters and setters from within a unique security content + // without raising a DOM security exception. + bool cookie_enabled; + + // This flag indicates whether H/W accelerated video decode is enabled for + // pepper plugins. Defaults to false. + bool pepper_accelerated_video_decode_enabled; + + ImageAnimationPolicy animation_policy; + +#if defined(OS_ANDROID) + bool text_autosizing_enabled; + float font_scale_factor; + float device_scale_adjustment; + bool force_enable_zoom; + bool fullscreen_supported; + bool double_tap_to_zoom_enabled; + bool user_gesture_required_for_media_playback; + GURL default_video_poster_url; + bool support_deprecated_target_density_dpi; + bool use_legacy_background_size_shorthand_behavior; + bool wide_viewport_quirk; + bool use_wide_viewport; + bool force_zero_layout_height; + bool viewport_meta_layout_size_quirk; + bool viewport_meta_merge_content_quirk; + bool viewport_meta_non_user_scalable_quirk; + bool viewport_meta_zero_values_quirk; + bool clobber_user_agent_initial_scale_quirk; + bool ignore_main_frame_overflow_hidden_quirk; + bool report_screen_size_in_physical_pixels_quirk; + bool record_whole_document; + std::string autoplay_experiment_mode; +#endif + + // Default (used if the page or UA doesn't override these) values for page + // scale limits. These are set directly on the WebView so there's no analogue + // in WebSettings. + float default_minimum_page_scale_factor; + float default_maximum_page_scale_factor; + + // We try to keep the default values the same as the default values in + // chrome, except for the cases where it would require lots of extra work for + // the embedder to use the same default value. + WebPreferences(); + ~WebPreferences(); +}; + +blink::WebConnectionType NetConnectionTypeToWebConnectionType( + net::NetworkChangeNotifier::ConnectionType net_type) { + switch (net_type) { + case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: + return blink::WebConnectionTypeUnknown; + case net::NetworkChangeNotifier::CONNECTION_ETHERNET: + return blink::WebConnectionTypeEthernet; + case net::NetworkChangeNotifier::CONNECTION_WIFI: + return blink::WebConnectionTypeWifi; + case net::NetworkChangeNotifier::CONNECTION_NONE: + return blink::WebConnectionTypeNone; + case net::NetworkChangeNotifier::CONNECTION_2G: + case net::NetworkChangeNotifier::CONNECTION_3G: + case net::NetworkChangeNotifier::CONNECTION_4G: + return blink::WebConnectionTypeCellular; + case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH: + return blink::WebConnectionTypeBluetooth; + } + NOTREACHED(); + return blink::WebConnectionTypeNone; +} + +// "Zyyy" is the ISO 15924 script code for undetermined script aka Common. +const char kCommonScript[] = "Zyyy"; + +WebPreferences::WebPreferences() + : default_font_size(16), + default_fixed_font_size(13), + minimum_font_size(0), + minimum_logical_font_size(6), + default_encoding("ISO-8859-1"), +#if defined(OS_WIN) + context_menu_on_mouse_up(true), +#else + context_menu_on_mouse_up(false), +#endif + javascript_enabled(true), + web_security_enabled(true), + javascript_can_open_windows_automatically(true), + loads_images_automatically(true), + images_enabled(true), + plugins_enabled(true), + dom_paste_enabled(false), // enables execCommand("paste") + shrinks_standalone_images_to_fit(true), + uses_universal_detector(false), // Disabled: page cycler regression + text_areas_are_resizable(true), + allow_scripts_to_close_windows(false), + remote_fonts_enabled(true), + javascript_can_access_clipboard(false), + xslt_enabled(true), + xss_auditor_enabled(true), + dns_prefetching_enabled(true), + local_storage_enabled(false), + databases_enabled(false), + application_cache_enabled(false), + tabs_to_links(true), + caret_browsing_enabled(false), + hyperlink_auditing_enabled(true), + is_online(true), + net_info_connection_type(net::NetworkChangeNotifier::CONNECTION_NONE), + net_info_max_bandwidth_mbps( + net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype( + net::NetworkChangeNotifier::SUBTYPE_NONE)), + allow_universal_access_from_file_urls(false), + allow_file_access_from_file_urls(false), + webaudio_enabled(false), + experimental_webgl_enabled(false), + pepper_3d_enabled(false), + flash_3d_enabled(true), + flash_stage3d_enabled(false), + flash_stage3d_baseline_enabled(false), + gl_multisampling_enabled(true), + privileged_webgl_extensions_enabled(false), + webgl_errors_to_console_enabled(true), + mock_scrollbars_enabled(false), + asynchronous_spell_checking_enabled(true), + unified_textchecker_enabled(false), + accelerated_2d_canvas_enabled(false), + minimum_accelerated_2d_canvas_size(257 * 256), + antialiased_2d_canvas_disabled(false), + antialiased_clips_2d_canvas_enabled(false), + accelerated_2d_canvas_msaa_sample_count(0), + accelerated_filters_enabled(false), + deferred_filters_enabled(false), + container_culling_enabled(false), + allow_displaying_insecure_content(true), + allow_running_insecure_content(false), + disable_reading_from_canvas(false), + strict_mixed_content_checking(false), + strict_powerful_feature_restrictions(false), + strictly_block_blockable_mixed_content(false), + block_mixed_plugin_content(false), + password_echo_enabled(false), + should_print_backgrounds(false), + should_clear_document_background(true), + enable_scroll_animator(false), + touch_enabled(false), + device_supports_touch(false), + device_supports_mouse(true), + touch_adjustment_enabled(true), + pointer_events_max_touch_points(0), + available_pointer_types(0), + primary_pointer_type(ui::POINTER_TYPE_NONE), + available_hover_types(0), + primary_hover_type(ui::HOVER_TYPE_NONE), + sync_xhr_in_documents_enabled(true), + image_color_profiles_enabled(false), + should_respect_image_orientation(false), + number_of_cpu_cores(1), +#if defined(OS_MACOSX) + editing_behavior(EDITING_BEHAVIOR_MAC), +#elif defined(OS_WIN) + editing_behavior(EDITING_BEHAVIOR_WIN), +#elif defined(OS_ANDROID) + editing_behavior(EDITING_BEHAVIOR_ANDROID), +#elif defined(OS_POSIX) + editing_behavior(EDITING_BEHAVIOR_UNIX), +#else + editing_behavior(EDITING_BEHAVIOR_MAC), +#endif + supports_multiple_windows(true), + viewport_enabled(false), +#if defined(OS_ANDROID) + viewport_meta_enabled(true), +#else + viewport_meta_enabled(false), +#endif + main_frame_resizes_are_orientation_changes(false), + initialize_at_minimum_page_scale(true), +#if defined(OS_MACOSX) + smart_insert_delete_enabled(true), +#else + smart_insert_delete_enabled(false), +#endif + spatial_navigation_enabled(false), + pinch_overlay_scrollbar_thickness(0), + use_solid_color_scrollbars(false), + navigate_on_drag_drop(true), + v8_cache_options(V8_CACHE_OPTIONS_DEFAULT), + slimming_paint_v2_enabled(false), + inert_visual_viewport(false), + cookie_enabled(true), + pepper_accelerated_video_decode_enabled(false), + animation_policy(IMAGE_ANIMATION_POLICY_ALLOWED), +#if defined(OS_ANDROID) + text_autosizing_enabled(true), + font_scale_factor(1.0f), + device_scale_adjustment(1.0f), + force_enable_zoom(false), + fullscreen_supported(true), + double_tap_to_zoom_enabled(true), + user_gesture_required_for_media_playback(true), + support_deprecated_target_density_dpi(false), + use_legacy_background_size_shorthand_behavior(false), + wide_viewport_quirk(false), + use_wide_viewport(true), + force_zero_layout_height(false), + viewport_meta_layout_size_quirk(false), + viewport_meta_merge_content_quirk(false), + viewport_meta_non_user_scalable_quirk(false), + viewport_meta_zero_values_quirk(false), + clobber_user_agent_initial_scale_quirk(false), + ignore_main_frame_overflow_hidden_quirk(false), + report_screen_size_in_physical_pixels_quirk(false), + record_whole_document(false), +#endif +#if defined(OS_ANDROID) + default_minimum_page_scale_factor(0.25f), + default_maximum_page_scale_factor(5.f) +#elif defined(OS_MACOSX) + default_minimum_page_scale_factor(1.f), + default_maximum_page_scale_factor(3.f) +#else + default_minimum_page_scale_factor(1.f), + default_maximum_page_scale_factor(4.f) +#endif +{ + standard_font_family_map[kCommonScript] = + base::ASCIIToUTF16("Times New Roman"); + fixed_font_family_map[kCommonScript] = base::ASCIIToUTF16("Courier New"); + serif_font_family_map[kCommonScript] = base::ASCIIToUTF16("Times New Roman"); + sans_serif_font_family_map[kCommonScript] = base::ASCIIToUTF16("Arial"); + cursive_font_family_map[kCommonScript] = base::ASCIIToUTF16("Script"); + fantasy_font_family_map[kCommonScript] = base::ASCIIToUTF16("Impact"); + pictograph_font_family_map[kCommonScript] = + base::ASCIIToUTF16("Times New Roman"); +} + +WebPreferences::~WebPreferences() {} + +typedef void (*SetFontFamilyWrapper)(blink::WebSettings*, + const base::string16&, + UScriptCode); + +// If |scriptCode| is a member of a family of "similar" script codes, returns +// the script code in that family that is used by WebKit for font selection +// purposes. For example, USCRIPT_KATAKANA_OR_HIRAGANA and USCRIPT_JAPANESE are +// considered equivalent for the purposes of font selection. WebKit uses the +// script code USCRIPT_KATAKANA_OR_HIRAGANA. So, if |scriptCode| is +// USCRIPT_JAPANESE, the function returns USCRIPT_KATAKANA_OR_HIRAGANA. WebKit +// uses different scripts than the ones in Chrome pref names because the version +// of ICU included on certain ports does not have some of the newer scripts. If +// |scriptCode| is not a member of such a family, returns |scriptCode|. +UScriptCode GetScriptForWebSettings(UScriptCode scriptCode) { + switch (scriptCode) { + case USCRIPT_HIRAGANA: + case USCRIPT_KATAKANA: + case USCRIPT_JAPANESE: + return USCRIPT_KATAKANA_OR_HIRAGANA; + case USCRIPT_KOREAN: + return USCRIPT_HANGUL; + default: + return scriptCode; + } +} + +void SetStandardFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setStandardFontFamily(font, script); +} + +void SetFixedFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setFixedFontFamily(font, script); +} + +void SetSerifFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setSerifFontFamily(font, script); +} + +void SetSansSerifFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setSansSerifFontFamily(font, script); +} + +void SetCursiveFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setCursiveFontFamily(font, script); +} + +void SetFantasyFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setFantasyFontFamily(font, script); +} + +void SetPictographFontFamilyWrapper(blink::WebSettings* settings, + const base::string16& font, + UScriptCode script) { + settings->setPictographFontFamily(font, script); +} + +void ApplyFontsFromMap(const ScriptFontFamilyMap& map, + SetFontFamilyWrapper setter, + blink::WebSettings* settings) { + for (ScriptFontFamilyMap::const_iterator it = map.begin(); it != map.end(); + ++it) { + int32 script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it->first).c_str()); + if (script >= 0 && script < USCRIPT_CODE_LIMIT) { + UScriptCode code = static_cast<UScriptCode>(script); + (*setter)(settings, it->second, GetScriptForWebSettings(code)); + } + } +} + +void UpdateWebPreferencesForTest(WebPreferences* prefs) { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + prefs->allow_universal_access_from_file_urls = true; + prefs->dom_paste_enabled = true; + prefs->javascript_can_access_clipboard = true; + prefs->xslt_enabled = true; + prefs->xss_auditor_enabled = false; +#if defined(OS_MACOSX) + prefs->editing_behavior = EDITING_BEHAVIOR_MAC; +#else + prefs->editing_behavior = EDITING_BEHAVIOR_WIN; +#endif + prefs->application_cache_enabled = true; + prefs->tabs_to_links = false; + prefs->hyperlink_auditing_enabled = false; + prefs->allow_displaying_insecure_content = true; + prefs->allow_running_insecure_content = false; + prefs->disable_reading_from_canvas = false; + prefs->strict_mixed_content_checking = false; + prefs->strict_powerful_feature_restrictions = false; + prefs->webgl_errors_to_console_enabled = false; + base::string16 serif; +#if defined(OS_MACOSX) + prefs->cursive_font_family_map[kCommonScript] = + base::ASCIIToUTF16("Apple Chancery"); + prefs->fantasy_font_family_map[kCommonScript] = base::ASCIIToUTF16("Papyrus"); + serif = base::ASCIIToUTF16("Times"); +#else + prefs->cursive_font_family_map[kCommonScript] = + base::ASCIIToUTF16("Comic Sans MS"); + prefs->fantasy_font_family_map[kCommonScript] = base::ASCIIToUTF16("Impact"); + serif = base::ASCIIToUTF16("times new roman"); +#endif + prefs->serif_font_family_map[kCommonScript] = serif; + prefs->standard_font_family_map[kCommonScript] = serif; + prefs->fixed_font_family_map[kCommonScript] = base::ASCIIToUTF16("Courier"); + prefs->sans_serif_font_family_map[kCommonScript] = + base::ASCIIToUTF16("Helvetica"); + prefs->minimum_logical_font_size = 9; + prefs->asynchronous_spell_checking_enabled = false; + prefs->accelerated_2d_canvas_enabled = false; + command_line.HasSwitch(kEnableAccelerated2DCanvas); + prefs->mock_scrollbars_enabled = false; + prefs->smart_insert_delete_enabled = true; + prefs->minimum_accelerated_2d_canvas_size = 0; +#if defined(OS_ANDROID) + prefs->text_autosizing_enabled = false; +#endif + prefs->viewport_enabled = false; + prefs->default_minimum_page_scale_factor = 1.f; + prefs->default_maximum_page_scale_factor = 4.f; +} + +void ApplySettings(blink::WebView* web_view, bool test_mode) { + WebPreferences prefs; + + if (test_mode) { + UpdateWebPreferencesForTest(&prefs); + } + + blink::WebSettings* settings = web_view->settings(); + ApplyFontsFromMap(prefs.standard_font_family_map, + SetStandardFontFamilyWrapper, settings); + ApplyFontsFromMap(prefs.fixed_font_family_map, SetFixedFontFamilyWrapper, + settings); + ApplyFontsFromMap(prefs.serif_font_family_map, SetSerifFontFamilyWrapper, + settings); + ApplyFontsFromMap(prefs.sans_serif_font_family_map, + SetSansSerifFontFamilyWrapper, settings); + ApplyFontsFromMap(prefs.cursive_font_family_map, SetCursiveFontFamilyWrapper, + settings); + ApplyFontsFromMap(prefs.fantasy_font_family_map, SetFantasyFontFamilyWrapper, + settings); + ApplyFontsFromMap(prefs.pictograph_font_family_map, + SetPictographFontFamilyWrapper, settings); + settings->setDefaultFontSize(prefs.default_font_size); + settings->setDefaultFixedFontSize(prefs.default_fixed_font_size); + settings->setMinimumFontSize(prefs.minimum_font_size); + settings->setMinimumLogicalFontSize(prefs.minimum_logical_font_size); + settings->setDefaultTextEncodingName( + base::ASCIIToUTF16(prefs.default_encoding)); + settings->setJavaScriptEnabled(prefs.javascript_enabled); + settings->setWebSecurityEnabled(prefs.web_security_enabled); + settings->setJavaScriptCanOpenWindowsAutomatically( + prefs.javascript_can_open_windows_automatically); + settings->setLoadsImagesAutomatically(prefs.loads_images_automatically); + settings->setImagesEnabled(prefs.images_enabled); + settings->setPluginsEnabled(prefs.plugins_enabled); + settings->setDOMPasteAllowed(prefs.dom_paste_enabled); + settings->setUsesEncodingDetector(prefs.uses_universal_detector); + settings->setTextAreasAreResizable(prefs.text_areas_are_resizable); + settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows); + settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled); + settings->setJavaScriptCanAccessClipboard( + prefs.javascript_can_access_clipboard); + blink::WebRuntimeFeatures::enableXSLT(prefs.xslt_enabled); + blink::WebRuntimeFeatures::enableSlimmingPaintV2( + prefs.slimming_paint_v2_enabled); + settings->setXSSAuditorEnabled(prefs.xss_auditor_enabled); + settings->setDNSPrefetchingEnabled(prefs.dns_prefetching_enabled); + settings->setLocalStorageEnabled(prefs.local_storage_enabled); + settings->setSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled); + blink::WebRuntimeFeatures::enableDatabase(prefs.databases_enabled); + settings->setOfflineWebApplicationCacheEnabled( + prefs.application_cache_enabled); + settings->setCaretBrowsingEnabled(prefs.caret_browsing_enabled); + settings->setHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled); + settings->setCookieEnabled(prefs.cookie_enabled); + settings->setNavigateOnDragDrop(prefs.navigate_on_drag_drop); + + // By default, allow_universal_access_from_file_urls is set to false and thus + // we mitigate attacks from local HTML files by not granting file:// URLs + // universal access. Only test shell will enable this. + settings->setAllowUniversalAccessFromFileURLs( + prefs.allow_universal_access_from_file_urls); + settings->setAllowFileAccessFromFileURLs( + prefs.allow_file_access_from_file_urls); + + // Enable the web audio API if requested on the command line. + settings->setWebAudioEnabled(prefs.webaudio_enabled); + + // Enable experimental WebGL support if requested on command line + // and support is compiled in. + settings->setExperimentalWebGLEnabled(prefs.experimental_webgl_enabled); + + // Disable GL multisampling if requested on command line. + settings->setOpenGLMultisamplingEnabled(prefs.gl_multisampling_enabled); + + // Enable WebGL errors to the JS console if requested. + settings->setWebGLErrorsToConsoleEnabled( + prefs.webgl_errors_to_console_enabled); + + // Uses the mock theme engine for scrollbars. + settings->setMockScrollbarsEnabled(prefs.mock_scrollbars_enabled); + + // Enable gpu-accelerated 2d canvas if requested on the command line. + settings->setAccelerated2dCanvasEnabled(prefs.accelerated_2d_canvas_enabled); + + settings->setMinimumAccelerated2dCanvasSize( + prefs.minimum_accelerated_2d_canvas_size); + + // Disable antialiasing for 2d canvas if requested on the command line. + settings->setAntialiased2dCanvasEnabled( + !prefs.antialiased_2d_canvas_disabled); + + // Enabled antialiasing of clips for 2d canvas if requested on the command + // line. + settings->setAntialiasedClips2dCanvasEnabled( + prefs.antialiased_clips_2d_canvas_enabled); + + // Set MSAA sample count for 2d canvas if requested on the command line (or + // default value if not). + settings->setAccelerated2dCanvasMSAASampleCount( + prefs.accelerated_2d_canvas_msaa_sample_count); + + settings->setAsynchronousSpellCheckingEnabled( + prefs.asynchronous_spell_checking_enabled); + settings->setUnifiedTextCheckerEnabled(prefs.unified_textchecker_enabled); + + // Tabs to link is not part of the settings. WebCore calls + // ChromeClient::tabsToLinks which is part of the glue code. + web_view->setTabsToLinks(prefs.tabs_to_links); + + settings->setAllowDisplayOfInsecureContent( + prefs.allow_displaying_insecure_content); + settings->setAllowRunningOfInsecureContent( + prefs.allow_running_insecure_content); + settings->setDisableReadingFromCanvas(prefs.disable_reading_from_canvas); + settings->setStrictMixedContentChecking(prefs.strict_mixed_content_checking); + + settings->setStrictlyBlockBlockableMixedContent( + prefs.strictly_block_blockable_mixed_content); + + settings->setStrictMixedContentCheckingForPlugin( + prefs.block_mixed_plugin_content); + + settings->setStrictPowerfulFeatureRestrictions( + prefs.strict_powerful_feature_restrictions); + settings->setPasswordEchoEnabled(prefs.password_echo_enabled); + settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds); + settings->setShouldClearDocumentBackground( + prefs.should_clear_document_background); + settings->setEnableScrollAnimator(prefs.enable_scroll_animator); + + blink::WebRuntimeFeatures::enableTouch(prefs.touch_enabled); + settings->setMaxTouchPoints(prefs.pointer_events_max_touch_points); + settings->setAvailablePointerTypes(prefs.available_pointer_types); + settings->setPrimaryPointerType( + static_cast<blink::WebSettings::PointerType>(prefs.primary_pointer_type)); + settings->setAvailableHoverTypes(prefs.available_hover_types); + settings->setPrimaryHoverType( + static_cast<blink::WebSettings::HoverType>(prefs.primary_hover_type)); + settings->setDeviceSupportsTouch(prefs.device_supports_touch); + settings->setDeviceSupportsMouse(prefs.device_supports_mouse); + settings->setEnableTouchAdjustment(prefs.touch_adjustment_enabled); + settings->setMultiTargetTapNotificationEnabled( + switches::IsLinkDisambiguationPopupEnabled()); + + blink::WebRuntimeFeatures::enableImageColorProfiles( + prefs.image_color_profiles_enabled); + settings->setShouldRespectImageOrientation( + prefs.should_respect_image_orientation); + + settings->setUnsafePluginPastingEnabled(false); + settings->setEditingBehavior( + static_cast<blink::WebSettings::EditingBehavior>(prefs.editing_behavior)); + + settings->setSupportsMultipleWindows(prefs.supports_multiple_windows); + + settings->setInertVisualViewport(prefs.inert_visual_viewport); + + // TODO(bokan): Remove once Blink side is gone. + settings->setInvertViewportScrollOrder(true); + + settings->setViewportEnabled(prefs.viewport_enabled); + settings->setLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale); + settings->setViewportMetaEnabled(prefs.viewport_meta_enabled); + settings->setMainFrameResizesAreOrientationChanges( + prefs.main_frame_resizes_are_orientation_changes); + + settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled); + + settings->setSpatialNavigationEnabled(prefs.spatial_navigation_enabled); + + settings->setSelectionIncludesAltImageText(true); + + settings->setV8CacheOptions( + static_cast<blink::WebSettings::V8CacheOptions>(prefs.v8_cache_options)); + + settings->setImageAnimationPolicy( + static_cast<blink::WebSettings::ImageAnimationPolicy>( + prefs.animation_policy)); + + // Needs to happen before setIgnoreVIewportTagScaleLimits below. + web_view->setDefaultPageScaleLimits(prefs.default_minimum_page_scale_factor, + prefs.default_maximum_page_scale_factor); + +#if defined(OS_ANDROID) + settings->setAllowCustomScrollbarInMainFrame(false); + settings->setTextAutosizingEnabled(prefs.text_autosizing_enabled); + settings->setAccessibilityFontScaleFactor(prefs.font_scale_factor); + settings->setDeviceScaleAdjustment(prefs.device_scale_adjustment); + settings->setFullscreenSupported(prefs.fullscreen_supported); + web_view->setIgnoreViewportTagScaleLimits(prefs.force_enable_zoom); + settings->setAutoZoomFocusedNodeToLegibleScale(true); + settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); + settings->setMediaControlsOverlayPlayButtonEnabled(true); + settings->setMediaPlaybackRequiresUserGesture( + prefs.user_gesture_required_for_media_playback); + settings->setDefaultVideoPosterURL( + base::ASCIIToUTF16(prefs.default_video_poster_url.spec())); + settings->setSupportDeprecatedTargetDensityDPI( + prefs.support_deprecated_target_density_dpi); + settings->setUseLegacyBackgroundSizeShorthandBehavior( + prefs.use_legacy_background_size_shorthand_behavior); + settings->setWideViewportQuirkEnabled(prefs.wide_viewport_quirk); + settings->setUseWideViewport(prefs.use_wide_viewport); + settings->setForceZeroLayoutHeight(prefs.force_zero_layout_height); + settings->setViewportMetaLayoutSizeQuirk( + prefs.viewport_meta_layout_size_quirk); + settings->setViewportMetaMergeContentQuirk( + prefs.viewport_meta_merge_content_quirk); + settings->setViewportMetaNonUserScalableQuirk( + prefs.viewport_meta_non_user_scalable_quirk); + settings->setViewportMetaZeroValuesQuirk( + prefs.viewport_meta_zero_values_quirk); + settings->setClobberUserAgentInitialScaleQuirk( + prefs.clobber_user_agent_initial_scale_quirk); + settings->setIgnoreMainFrameOverflowHiddenQuirk( + prefs.ignore_main_frame_overflow_hidden_quirk); + settings->setReportScreenSizeInPhysicalPixelsQuirk( + prefs.report_screen_size_in_physical_pixels_quirk); + settings->setPreferHiddenVolumeControls(true); + settings->setMainFrameClipsContent(!prefs.record_whole_document); + settings->setShrinksViewportContentToFit(true); + settings->setUseMobileViewportStyle(true); + settings->setAutoplayExperimentMode( + blink::WebString::fromUTF8(prefs.autoplay_experiment_mode)); +#endif + + blink::WebNetworkStateNotifier::setOnLine(prefs.is_online); + blink::WebNetworkStateNotifier::setWebConnection( + NetConnectionTypeToWebConnectionType(prefs.net_info_connection_type), + prefs.net_info_max_bandwidth_mbps); + + settings->setPinchOverlayScrollbarThickness( + prefs.pinch_overlay_scrollbar_thickness); + settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars); + + settings->setShowContextMenuOnMouseUp(prefs.context_menu_on_mouse_up); + +#if defined(OS_MACOSX) + settings->setDoubleTapToZoomEnabled(true); + web_view->setMaximumLegibleScale(prefs.default_maximum_page_scale_factor); +#endif + +#if !defined(OS_ANDROID) && !defined(OS_MACOSX) + // On platforms where the pinch viewport and the layout viewport can + // both show scrollbars, hide pinch scrollbars when we are near minimum + // page scale. (See http://crbug.com/446411 and http://crbug.com/515746.) + settings->setHidePinchScrollbarsNearMinScale(true); +#endif +} + +#if defined(OS_LINUX) +// TODO(rjkroege): Some of this information needs to be plumbed out of +// mus into the html_viewer. Most of this information needs to be +// dynamically adjustable (e.g. if I move a mandoline PlatformWindow from +// a LCD panel to a CRT display on a multiple-monitor system, then mus +// should communicate this to the app as part of having the app rasterize +// itself. See http://crbug.com/540054 +void ApplyFontRendereringSettings() { + blink::WebFontRendering::setHinting(SkPaint::kNormal_Hinting); + blink::WebFontRendering::setAutoHint(false); + blink::WebFontRendering::setUseBitmaps(false); + blink::WebFontRendering::setLCDOrder( + gfx::FontRenderParams::SubpixelRenderingToSkiaLCDOrder( + gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE)); + blink::WebFontRendering::setLCDOrientation( + gfx::FontRenderParams::SubpixelRenderingToSkiaLCDOrientation( + gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE)); + blink::WebFontRendering::setAntiAlias(true); + blink::WebFontRendering::setSubpixelRendering(false); + blink::WebFontRendering::setSubpixelPositioning(false); + blink::WebFontRendering::setDefaultFontSize(0); +} +#else +void ApplyFontRendereringSettings() {} +#endif + +} // namespace + +BlinkSettings::BlinkSettings() + : layout_test_settings_(false), experimental_webgl_enabled_(false) {} + +BlinkSettings::~BlinkSettings() {} + +void BlinkSettings::Init() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + experimental_webgl_enabled_ = !command_line->HasSwitch(kDisableWebGLSwitch); +} + +void BlinkSettings::SetLayoutTestMode() { + layout_test_settings_ = true; +} + +void BlinkSettings::ApplySettingsToWebView(blink::WebView* view) const { + if (layout_test_settings_) + ApplySettings(view, true /* test_mode */); + else + ApplySettings(view, false /* test_mode */); + ApplyFontRendereringSettings(); +} + +} // namespace html_viewer
diff --git a/components/html_viewer/blink_settings.h b/components/html_viewer/blink_settings.h new file mode 100644 index 0000000..0bc15e7 --- /dev/null +++ b/components/html_viewer/blink_settings.h
@@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_HTML_VIEWER_BLINK_SETTINGS_H_ +#define COMPONENTS_HTML_VIEWER_BLINK_SETTINGS_H_ + +#include "base/basictypes.h" + +namespace blink { +class WebView; +} + +namespace html_viewer { + +// BlinkSettings encapsulates the necessary settings needed by the blink +// instance used by this HTMLViewer. +// +// TODO(rjkroege): The methods labeled "interim" are waiting on the a +// future rationaliztion of the code comprising blink::WebSettings, +// content::WebPreferences etc. per http://crbug.com/481108 +// +// TODO(rjkroege): Support configuring preferences via mojo as necessary. +class BlinkSettings { + public: + BlinkSettings(); + ~BlinkSettings(); + + // Additional more time-consuming configuration. + void Init(); + + // Marks this |BlinkSettings| object to setup blink for running layout tests. + void SetLayoutTestMode(); + + // interim code: pushes layout test mode and other interim settings + // into Blink. + void ApplySettingsToWebView(blink::WebView* view) const; + + private: + bool layout_test_settings_; + bool experimental_webgl_enabled_; + + DISALLOW_COPY_AND_ASSIGN(BlinkSettings); +}; + +} // namespace html_viewer + +#endif // COMPONENTS_HTML_VIEWER_BLINK_SETTINGS_H_
diff --git a/components/html_viewer/global_state.cc b/components/html_viewer/global_state.cc index e9c295f..1153c4a0 100644 --- a/components/html_viewer/global_state.cc +++ b/components/html_viewer/global_state.cc
@@ -11,6 +11,7 @@ #include "base/i18n/icu_util.h" #include "base/logging.h" #include "components/html_viewer/blink_platform_impl.h" +#include "components/html_viewer/blink_settings.h" #include "components/html_viewer/media_factory.h" #include "components/scheduler/renderer/renderer_scheduler.h" #include "gin/v8_initializer.h" @@ -64,8 +65,7 @@ did_init_(false), device_pixel_ratio_(1.f), discardable_memory_allocator_(kDesiredMaxMemory), - compositor_thread_("compositor thread") { -} + compositor_thread_("compositor thread") {} GlobalState::~GlobalState() { if (blink_platform_) { @@ -140,6 +140,8 @@ if (command_line->HasSwitch(kDisableEncryptedMedia)) blink::WebRuntimeFeatures::enableEncryptedMedia(false); + blink_settings_.Init(); + base::File pak_file = resource_loader_.ReleaseFile(kResourceResourcesPak); base::File pak_file_2 = pak_file.Duplicate(); ui::ResourceBundle::InitSharedInstanceWithPakFileRegion( @@ -159,6 +161,8 @@ } } +// TODO(rjkroege): These two functions probably do not interoperate correctly +// with MUS. const mojo::GpuInfo* GlobalState::GetGpuInfo() { if (gpu_service_) CHECK(gpu_service_.WaitForIncomingResponse()) <<"Get GPU info failed!";
diff --git a/components/html_viewer/global_state.h b/components/html_viewer/global_state.h index b000782d..4240e44 100644 --- a/components/html_viewer/global_state.h +++ b/components/html_viewer/global_state.h
@@ -8,6 +8,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" +#include "components/html_viewer/blink_settings.h" #include "components/html_viewer/discardable_memory_allocator.h" #include "components/mus/gles2/mojo_gpu_memory_buffer_manager.h" #include "components/mus/gles2/raster_thread_helper.h" @@ -83,6 +84,8 @@ MediaFactory* media_factory() { return media_factory_.get(); } + BlinkSettings* blink_settings() { return &blink_settings_; } + private: // Callback for |gpu_service_|->GetGpuInfo(). void GetGpuInfoCallback(mojo::GpuInfoPtr gpu_info); @@ -120,6 +123,8 @@ mojo::GpuInfoPtr gpu_info_; scoped_ptr<MediaFactory> media_factory_; + BlinkSettings blink_settings_; + #if defined(OS_LINUX) && !defined(OS_ANDROID) skia::RefPtr<font_service::FontLoader> font_loader_; #endif
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc index a6207d2d..809903f 100644 --- a/components/html_viewer/html_frame.cc +++ b/components/html_viewer/html_frame.cc
@@ -581,7 +581,7 @@ html_widget_.reset( delegate_->GetHTMLFactory()->CreateHTMLWidgetRootLocal(&create_params)); } else { - html_widget_.reset(new HTMLWidgetRootRemote); + html_widget_.reset(new HTMLWidgetRootRemote(global_state())); } }
diff --git a/components/html_viewer/html_widget.cc b/components/html_viewer/html_widget.cc index 14c04742..25abfcf 100644 --- a/components/html_viewer/html_widget.cc +++ b/components/html_viewer/html_widget.cc
@@ -5,6 +5,7 @@ #include "components/html_viewer/html_widget.h" #include "base/command_line.h" +#include "components/html_viewer/blink_settings.h" #include "components/html_viewer/global_state.h" #include "components/html_viewer/ime_controller.h" #include "components/html_viewer/stats_collection_controller.h" @@ -21,8 +22,6 @@ namespace html_viewer { namespace { -const char kDisableWebGLSwitch[] = "disable-webgl"; - scoped_ptr<WebLayerTreeViewImpl> CreateWebLayerTreeView( GlobalState* global_state) { return make_scoped_ptr(new WebLayerTreeViewImpl( @@ -54,25 +53,13 @@ web_layer_tree_view->setViewportSize(size_in_pixels); } -void ConfigureSettings(blink::WebSettings* settings) { - settings->setCookieEnabled(true); - settings->setDefaultFixedFontSize(13); - settings->setDefaultFontSize(16); - settings->setLoadsImagesAutomatically(true); - settings->setJavaScriptEnabled(true); - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - settings->setExperimentalWebGLEnabled( - !command_line->HasSwitch(kDisableWebGLSwitch)); -} - } // namespace // HTMLWidgetRootRemote ------------------------------------------------------- -HTMLWidgetRootRemote::HTMLWidgetRootRemote() - : web_view_(blink::WebView::create(this)) { - ConfigureSettings(web_view_->settings()); +HTMLWidgetRootRemote::HTMLWidgetRootRemote(GlobalState* global_state) + : web_view_(blink::WebView::create(nullptr)) { + global_state->blink_settings()->ApplySettingsToWebView(web_view_); } HTMLWidgetRootRemote::~HTMLWidgetRootRemote() {} @@ -117,7 +104,7 @@ UpdateWebViewSizeFromViewSize(view_, web_view_, web_layer_tree_view_impl_.get()); } - ConfigureSettings(web_view_->settings()); + global_state_->blink_settings()->ApplySettingsToWebView(web_view_); } HTMLWidgetRootLocal::~HTMLWidgetRootLocal() {}
diff --git a/components/html_viewer/html_widget.h b/components/html_viewer/html_widget.h index 21f7daa..f7eebbb6 100644 --- a/components/html_viewer/html_widget.h +++ b/components/html_viewer/html_widget.h
@@ -40,7 +40,7 @@ // Used for the root frame when the root frame is remote. class HTMLWidgetRootRemote : public HTMLWidget, public blink::WebViewClient { public: - HTMLWidgetRootRemote(); + explicit HTMLWidgetRootRemote(GlobalState* global_state); ~HTMLWidgetRootRemote() override; private:
diff --git a/components/html_viewer/layout_test_content_handler_impl.cc b/components/html_viewer/layout_test_content_handler_impl.cc index a76f294..7d26e5f0 100644 --- a/components/html_viewer/layout_test_content_handler_impl.cc +++ b/components/html_viewer/layout_test_content_handler_impl.cc
@@ -5,6 +5,8 @@ #include "components/html_viewer/layout_test_content_handler_impl.h" #include "base/bind.h" +#include "components/html_viewer/blink_settings.h" +#include "components/html_viewer/global_state.h" #include "components/html_viewer/html_document_application_delegate.h" #include "components/html_viewer/html_widget.h" #include "components/html_viewer/web_test_delegate_impl.h" @@ -78,6 +80,8 @@ HTMLFrame* LayoutTestContentHandlerImpl::CreateHTMLFrame( HTMLFrame::CreateParams* params) { + params->manager->global_state()->blink_settings()->SetLayoutTestMode(); + // The test harness isn't correctly set-up for iframes yet. So return a normal // HTMLFrame for iframes. if (params->parent || !params->view || params->view->id() != params->id)
diff --git a/components/mus/gles2/command_buffer_driver.cc b/components/mus/gles2/command_buffer_driver.cc index acffd14..aca7d41 100644 --- a/components/mus/gles2/command_buffer_driver.cc +++ b/components/mus/gles2/command_buffer_driver.cc
@@ -44,12 +44,13 @@ } void CommandBufferDriver::Initialize( - mojo::CommandBufferSyncClientPtr sync_client, - mojo::CommandBufferLostContextObserverPtr loss_observer, + mojo::InterfacePtrInfo<mojo::CommandBufferSyncClient> sync_client, + mojo::InterfacePtrInfo<mojo::CommandBufferLostContextObserver> + loss_observer, mojo::ScopedSharedBufferHandle shared_state, mojo::Array<int32_t> attribs) { - sync_client_ = sync_client.Pass(); - loss_observer_ = loss_observer.Pass(); + sync_client_ = mojo::MakeProxy(sync_client.Pass()); + loss_observer_ = mojo::MakeProxy(loss_observer.Pass()); bool success = DoInitialize(shared_state.Pass(), attribs.Pass()); mojo::GpuCapabilitiesPtr capabilities = success ? mojo::GpuCapabilities::From(decoder_->GetCapabilities())
diff --git a/components/mus/gles2/command_buffer_driver.h b/components/mus/gles2/command_buffer_driver.h index 9029d575..460ab5a 100644 --- a/components/mus/gles2/command_buffer_driver.h +++ b/components/mus/gles2/command_buffer_driver.h
@@ -48,10 +48,12 @@ void set_client(scoped_ptr<Client> client) { client_ = client.Pass(); } - void Initialize(mojo::CommandBufferSyncClientPtr sync_client, - mojo::CommandBufferLostContextObserverPtr loss_observer, - mojo::ScopedSharedBufferHandle shared_state, - mojo::Array<int32_t> attribs); + void Initialize( + mojo::InterfacePtrInfo<mojo::CommandBufferSyncClient> sync_client, + mojo::InterfacePtrInfo<mojo::CommandBufferLostContextObserver> + loss_observer, + mojo::ScopedSharedBufferHandle shared_state, + mojo::Array<int32_t> attribs); void SetGetBuffer(int32_t buffer); void Flush(int32_t put_offset); void MakeProgress(int32_t last_get_offset);
diff --git a/components/mus/gles2/command_buffer_impl.cc b/components/mus/gles2/command_buffer_impl.cc index f2ec677..cc05053 100644 --- a/components/mus/gles2/command_buffer_impl.cc +++ b/components/mus/gles2/command_buffer_impl.cc
@@ -62,9 +62,10 @@ driver_task_runner_->PostTask( FROM_HERE, base::Bind(&CommandBufferDriver::Initialize, - base::Unretained(driver_.get()), base::Passed(&sync_client), - base::Passed(&loss_observer), base::Passed(&shared_state), - base::Passed(&attribs))); + base::Unretained(driver_.get()), + base::Passed(sync_client.PassInterface()), + base::Passed(loss_observer.PassInterface()), + base::Passed(&shared_state), base::Passed(&attribs))); } void CommandBufferImpl::SetGetBuffer(int32_t buffer) {
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 1d5dd83..0b07b2bd 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -443,6 +443,14 @@ // http://crbug.com/294468 to look into this. is_credential_protected |= login->type == PasswordForm::TYPE_GENERATED; + // Websites that participate in affiliation-based matching will normally + // have a single authentication system per domain, therefore affiliation + // based matches are desired to be offered on any login form on the site. + // However, for Android credentials, most meta-data attributes are empty, + // so they will have a very low score, hence need to be protected against + // the high-scoring logins saved from the website. + is_credential_protected |= IsValidAndroidFacetURI(login->signon_realm); + if (is_credential_protected) protected_credentials.push_back(login.Pass()); else
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index bf329791..3afd4a3 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -19,6 +19,7 @@ #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" @@ -1168,6 +1169,54 @@ EXPECT_EQ(1u, form_manager()->best_matches().size()); } +// Credentials saved through Android apps should always be shown in the drop- +// down menu, unless there is a better-scoring match with the same username. +TEST_F(PasswordFormManagerTest, AndroidCredentialsAreProtected) { + const char kTestUsername1[] = "test-user@gmail.com"; + const char kTestUsername2[] = "test-other-user@gmail.com"; + const char kTestWebPassword[] = "web-password"; + const char kTestAndroidPassword1[] = "android-password-alpha"; + const char kTestAndroidPassword2[] = "android-password-beta"; + + EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_)); + + // Suppose there is one login saved through the website, and two other coming + // from Android: the first has the same username as the web-based credential, + // so it should be suppressed, but the second has a different username, so it + // should be shown. + ScopedVector<PasswordForm> simulated_results; + simulated_results.push_back(CreateSavedMatch(false)); + simulated_results[0]->username_value = ASCIIToUTF16(kTestUsername1); + simulated_results[0]->password_value = ASCIIToUTF16(kTestWebPassword); + simulated_results.push_back(new PasswordForm); + simulated_results[1]->signon_realm = "android://hash@com.google.android"; + simulated_results[1]->origin = GURL("android://hash@com.google.android/"); + simulated_results[1]->username_value = ASCIIToUTF16(kTestUsername1); + simulated_results[1]->password_value = ASCIIToUTF16(kTestAndroidPassword1); + simulated_results.push_back(new PasswordForm(*simulated_results[1])); + simulated_results[2]->username_value = ASCIIToUTF16(kTestUsername2); + simulated_results[2]->password_value = ASCIIToUTF16(kTestAndroidPassword2); + + ScopedVector<PasswordForm> expected_matches; + expected_matches.push_back(new PasswordForm(*simulated_results[0])); + expected_matches.push_back(new PasswordForm(*simulated_results[2])); + + autofill::PasswordFormFillData fill_data; + EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)) + .WillOnce(SaveArg<0>(&fill_data)); + form_manager()->SimulateFetchMatchingLoginsFromPasswordStore(); + form_manager()->OnGetPasswordStoreResults(simulated_results.Pass()); + + EXPECT_FALSE(fill_data.wait_for_username); + EXPECT_EQ(1u, fill_data.additional_logins.size()); + + std::vector<PasswordForm*> actual_matches; + for (const auto& username_match_pair : form_manager()->best_matches()) + actual_matches.push_back(username_match_pair.second); + EXPECT_THAT(actual_matches, + UnorderedPasswordFormElementsAre(expected_matches.get())); +} + TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) { PasswordForm invalid_action_form(*observed_form()); invalid_action_form.action = GURL("http://");
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi index 0c3fcd6..02716cfd 100644 --- a/components/proximity_auth.gypi +++ b/components/proximity_auth.gypi
@@ -36,8 +36,6 @@ "proximity_auth/ble/fake_wire_message.h", "proximity_auth/ble/pref_names.cc", "proximity_auth/ble/pref_names.h", - "proximity_auth/ble/proximity_auth_ble_system.cc", - "proximity_auth/ble/proximity_auth_ble_system.h", "proximity_auth/bluetooth_connection.cc", "proximity_auth/bluetooth_connection.h", "proximity_auth/bluetooth_connection_finder.cc",
diff --git a/components/proximity_auth/ble/BUILD.gn b/components/proximity_auth/ble/BUILD.gn index d8737eb..3fd1b688 100644 --- a/components/proximity_auth/ble/BUILD.gn +++ b/components/proximity_auth/ble/BUILD.gn
@@ -18,8 +18,6 @@ "fake_wire_message.h", "pref_names.cc", "pref_names.h", - "proximity_auth_ble_system.cc", - "proximity_auth_ble_system.h", "remote_attribute.h", ] @@ -42,7 +40,6 @@ "bluetooth_low_energy_connection_finder_unittest.cc", "bluetooth_low_energy_connection_unittest.cc", "bluetooth_low_energy_device_whitelist_unittest.cc", - "proximity_auth_ble_system_unittest.cc", ] configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_characteristics_finder.cc b/components/proximity_auth/ble/bluetooth_low_energy_characteristics_finder.cc index ef737d3..7e233a7 100644 --- a/components/proximity_auth/ble/bluetooth_low_energy_characteristics_finder.cc +++ b/components/proximity_auth/ble/bluetooth_low_energy_characteristics_finder.cc
@@ -88,11 +88,15 @@ PA_LOG(INFO) << "Scanning remote characteristics."; if (device) { std::vector<BluetoothGattService*> services = device->GetGattServices(); + PA_LOG(INFO) << device->GetAddress() << " has " << services.size() + << " services."; for (const auto& service : services) { if (service->GetUUID() == service_uuid) { // Right service found, now scaning its characteristics. std::vector<device::BluetoothGattCharacteristic*> characteristics = service->GetCharacteristics(); + PA_LOG(INFO) << "Service " << service_uuid.canonical_value() << " has " + << characteristics.size() << " characteristics."; for (const auto& characteristic : characteristics) { HandleCharacteristicUpdate(characteristic); }
diff --git a/components/proximity_auth/ble/proximity_auth_ble_system.cc b/components/proximity_auth/ble/proximity_auth_ble_system.cc deleted file mode 100644 index 652341f..0000000 --- a/components/proximity_auth/ble/proximity_auth_ble_system.cc +++ /dev/null
@@ -1,423 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/proximity_auth/ble/proximity_auth_ble_system.h" - -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/location.h" -#include "base/strings/utf_string_conversions.h" -#include "base/thread_task_runner_handle.h" -#include "base/time/default_tick_clock.h" -#include "components/proximity_auth/ble/bluetooth_low_energy_connection.h" -#include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" -#include "components/proximity_auth/ble/bluetooth_low_energy_device_whitelist.h" -#include "components/proximity_auth/ble/fake_wire_message.h" -#include "components/proximity_auth/bluetooth_throttler_impl.h" -#include "components/proximity_auth/connection.h" -#include "components/proximity_auth/cryptauth/base64url.h" -#include "components/proximity_auth/cryptauth/cryptauth_device_manager.h" -#include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" -#include "components/proximity_auth/logging/logging.h" -#include "components/proximity_auth/proximity_auth_client.h" -#include "components/proximity_auth/remote_device.h" -#include "components/proximity_auth/wire_message.h" -#include "device/bluetooth/bluetooth_device.h" -#include "device/bluetooth/bluetooth_gatt_connection.h" - -namespace proximity_auth { - -namespace { - -// The UUID of the Bluetooth Low Energy service. -const char kSmartLockServiceUUID[] = "b3b7e28e-a000-3e17-bd86-6e97b9e28c11"; - -// Polling interval in seconds. -const int kPollingIntervalSeconds = 5; - -// String received when the remote device's screen is unlocked. -const char kScreenUnlocked[] = "Screen Unlocked"; - -// String received when the remote device's screen is locked. -const char kScreenLocked[] = "Screen Locked"; - -// String send to poll the remote device screen state. -const char kPollScreenState[] = "PollScreenState"; - -// String prefix received with the public key. -const char kPublicKeyMessagePrefix[] = "PublicKey:"; - -// BluetoothLowEnergyConnection parameter, number of attempts to send a write -// request before failing. -const int kMaxNumberOfTries = 2; - -// The time, in seconds, to show a spinner for the user pod immediately after -// the screen is locked. -const int kSpinnerTimeSeconds = 15; - -// Text shown on the user pod when unlock is allowed. -const char kUserPodUnlockText[] = "Click your photo"; - -// Text of tooltip shown on when hovering over the user pod icon when unlock is -// not allowed. -const char kUserPodIconLockedTooltip[] = "Unable to find an unlocked phone."; - -} // namespace - -ProximityAuthBleSystem::ProximityAuthBleSystem( - ScreenlockBridge* screenlock_bridge, - ProximityAuthClient* proximity_auth_client, - PrefService* pref_service) - : screenlock_bridge_(screenlock_bridge), - proximity_auth_client_(proximity_auth_client), - device_whitelist_(new BluetoothLowEnergyDeviceWhitelist(pref_service)), - bluetooth_throttler_(new BluetoothThrottlerImpl( - make_scoped_ptr(new base::DefaultTickClock()))), - device_authenticated_(false), - is_polling_screen_state_(false), - weak_ptr_factory_(this) { - PA_LOG(INFO) << "Starting Proximity Auth over Bluetooth Low Energy."; - screenlock_bridge_->AddObserver(this); -} - -ProximityAuthBleSystem::~ProximityAuthBleSystem() { - PA_LOG(INFO) << "Stopping Proximity over Bluetooth Low Energy."; - screenlock_bridge_->RemoveObserver(this); - if (connection_) - connection_->RemoveObserver(this); -} - -void ProximityAuthBleSystem::RegisterPrefs(PrefRegistrySimple* registry) { - BluetoothLowEnergyDeviceWhitelist::RegisterPrefs(registry); -} - -void ProximityAuthBleSystem::RemoveStaleWhitelistedDevices() { - PA_LOG(INFO) << "Removing stale whitelist devices."; - std::vector<std::string> b64_public_keys = device_whitelist_->GetPublicKeys(); - PA_LOG(INFO) << "There were " << b64_public_keys.size() - << " whitelisted devices."; - - std::vector<cryptauth::ExternalDeviceInfo> unlock_keys = - proximity_auth_client_->GetCryptAuthDeviceManager()->unlock_keys(); - - for (const auto& b64_public_key : b64_public_keys) { - std::string public_key; - if (!Base64UrlDecode(b64_public_key, &public_key)) - continue; - - bool public_key_registered = false; - for (const auto& unlock_key : unlock_keys) { - public_key_registered |= unlock_key.public_key() == public_key; - } - - if (!public_key_registered) { - PA_LOG(INFO) << "Removing device: " << b64_public_key; - device_whitelist_->RemoveDeviceWithPublicKey(b64_public_key); - } - } - b64_public_keys = device_whitelist_->GetPublicKeys(); - PA_LOG(INFO) << "There are " << b64_public_keys.size() - << " whitelisted devices."; -} - -void ProximityAuthBleSystem::OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { - PA_LOG(INFO) << "OnScreenDidLock: " << screen_type; - if (!IsAnyUnlockKeyBLE()) { - PA_LOG(INFO) << "No BLE device registered as unlock key"; - return; - } - - switch (screen_type) { - case ScreenlockBridge::LockHandler::SIGNIN_SCREEN: - connection_finder_.reset(); - break; - case ScreenlockBridge::LockHandler::LOCK_SCREEN: - DCHECK(!connection_finder_); - connection_finder_.reset(CreateConnectionFinder()); - connection_finder_->Find( - base::Bind(&ProximityAuthBleSystem::OnConnectionFound, - weak_ptr_factory_.GetWeakPtr())); - break; - case ScreenlockBridge::LockHandler::OTHER_SCREEN: - connection_finder_.reset(); - break; - } - - // Reset the screen lock UI state to the default state. - is_remote_screen_locked_ = true; - screenlock_ui_state_ = ScreenlockUIState::NO_SCREENLOCK; - last_focused_user_ = screenlock_bridge_->focused_user_id(); - spinner_timer_.Start(FROM_HERE, - base::TimeDelta::FromSeconds(kSpinnerTimeSeconds), this, - &ProximityAuthBleSystem::OnSpinnerTimerFired); - UpdateLockScreenUI(); -} - -ConnectionFinder* ProximityAuthBleSystem::CreateConnectionFinder() { - return new BluetoothLowEnergyConnectionFinder( - RemoteDevice(), kSmartLockServiceUUID, - BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE, - device_whitelist_.get(), bluetooth_throttler_.get(), kMaxNumberOfTries); -} - -void ProximityAuthBleSystem::OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { - PA_LOG(INFO) << "OnScreenDidUnlock: " << screen_type; - - if (connection_) { - // Note: it's important to remove the observer before calling - // |Disconnect()|, otherwise |OnConnectedStatusChanged()| will be called - // from |connection_| and a new instance for |connection_finder_| will be - // created. - connection_->RemoveObserver(this); - connection_->Disconnect(); - device_authenticated_ = false; - } - - connection_.reset(); - connection_finder_.reset(); -} - -void ProximityAuthBleSystem::OnFocusedUserChanged(const std::string& user_id) { - PA_LOG(INFO) << "OnFocusedUserChanged: " << user_id; - // TODO(tengs): We assume that the last focused user is the one with Smart - // Lock enabled. This may not be the case for multiprofile scenarios. - last_focused_user_ = user_id; - UpdateLockScreenUI(); -} - -void ProximityAuthBleSystem::OnMessageReceived(const Connection& connection, - const WireMessage& message) { - PA_LOG(INFO) << "Message with " << message.payload().size() - << " bytes received."; - - // The first message should contain a public key registered with - // CryptAuthDeviceManager to authenticate the device. - if (!device_authenticated_) { - std::string out_public_key; - if (HasUnlockKey(message.payload(), &out_public_key)) { - PA_LOG(INFO) << "Device authenticated. Adding " - << connection_->remote_device().bluetooth_address << ", " - << out_public_key << " to whitelist."; - device_whitelist_->AddOrUpdateDevice( - connection_->remote_device().bluetooth_address, out_public_key); - device_authenticated_ = true; - - // Only start polling the screen state if the device is authenticated. - if (!is_polling_screen_state_) { - is_polling_screen_state_ = true; - StartPollingScreenState(); - } - - } else { - PA_LOG(INFO) << "Key not found. Authentication failed."; - connection_->Disconnect(); - } - return; - } - - if (message.payload() == kScreenUnlocked) { - is_remote_screen_locked_ = false; - spinner_timer_.Stop(); - UpdateLockScreenUI(); - } else if (message.payload() == kScreenLocked) { - is_remote_screen_locked_ = true; - UpdateLockScreenUI(); - } -} - -void ProximityAuthBleSystem::OnAuthAttempted(const std::string& user_id) { - if (user_id != last_focused_user_) { - PA_LOG(ERROR) << "Unexpected user: " << last_focused_user_ - << " != " << user_id; - return; - } - - // Ignore this auth attempt if there is no BLE unlock key. - if (!IsAnyUnlockKeyBLE()) - return; - - // Accept the auth attempt and authorize the screen unlock if the remote - // device is connected and its screen is unlocked. - bool accept_auth_attempt = connection_ && connection_->IsConnected() && - device_authenticated_ && !is_remote_screen_locked_; - proximity_auth_client_->FinalizeUnlock(accept_auth_attempt); -} - -void ProximityAuthBleSystem::OnConnectionFound( - scoped_ptr<Connection> connection) { - PA_LOG(INFO) << "Connection found."; - DCHECK(connection); - - connection_ = connection.Pass(); - connection_->AddObserver(this); -} - -void ProximityAuthBleSystem::OnConnectionStatusChanged( - Connection* connection, - Connection::Status old_status, - Connection::Status new_status) { - PA_LOG(INFO) << "OnConnectionStatusChanged: " << old_status << " -> " - << new_status; - if (old_status == Connection::CONNECTED && - new_status == Connection::DISCONNECTED) { - device_authenticated_ = false; - is_remote_screen_locked_ = true; - StopPollingScreenState(); - UpdateLockScreenUI(); - - // Note: it's not necessary to destroy the |connection_| here, as it's - // already in a DISCONNECTED state. Moreover, destroying it here can cause - // memory corruption, since the instance |connection_| still accesses some - // internal data members after |OnConnectionStatusChanged()| finishes. - connection_->RemoveObserver(this); - - connection_finder_.reset(CreateConnectionFinder()); - connection_finder_->Find( - base::Bind(&ProximityAuthBleSystem::OnConnectionFound, - weak_ptr_factory_.GetWeakPtr())); - } -} - -void ProximityAuthBleSystem::StartPollingScreenState() { - PA_LOG(INFO) << "Polling screen state."; - if (is_polling_screen_state_) { - if (!connection_ || !connection_->IsConnected()) { - PA_LOG(INFO) << "Polling stopped."; - is_polling_screen_state_ = false; - return; - } - // Sends message requesting screen state. - connection_->SendMessage( - make_scoped_ptr(new WireMessage(kPollScreenState))); - - // Schedules the next message in |kPollingIntervalSeconds| s. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&ProximityAuthBleSystem::StartPollingScreenState, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(kPollingIntervalSeconds)); - - PA_LOG(INFO) << "Next poll iteration posted."; - } -} - -void ProximityAuthBleSystem::StopPollingScreenState() { - is_polling_screen_state_ = false; -} - -bool ProximityAuthBleSystem::IsAnyUnlockKeyBLE() { - CryptAuthDeviceManager* device_manager = - proximity_auth_client_->GetCryptAuthDeviceManager(); - if (!device_manager) - return false; - - for (const auto& unlock_key : device_manager->unlock_keys()) { - // TODO(tengs): We currently assume that any device registered as an unlock - // key, but does not have a Bluetooth address, is a BLE device. - if (unlock_key.bluetooth_address().empty()) - return true; - } - - return false; -} - -bool ProximityAuthBleSystem::HasUnlockKey(const std::string& message, - std::string* out_public_key) { - std::string message_prefix(kPublicKeyMessagePrefix); - if (message.substr(0, message_prefix.size()) != message_prefix) - return false; - std::string public_key = message.substr(message_prefix.size()); - if (out_public_key) - (*out_public_key) = public_key; - - std::vector<cryptauth::ExternalDeviceInfo> unlock_keys = - proximity_auth_client_->GetCryptAuthDeviceManager()->unlock_keys(); - - std::string decoded_public_key; - if (!Base64UrlDecode(public_key, &decoded_public_key)) - return false; - - bool unlock_key_registered = false; - for (const auto& unlock_key : unlock_keys) { - unlock_key_registered |= unlock_key.public_key() == decoded_public_key; - } - - RemoveStaleWhitelistedDevices(); - return unlock_key_registered || - device_whitelist_->HasDeviceWithPublicKey(public_key); -} - -void ProximityAuthBleSystem::OnSpinnerTimerFired() { - UpdateLockScreenUI(); -} - -void ProximityAuthBleSystem::UpdateLockScreenUI() { - ScreenlockUIState screenlock_ui_state = ScreenlockUIState::NO_SCREENLOCK; - - // TODO(tengs): We assume that the last focused user is the one with Smart - // Lock enabled. This may not be the case for multiprofile scenarios. - if (last_focused_user_.empty()) - return; - - // Check that the lock screen exists. - ScreenlockBridge::LockHandler* lock_handler = - screenlock_bridge_->lock_handler(); - if (!lock_handler) { - PA_LOG(WARNING) << "No LockHandler"; - return; - } - - // Check the current authentication state of the phone. - if (connection_ && connection_->IsConnected()) { - if (!device_authenticated_ || is_remote_screen_locked_) - screenlock_ui_state = ScreenlockUIState::UNAUTHENTICATED; - else - screenlock_ui_state = ScreenlockUIState::AUTHENTICATED; - } else if (spinner_timer_.IsRunning()) { - screenlock_ui_state = ScreenlockUIState::SPINNER; - } else { - screenlock_ui_state = ScreenlockUIState::UNAUTHENTICATED; - } - - if (screenlock_ui_state == screenlock_ui_state_) - return; - screenlock_ui_state_ = screenlock_ui_state; - - // Customize the user pod for the current UI state. - PA_LOG(INFO) << "Screenlock UI state changed: " - << static_cast<int>(screenlock_ui_state_); - ScreenlockBridge::UserPodCustomIconOptions icon_options; - ScreenlockBridge::LockHandler::AuthType auth_type = - ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; - base::string16 auth_value; - - switch (screenlock_ui_state_) { - case ScreenlockUIState::SPINNER: - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER); - icon_options.SetTooltip(base::UTF8ToUTF16(kUserPodIconLockedTooltip), - false); - break; - case ScreenlockUIState::UNAUTHENTICATED: - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED); - icon_options.SetTooltip(base::UTF8ToUTF16(kUserPodIconLockedTooltip), - false); - break; - case ScreenlockUIState::AUTHENTICATED: - auth_value = base::UTF8ToUTF16(kUserPodUnlockText); - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED); - icon_options.SetTooltip(base::UTF8ToUTF16(kUserPodUnlockText), false); - auth_type = ScreenlockBridge::LockHandler::USER_CLICK; - break; - default: - break; - } - - lock_handler->ShowUserPodCustomIcon(last_focused_user_, icon_options); - lock_handler->SetAuthType(last_focused_user_, auth_type, auth_value); -} - -} // namespace proximity_auth
diff --git a/components/proximity_auth/ble/proximity_auth_ble_system.h b/components/proximity_auth/ble/proximity_auth_ble_system.h deleted file mode 100644 index 2eb1760..0000000 --- a/components/proximity_auth/ble/proximity_auth_ble_system.h +++ /dev/null
@@ -1,155 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_PROXIMITY_AUTH_BLE_PROXIMITY_AUTH_BLE_SYSTEM_H_ -#define COMPONENTS_PROXIMITY_AUTH_BLE_PROXIMITY_AUTH_BLE_SYSTEM_H_ - -#include <map> -#include <string> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "components/proximity_auth/connection_observer.h" -#include "components/proximity_auth/cryptauth/cryptauth_client.h" -#include "components/proximity_auth/screenlock_bridge.h" - -class PrefRegistrySimple; -class PrefService; - -namespace device { -class BluetoothGattConnection; -} - -namespace proximity_auth { - -class BluetoothLowEnergyConnection; -class BluetoothLowEnergyConnectionFinder; -class BluetoothLowEnergyDeviceWhitelist; -class BluetoothThrottler; -class Connection; -class ConnectionFinder; -class ProximityAuthClient; - -// This is the main entry point to start Proximity Auth over Bluetooth Low -// Energy. This is the underlying system for the Smart Lock features. It will -// discover Bluetooth Low Energy phones and unlock the lock screen if the phone -// passes an authorization and authentication protocol. -class ProximityAuthBleSystem : public ScreenlockBridge::Observer, - public ConnectionObserver { - public: - ProximityAuthBleSystem( - ScreenlockBridge* screenlock_bridge, - ProximityAuthClient* proximity_auth_client, - PrefService* pref_service); - ~ProximityAuthBleSystem() override; - - // Registers the prefs used by this class - static void RegisterPrefs(PrefRegistrySimple* registry); - - // ScreenlockBridge::Observer: - void OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; - void OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; - void OnFocusedUserChanged(const std::string& user_id) override; - - // proximity_auth::ConnectionObserver: - void OnConnectionStatusChanged(Connection* connection, - Connection::Status old_status, - Connection::Status new_status) override; - void OnMessageReceived(const Connection& connection, - const WireMessage& message) override; - - // Called by EasyUnlockService when the user clicks their user pod and - // initiates an auth attempt. - void OnAuthAttempted(const std::string& user_id); - - protected: - // Virtual for testing. - virtual ConnectionFinder* CreateConnectionFinder(); - - private: - // Checks if the devices in |device_whitelist_| have their public keys - // registered in CryptAuth, removes the ones that do not. - void RemoveStaleWhitelistedDevices(); - - // Handler for a new connection found event. - void OnConnectionFound(scoped_ptr<Connection> connection); - - // Start (recurrently) polling every |polling_interval_| ms for the screen - // state of the remote device. - void StartPollingScreenState(); - - // Stop polling for screen state of the remote device, if currently active. - void StopPollingScreenState(); - - // Returns true if any unlock key registered with CryptAuth is a BLE device. - bool IsAnyUnlockKeyBLE(); - - // Checks if |message| contains a valid whitelisted public key. If so, returns - // the public key in |out_public_key|. - bool HasUnlockKey(const std::string& message, std::string* out_public_key); - - // Called when |spinner_timer_| is fired to stop showing the spinner on the - // user pod. - void OnSpinnerTimerFired(); - - // Called to update the lock screen's UI for the current authentication state - // with the remote device. - void UpdateLockScreenUI(); - - ScreenlockBridge* screenlock_bridge_; - - // Not owned. Must outlive this object. - ProximityAuthClient* proximity_auth_client_; - - scoped_ptr<ConnectionFinder> connection_finder_; - - scoped_ptr<Connection> connection_; - - scoped_ptr<BluetoothLowEnergyDeviceWhitelist> device_whitelist_; - - scoped_ptr<BluetoothThrottler> bluetooth_throttler_; - - const base::TimeDelta polling_interval_; - - // True if the remote device sent public key contained in |unlock_keyes_| or - // |device_whitelist_|. - bool device_authenticated_; - - // True if |this| instance is currently polling the phone for the phone's - // screenlock state. - bool is_polling_screen_state_; - - // The user id or email of the last focused user on the lock screen. - std::string last_focused_user_; - - // True if the the last status update from the phone reports that the phone's - // screen is locked. If no status update has been received, this value is true - // by default. - bool is_remote_screen_locked_; - - // The timer controlling the time the spinner for the user pod icon is shown - // right after the screen is locked. - base::OneShotTimer spinner_timer_; - - // The different UI states that the lock screen can be in. - enum class ScreenlockUIState { - NO_SCREENLOCK, - SPINNER, - UNAUTHENTICATED, - AUTHENTICATED - }; - ScreenlockUIState screenlock_ui_state_; - - base::WeakPtrFactory<ProximityAuthBleSystem> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProximityAuthBleSystem); -}; - -} // namespace proximity_auth - -#endif // COMPONENTS_PROXIMITY_AUTH_BLE_PROXIMITY_AUTH_BLE_SYSTEM_H_
diff --git a/components/proximity_auth/ble/proximity_auth_ble_system_unittest.cc b/components/proximity_auth/ble/proximity_auth_ble_system_unittest.cc deleted file mode 100644 index 7a4f35b3..0000000 --- a/components/proximity_auth/ble/proximity_auth_ble_system_unittest.cc +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/proximity_auth/ble/proximity_auth_ble_system.h" - -#include "base/bind.h" -#include "base/memory/scoped_ptr.h" -#include "base/prefs/testing_pref_service.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "components/proximity_auth/ble/bluetooth_low_energy_device_whitelist.h" -#include "components/proximity_auth/connection_finder.h" -#include "components/proximity_auth/cryptauth/mock_cryptauth_client.h" -#include "components/proximity_auth/mock_proximity_auth_client.h" -#include "components/proximity_auth/screenlock_bridge.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::_; -using testing::NiceMock; -using testing::Return; - -namespace proximity_auth { - -namespace { - -const char kTestUser[] = "example@gmail.com"; - -class MockConnectionFinder : public ConnectionFinder { - public: - MockConnectionFinder() {} - ~MockConnectionFinder() {} - - MOCK_METHOD1(Find, void(const ConnectionCallback&)); -}; - -class MockLockHandler : public ScreenlockBridge::LockHandler { - public: - MockLockHandler() {} - ~MockLockHandler() {} - - // ScreenlockBridge::LockHandler: - MOCK_METHOD1(ShowBannerMessage, void(const base::string16& message)); - MOCK_METHOD2(ShowUserPodCustomIcon, - void(const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon)); - MOCK_METHOD1(HideUserPodCustomIcon, void(const std::string& user_email)); - MOCK_METHOD0(EnableInput, void()); - MOCK_METHOD3(SetAuthType, - void(const std::string& user_email, - AuthType auth_type, - const base::string16& auth_value)); - MOCK_CONST_METHOD1(GetAuthType, AuthType(const std::string& user_email)); - MOCK_CONST_METHOD0(GetScreenType, ScreenType()); - MOCK_METHOD1(Unlock, void(const std::string& user_email)); - MOCK_METHOD3(AttemptEasySignin, - void(const std::string& user_email, - const std::string& secret, - const std::string& key_label)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockLockHandler); -}; - -} // namespace - -class ProximityAuthBleSystemTestable : public ProximityAuthBleSystem { - public: - ProximityAuthBleSystemTestable( - ScreenlockBridge* screenlock_bridge, - ProximityAuthClient* proximity_auth_client, - PrefService* pref_service) - : ProximityAuthBleSystem(screenlock_bridge, - proximity_auth_client, - pref_service) {} - - ConnectionFinder* CreateConnectionFinder() override { - return new NiceMock<MockConnectionFinder>(); - } -}; - -class ProximityAuthBleSystemTest : public testing::Test { - protected: - ProximityAuthBleSystemTest() - : task_runner_(new base::TestMockTimeTaskRunner), - runner_handle_(task_runner_) {} - - void SetUp() override { - BluetoothLowEnergyDeviceWhitelist::RegisterPrefs(pref_service_.registry()); - - proximity_auth_system_.reset(new ProximityAuthBleSystemTestable( - ScreenlockBridge::Get(), &proximity_auth_client_, &pref_service_)); - - ON_CALL(proximity_auth_client_, GetAuthenticatedUsername()) - .WillByDefault(Return(kTestUser)); - } - - // Injects the thread's TaskRunner for testing. - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle runner_handle_; - - NiceMock<MockProximityAuthClient> proximity_auth_client_; - TestingPrefServiceSimple pref_service_; - scoped_ptr<ProximityAuthBleSystem> proximity_auth_system_; - - NiceMock<MockLockHandler> lock_handler_; -}; - -TEST_F(ProximityAuthBleSystemTest, LockAndUnlock_LockScreen) { - // Lock the screen. - ON_CALL(lock_handler_, GetScreenType()) - .WillByDefault(Return(ScreenlockBridge::LockHandler::LOCK_SCREEN)); - ScreenlockBridge::Get()->SetLockHandler(&lock_handler_); - - // Unlock the screen. - ScreenlockBridge::Get()->SetLockHandler(nullptr); -} - -TEST_F(ProximityAuthBleSystemTest, LockAndUnlock_SigninScreen) { - // Show the sign-in screen. - ON_CALL(lock_handler_, GetScreenType()) - .WillByDefault(Return(ScreenlockBridge::LockHandler::SIGNIN_SCREEN)); - ScreenlockBridge::Get()->SetLockHandler(&lock_handler_); - - // Sign-in. - ScreenlockBridge::Get()->SetLockHandler(nullptr); -} - -TEST_F(ProximityAuthBleSystemTest, LockAndUnlock_OtherScreen) { - // Show the screen. - ON_CALL(lock_handler_, GetScreenType()) - .WillByDefault(Return(ScreenlockBridge::LockHandler::OTHER_SCREEN)); - ScreenlockBridge::Get()->SetLockHandler(&lock_handler_); - - // Hide the screen. - ScreenlockBridge::Get()->SetLockHandler(nullptr); -} - -} // namespace proximity_auth
diff --git a/components/proximity_auth/remote_device_life_cycle_impl.cc b/components/proximity_auth/remote_device_life_cycle_impl.cc index d7d5508..edb1f41 100644 --- a/components/proximity_auth/remote_device_life_cycle_impl.cc +++ b/components/proximity_auth/remote_device_life_cycle_impl.cc
@@ -51,7 +51,8 @@ RemoteDeviceLifeCycleImpl::~RemoteDeviceLifeCycleImpl() {} void RemoteDeviceLifeCycleImpl::Start() { - PA_LOG(INFO) << "Life cycle started."; + PA_LOG(INFO) << "Life cycle for " << remote_device_.bluetooth_address + << " started."; DCHECK(state_ == RemoteDeviceLifeCycle::State::STOPPED); FindConnection(); }
diff --git a/components/resources/OWNERS b/components/resources/OWNERS index 7d73d57..3b3d0757 100644 --- a/components/resources/OWNERS +++ b/components/resources/OWNERS
@@ -1,10 +1,10 @@ per-file autofill_scaled_resources.grdp=estade@chromium.org -per-file crash_resources.grdp=cpu@chromium.org -per-file crash_resources.grdp=jochen@chromium.org -per-file crash_resources.grdp=mark@chromium.org -per-file crash_resources.grdp=rsesek@chromium.org -per-file crash_resources.grdp=scottmg@chromium.org -per-file crash_resources.grdp=thestig@chromium.org +per-file crash_*=cpu@chromium.org +per-file crash_*=jochen@chromium.org +per-file crash_*=mark@chromium.org +per-file crash_*=rsesek@chromium.org +per-file crash_*=scottmg@chromium.org +per-file crash_*=thestig@chromium.org per-file data_reduction_proxy*=bengr@chromium.org per-file data_reduction_proxy*=sclittle@chromium.org per-file data_reduction_proxy*=megjablon@chromium.org
diff --git a/components/resources/components_scaled_resources.grd b/components/resources/components_scaled_resources.grd index fcb9a36..f92a349c 100644 --- a/components/resources/components_scaled_resources.grd +++ b/components/resources/components_scaled_resources.grd
@@ -13,6 +13,7 @@ <release seq="1"> <structures fallback_to_low_resolution="true"> <part file="autofill_scaled_resources.grdp" /> + <part file="crash_scaled_resources.grdp" /> <part file="omnibox_scaled_resources.grdp" /> </structures> </release>
diff --git a/components/resources/crash_scaled_resources.grdp b/components/resources/crash_scaled_resources.grdp new file mode 100644 index 0000000..25ddde1 --- /dev/null +++ b/components/resources/crash_scaled_resources.grdp
@@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit-part> + <structure type="chrome_scaled_image" name="IDR_CRASH_SAD_FAVICON" file="crash/favicon_sad_tab.png" /> +</grit-part>
diff --git a/chrome/app/theme/default_100_percent/common/favicon_sad_tab.png b/components/resources/default_100_percent/crash/favicon_sad_tab.png similarity index 100% rename from chrome/app/theme/default_100_percent/common/favicon_sad_tab.png rename to components/resources/default_100_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_sad_tab.png b/components/resources/default_200_percent/crash/favicon_sad_tab.png similarity index 100% rename from chrome/app/theme/default_200_percent/common/favicon_sad_tab.png rename to components/resources/default_200_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/chrome/app/theme/default_300_percent/common/favicon_sad_tab.png b/components/resources/default_300_percent/crash/favicon_sad_tab.png similarity index 100% rename from chrome/app/theme/default_300_percent/common/favicon_sad_tab.png rename to components/resources/default_300_percent/crash/favicon_sad_tab.png Binary files differ
diff --git a/components/resources/material_100_percent/omnibox/omnibox_extension_app.png b/components/resources/material_100_percent/omnibox/omnibox_extension_app.png index 0ac642c..15e67fdc 100644 --- a/components/resources/material_100_percent/omnibox/omnibox_extension_app.png +++ b/components/resources/material_100_percent/omnibox/omnibox_extension_app.png Binary files differ
diff --git a/components/resources/material_100_percent/omnibox/omnibox_http.png b/components/resources/material_100_percent/omnibox/omnibox_http.png index 6588aef..02e4b58 100644 --- a/components/resources/material_100_percent/omnibox/omnibox_http.png +++ b/components/resources/material_100_percent/omnibox/omnibox_http.png Binary files differ
diff --git a/components/resources/material_100_percent/omnibox/omnibox_search.png b/components/resources/material_100_percent/omnibox/omnibox_search.png index af25879a..06595a3 100644 --- a/components/resources/material_100_percent/omnibox/omnibox_search.png +++ b/components/resources/material_100_percent/omnibox/omnibox_search.png Binary files differ
diff --git a/components/resources/material_200_percent/omnibox/omnibox_extension_app.png b/components/resources/material_200_percent/omnibox/omnibox_extension_app.png index 865be93..0a5ff08c 100644 --- a/components/resources/material_200_percent/omnibox/omnibox_extension_app.png +++ b/components/resources/material_200_percent/omnibox/omnibox_extension_app.png Binary files differ
diff --git a/components/resources/material_200_percent/omnibox/omnibox_http.png b/components/resources/material_200_percent/omnibox/omnibox_http.png index d6e9219..7cb45c5 100644 --- a/components/resources/material_200_percent/omnibox/omnibox_http.png +++ b/components/resources/material_200_percent/omnibox/omnibox_http.png Binary files differ
diff --git a/components/resources/material_200_percent/omnibox/omnibox_search.png b/components/resources/material_200_percent/omnibox/omnibox_search.png index 62ab423..9e1bebe4 100644 --- a/components/resources/material_200_percent/omnibox/omnibox_search.png +++ b/components/resources/material_200_percent/omnibox/omnibox_search.png Binary files differ
diff --git a/components/sync_bookmarks.gypi b/components/sync_bookmarks.gypi new file mode 100644 index 0000000..a599993 --- /dev/null +++ b/components/sync_bookmarks.gypi
@@ -0,0 +1,35 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + # GN version: //components/sync_bookmarks + 'target_name': 'sync_bookmarks', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../sync/sync.gyp:sync', + '../ui/gfx/gfx.gyp:gfx', + 'bookmarks_browser', + 'favicon_core', + 'history_core_browser', + 'sync_driver', + 'undo_component', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + # Note: file list duplicated in GN build. + 'sync_bookmarks/bookmark_change_processor.cc', + 'sync_bookmarks/bookmark_change_processor.h', + 'sync_bookmarks/bookmark_data_type_controller.cc', + 'sync_bookmarks/bookmark_data_type_controller.h', + 'sync_bookmarks/bookmark_model_associator.cc', + 'sync_bookmarks/bookmark_model_associator.h', + ], + }, + ], +}
diff --git a/components/sync_bookmarks/BUILD.gn b/components/sync_bookmarks/BUILD.gn new file mode 100644 index 0000000..faa6123 --- /dev/null +++ b/components/sync_bookmarks/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") + +source_set("sync_bookmarks") { + sources = [ + "bookmark_change_processor.cc", + "bookmark_change_processor.h", + "bookmark_data_type_controller.cc", + "bookmark_data_type_controller.h", + "bookmark_model_associator.cc", + "bookmark_model_associator.h", + ] + + deps = [ + "//base", + "//components/bookmarks/browser", + "//components/favicon/core", + "//components/history/core/browser", + "//components/sync_driver", + "//components/undo", + "//sync", + "//ui/gfx", + ] +}
diff --git a/components/sync_bookmarks/DEPS b/components/sync_bookmarks/DEPS new file mode 100644 index 0000000..9b3e0d6 --- /dev/null +++ b/components/sync_bookmarks/DEPS
@@ -0,0 +1,9 @@ +include_rules = [ + "+components/bookmarks/browser", + "+components/favicon/core", + "+components/history/core/browser", + "+components/sync_driver", + "+components/undo", + "+sync", + "+ui/gfx", +]
diff --git a/components/sync_bookmarks/OWNERS b/components/sync_bookmarks/OWNERS new file mode 100644 index 0000000..3aba9797 --- /dev/null +++ b/components/sync_bookmarks/OWNERS
@@ -0,0 +1,3 @@ +pavely@chromium.org +stanisc@chromium.org +zea@chromium.org
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/components/sync_bookmarks/bookmark_change_processor.cc similarity index 95% rename from chrome/browser/sync/glue/bookmark_change_processor.cc rename to components/sync_bookmarks/bookmark_change_processor.cc index d612240..dd10e633 100644 --- a/chrome/browser/sync/glue/bookmark_change_processor.cc +++ b/components/sync_bookmarks/bookmark_change_processor.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/bookmark_change_processor.h" +#include "components/sync_bookmarks/bookmark_change_processor.h" #include <map> #include <stack> @@ -13,19 +13,14 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/bookmarks/bookmark_model_factory.h" -#include "chrome/browser/favicon/favicon_service_factory.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/sync/profile_sync_service.h" -#include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "components/bookmarks/browser/bookmark_client.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/favicon/core/favicon_service.h" #include "components/history/core/browser/history_service.h" +#include "components/sync_driver/sync_client.h" #include "components/undo/bookmark_undo_service.h" #include "components/undo/bookmark_undo_utils.h" -#include "content/public/browser/browser_thread.h" #include "sync/internal_api/public/change_record.h" #include "sync/internal_api/public/read_node.h" #include "sync/internal_api/public/write_node.h" @@ -37,7 +32,6 @@ using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; -using content::BrowserThread; using syncer::ChangeRecord; using syncer::ChangeRecordList; @@ -46,16 +40,15 @@ static const char kMobileBookmarksTag[] = "synced_bookmarks"; BookmarkChangeProcessor::BookmarkChangeProcessor( - Profile* profile, + sync_driver::SyncClient* sync_client, BookmarkModelAssociator* model_associator, sync_driver::DataTypeErrorHandler* error_handler) : sync_driver::ChangeProcessor(error_handler), bookmark_model_(NULL), - profile_(profile), + sync_client_(sync_client), model_associator_(model_associator) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(model_associator); - DCHECK(profile); + DCHECK(sync_client); DCHECK(error_handler); } @@ -65,9 +58,9 @@ } void BookmarkChangeProcessor::StartImpl() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!bookmark_model_); - bookmark_model_ = BookmarkModelFactory::GetForProfile(profile_); + bookmark_model_ = sync_client_->GetBookmarkModel(); DCHECK(bookmark_model_->loaded()); bookmark_model_->AddObserver(this); } @@ -554,7 +547,7 @@ const syncer::BaseTransaction* trans, int64 model_version, const syncer::ImmutableChangeRecordList& changes) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); // A note about ordering. Sync backend is responsible for ordering the change // records in the following order: // @@ -580,7 +573,7 @@ // Changes made to the bookmark model due to sync should not be undoable. ScopedSuspendBookmarkUndo suspend_undo( - BookmarkUndoServiceFactory::GetForProfileIfExists(profile_)); + sync_client_->GetBookmarkUndoServiceIfExists()); // Notify UI intensive observers of BookmarkModel that we are about to make // potentially significant changes to it, so the updates may be batched. For @@ -698,7 +691,7 @@ if (dst) { DCHECK(it->action == ChangeRecord::ACTION_UPDATE) << "ACTION_UPDATE should be seen if and only if the node is known."; - UpdateBookmarkWithSyncData(src, model, dst, profile_); + UpdateBookmarkWithSyncData(src, model, dst, sync_client_); // Move all modified entries to the right. We'll fix it later. model->Move(dst, parent, parent->child_count()); @@ -706,10 +699,7 @@ DCHECK(it->action == ChangeRecord::ACTION_ADD) << "ACTION_ADD should be seen if and only if the node is unknown."; - dst = CreateBookmarkNode(&src, - parent, - model, - profile_, + dst = CreateBookmarkNode(&src, parent, model, sync_client_, parent->child_count()); if (!dst) { // We ignore bookmarks we can't add. Chances are this is caused by @@ -766,7 +756,7 @@ const syncer::BaseNode& sync_node, BookmarkModel* model, const BookmarkNode* node, - Profile* profile) { + sync_driver::SyncClient* sync_client) { DCHECK_EQ(sync_node.GetIsFolder(), node->is_folder()); const sync_pb::BookmarkSpecifics& specifics = sync_node.GetBookmarkSpecifics(); @@ -778,7 +768,7 @@ node, base::Time::FromInternalValue(specifics.creation_time_us())); } - SetBookmarkFavicon(&sync_node, node, model, profile); + SetBookmarkFavicon(&sync_node, node, model, sync_client); model->SetNodeMetaInfoMap(node, *GetBookmarkMetaInfo(&sync_node)); } @@ -802,11 +792,11 @@ const syncer::BaseNode* sync_node, const BookmarkNode* parent, BookmarkModel* model, - Profile* profile, + sync_driver::SyncClient* sync_client, int index) { return CreateBookmarkNode(base::UTF8ToUTF16(sync_node->GetTitle()), GURL(sync_node->GetBookmarkSpecifics().url()), - sync_node, parent, model, profile, index); + sync_node, parent, model, sync_client, index); } // static @@ -818,7 +808,7 @@ const syncer::BaseNode* sync_node, const BookmarkNode* parent, BookmarkModel* model, - Profile* profile, + sync_driver::SyncClient* sync_client, int index) { DCHECK(parent); @@ -837,7 +827,7 @@ parent, index, title, url, create_time, GetBookmarkMetaInfo(sync_node).get()); if (node) - SetBookmarkFavicon(sync_node, node, model, profile); + SetBookmarkFavicon(sync_node, node, model, sync_client); } return node; @@ -849,7 +839,7 @@ const syncer::BaseNode* sync_node, const BookmarkNode* bookmark_node, BookmarkModel* bookmark_model, - Profile* profile) { + sync_driver::SyncClient* sync_client) { const sync_pb::BookmarkSpecifics& specifics = sync_node->GetBookmarkSpecifics(); const std::string& icon_bytes_str = specifics.favicon(); @@ -867,7 +857,7 @@ if (icon_url.is_empty()) icon_url = bookmark_node->url(); - ApplyBookmarkFavicon(bookmark_node, profile, icon_url, icon_bytes); + ApplyBookmarkFavicon(bookmark_node, sync_client, icon_url, icon_bytes); return true; } @@ -938,14 +928,11 @@ // static void BookmarkChangeProcessor::ApplyBookmarkFavicon( const BookmarkNode* bookmark_node, - Profile* profile, + sync_driver::SyncClient* sync_client, const GURL& icon_url, const scoped_refptr<base::RefCountedMemory>& bitmap_data) { - history::HistoryService* history = HistoryServiceFactory::GetForProfile( - profile, ServiceAccessType::EXPLICIT_ACCESS); - favicon::FaviconService* favicon_service = - FaviconServiceFactory::GetForProfile(profile, - ServiceAccessType::EXPLICIT_ACCESS); + history::HistoryService* history = sync_client->GetHistoryService(); + favicon::FaviconService* favicon_service = sync_client->GetFaviconService(); history->AddPageNoVisitForBookmark(bookmark_node->url(), bookmark_node->GetTitle());
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.h b/components/sync_bookmarks/bookmark_change_processor.h similarity index 93% rename from chrome/browser/sync/glue/bookmark_change_processor.h rename to components/sync_bookmarks/bookmark_change_processor.h index 9c69cc5..b8d25fe 100644 --- a/chrome/browser/sync/glue/bookmark_change_processor.h +++ b/components/sync_bookmarks/bookmark_change_processor.h
@@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_CHANGE_PROCESSOR_H_ -#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_CHANGE_PROCESSOR_H_ +#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_ +#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_ #include <vector> #include "base/compiler_specific.h" -#include "chrome/browser/sync/glue/bookmark_model_associator.h" +#include "base/threading/thread_checker.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_node.h" +#include "components/sync_bookmarks/bookmark_model_associator.h" #include "components/sync_driver/change_processor.h" #include "components/sync_driver/data_type_error_handler.h" @@ -25,6 +26,10 @@ class WriteTransaction; } // namespace syncer +namespace sync_driver { +class SyncClient; +} + namespace browser_sync { // This class is responsible for taking changes from the BookmarkModel @@ -34,7 +39,7 @@ class BookmarkChangeProcessor : public bookmarks::BookmarkModelObserver, public sync_driver::ChangeProcessor { public: - BookmarkChangeProcessor(Profile* profile, + BookmarkChangeProcessor(sync_driver::SyncClient* sync_client, BookmarkModelAssociator* model_associator, sync_driver::DataTypeErrorHandler* error_handler); ~BookmarkChangeProcessor() override; @@ -89,7 +94,7 @@ static void UpdateBookmarkWithSyncData(const syncer::BaseNode& sync_node, bookmarks::BookmarkModel* model, const bookmarks::BookmarkNode* node, - Profile* profile); + sync_driver::SyncClient* sync_client); // Creates a bookmark node under the given parent node from the given sync // node. Returns the newly created node. The created node is placed at the @@ -98,7 +103,7 @@ const syncer::BaseNode* sync_node, const bookmarks::BookmarkNode* parent, bookmarks::BookmarkModel* model, - Profile* profile, + sync_driver::SyncClient* sync_client, int index); // Overload of CreateBookmarkNode function above that helps to avoid @@ -109,7 +114,7 @@ const syncer::BaseNode* sync_node, const bookmarks::BookmarkNode* parent, bookmarks::BookmarkModel* model, - Profile* profile, + sync_driver::SyncClient* sync_client, int index); // Sets the favicon of the given bookmark node from the given sync node. @@ -119,14 +124,14 @@ static bool SetBookmarkFavicon(const syncer::BaseNode* sync_node, const bookmarks::BookmarkNode* bookmark_node, bookmarks::BookmarkModel* model, - Profile* profile); + sync_driver::SyncClient* sync_client); // Applies the 1x favicon |bitmap_data| and |icon_url| to |bookmark_node|. // |profile| is the profile that contains the HistoryService and BookmarkModel // for the bookmark in question. static void ApplyBookmarkFavicon( const bookmarks::BookmarkNode* bookmark_node, - Profile* profile, + sync_driver::SyncClient* sync_client, const GURL& icon_url, const scoped_refptr<base::RefCountedMemory>& bitmap_data); @@ -233,11 +238,13 @@ // Returns false if |node| should not be synced. bool CanSyncNode(const bookmarks::BookmarkNode* node); + base::ThreadChecker thread_checker_; + // The bookmark model we are processing changes from. Non-NULL when // |running_| is true. bookmarks::BookmarkModel* bookmark_model_; - Profile* profile_; + sync_driver::SyncClient* sync_client_; // The two models should be associated according to this ModelAssociator. BookmarkModelAssociator* model_associator_; @@ -247,4 +254,4 @@ } // namespace browser_sync -#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_CHANGE_PROCESSOR_H_ +#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.cc b/components/sync_bookmarks/bookmark_data_type_controller.cc similarity index 97% rename from chrome/browser/sync/glue/bookmark_data_type_controller.cc rename to components/sync_bookmarks/bookmark_data_type_controller.cc index 99a8073..85e71fa 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller.cc +++ b/components/sync_bookmarks/bookmark_data_type_controller.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" +#include "components/sync_bookmarks/bookmark_data_type_controller.h" #include "base/metrics/histogram.h" #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.h b/components/sync_bookmarks/bookmark_data_type_controller.h similarity index 90% rename from chrome/browser/sync/glue/bookmark_data_type_controller.h rename to components/sync_bookmarks/bookmark_data_type_controller.h index 30d8cde0..b7cb7b3b 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller.h +++ b/components/sync_bookmarks/bookmark_data_type_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_DATA_TYPE_CONTROLLER_H__ -#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_DATA_TYPE_CONTROLLER_H__ +#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_DATA_TYPE_CONTROLLER_H__ +#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_DATA_TYPE_CONTROLLER_H__ #include <string> @@ -61,4 +61,4 @@ } // namespace browser_sync -#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_DATA_TYPE_CONTROLLER_H__ +#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_DATA_TYPE_CONTROLLER_H__
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/components/sync_bookmarks/bookmark_model_associator.cc similarity index 97% rename from chrome/browser/sync/glue/bookmark_model_associator.cc rename to components/sync_bookmarks/bookmark_model_associator.cc index 5bb4f9a..27b5824a 100644 --- a/chrome/browser/sync/glue/bookmark_model_associator.cc +++ b/components/sync_bookmarks/bookmark_model_associator.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/bookmark_model_associator.h" +#include "components/sync_bookmarks/bookmark_model_associator.h" #include "base/bind.h" #include "base/command_line.h" @@ -17,13 +17,12 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/thread_task_runner_handle.h" -#include "chrome/browser/sync/glue/bookmark_change_processor.h" -#include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "components/bookmarks/browser/bookmark_client.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/sync_bookmarks/bookmark_change_processor.h" +#include "components/sync_driver/sync_client.h" #include "components/undo/bookmark_undo_service.h" #include "components/undo/bookmark_undo_utils.h" -#include "content/public/browser/browser_thread.h" #include "sync/api/sync_error.h" #include "sync/api/sync_merge_result.h" #include "sync/internal_api/public/delete_journal.h" @@ -39,7 +38,6 @@ using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; -using content::BrowserThread; namespace browser_sync { @@ -353,29 +351,28 @@ BookmarkModelAssociator::BookmarkModelAssociator( BookmarkModel* bookmark_model, - Profile* profile, + sync_driver::SyncClient* sync_client, syncer::UserShare* user_share, sync_driver::DataTypeErrorHandler* unrecoverable_error_handler, bool expect_mobile_bookmarks_folder) : bookmark_model_(bookmark_model), - profile_(profile), + sync_client_(sync_client), user_share_(user_share), unrecoverable_error_handler_(unrecoverable_error_handler), expect_mobile_bookmarks_folder_(expect_mobile_bookmarks_folder), optimistic_association_enabled_(IsOptimisticAssociationEnabled()), weak_factory_(this) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(bookmark_model_); DCHECK(user_share_); DCHECK(unrecoverable_error_handler_); } BookmarkModelAssociator::~BookmarkModelAssociator() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); } void BookmarkModelAssociator::UpdatePermanentNodeVisibility() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(bookmark_model_->loaded()); BookmarkNode::Type bookmark_node_types[] = { @@ -427,7 +424,7 @@ void BookmarkModelAssociator::AddAssociation(const BookmarkNode* node, int64 sync_id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); int64 node_id = node->id(); DCHECK_NE(sync_id, syncer::kInvalidId); DCHECK(id_map_.find(node_id) == id_map_.end()); @@ -454,7 +451,7 @@ } void BookmarkModelAssociator::Disassociate(int64 sync_id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(thread_checker_.CalledOnValidThread()); SyncIdToBookmarkNodeMap::iterator iter = id_map_inverse_.find(sync_id); if (iter == id_map_inverse_.end()) return; @@ -519,7 +516,7 @@ // Since any changes to the bookmark model made here are not user initiated, // these change should not be undoable and so suspend the undo tracking. ScopedSuspendBookmarkUndo suspend_undo( - BookmarkUndoServiceFactory::GetForProfileIfExists(profile_)); + sync_client_->GetBookmarkUndoServiceIfExists()); Context context(local_merge_result, syncer_merge_result); @@ -756,7 +753,7 @@ // nothing has changed. // TODO(sync): Only modify the bookmark model if necessary. BookmarkChangeProcessor::UpdateBookmarkWithSyncData( - sync_child_node, bookmark_model_, child_node, profile_); + sync_child_node, bookmark_model_, child_node, sync_client_); bookmark_model_->Move(child_node, parent_node, index); context->IncrementLocalItemsModified(); } else { @@ -951,7 +948,7 @@ base::string16 bookmark_title = base::UTF8ToUTF16(sync_title); const BookmarkNode* child_node = BookmarkChangeProcessor::CreateBookmarkNode( bookmark_title, url, sync_child_node, parent_node, bookmark_model_, - profile_, bookmark_index); + sync_client_, bookmark_index); if (!child_node) { *error = unrecoverable_error_handler_->CreateAndUploadError( FROM_HERE, "Failed to create bookmark node with title " + sync_title +
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.h b/components/sync_bookmarks/bookmark_model_associator.h similarity index 96% rename from chrome/browser/sync/glue/bookmark_model_associator.h rename to components/sync_bookmarks/bookmark_model_associator.h index 33d08c9..9075a1e 100644 --- a/chrome/browser/sync/glue/bookmark_model_associator.h +++ b/components/sync_bookmarks/bookmark_model_associator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ -#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ +#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_ASSOCIATOR_H_ +#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_ASSOCIATOR_H_ #include <map> #include <set> @@ -15,11 +15,11 @@ #include "base/compiler_specific.h" #include "base/hash.h" #include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" #include "components/sync_driver/data_type_error_handler.h" #include "components/sync_driver/model_associator.h" #include "sync/internal_api/public/util/unrecoverable_error_handler.h" -class Profile; class GURL; namespace bookmarks { @@ -34,6 +34,10 @@ class WriteTransaction; } +namespace sync_driver { +class SyncClient; +} + namespace browser_sync { // Contains all model association related logic: @@ -50,7 +54,7 @@ // Should be set to true only by mobile clients. BookmarkModelAssociator( bookmarks::BookmarkModel* bookmark_model, - Profile* profile_, + sync_driver::SyncClient* sync_client, syncer::UserShare* user_share, sync_driver::DataTypeErrorHandler* unrecoverable_error_handler, bool expect_mobile_bookmarks_folder); @@ -298,8 +302,9 @@ // the native model has a newer transaction verison. syncer::SyncError CheckModelSyncState(Context* context) const; + base::ThreadChecker thread_checker_; bookmarks::BookmarkModel* bookmark_model_; - Profile* profile_; + sync_driver::SyncClient* sync_client_; syncer::UserShare* user_share_; sync_driver::DataTypeErrorHandler* unrecoverable_error_handler_; const bool expect_mobile_bookmarks_folder_; @@ -320,4 +325,4 @@ } // namespace browser_sync -#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_ASSOCIATOR_H_ +#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_ASSOCIATOR_H_
diff --git a/components/sync_driver.gypi b/components/sync_driver.gypi index a442864..40a25d12 100644 --- a/components/sync_driver.gypi +++ b/components/sync_driver.gypi
@@ -68,6 +68,8 @@ 'sync_driver/generic_change_processor_factory.h', 'sync_driver/glue/browser_thread_model_worker.cc', 'sync_driver/glue/browser_thread_model_worker.h', + 'sync_driver/glue/chrome_report_unrecoverable_error.cc', + 'sync_driver/glue/chrome_report_unrecoverable_error.h', 'sync_driver/glue/history_model_worker.cc', 'sync_driver/glue/history_model_worker.h', 'sync_driver/glue/synced_session.cc', @@ -87,6 +89,8 @@ 'sync_driver/model_associator.h', 'sync_driver/non_blocking_data_type_controller.cc', 'sync_driver/non_blocking_data_type_controller.h', + 'sync_driver/non_frontend_data_type_controller.cc', + 'sync_driver/non_frontend_data_type_controller.h', 'sync_driver/non_ui_data_type_controller.cc', 'sync_driver/non_ui_data_type_controller.h', 'sync_driver/open_tabs_ui_delegate.cc', @@ -203,6 +207,8 @@ 'sync_driver/local_device_info_provider_mock.h', 'sync_driver/model_associator_mock.cc', 'sync_driver/model_associator_mock.h', + 'sync_driver/non_frontend_data_type_controller_mock.cc', + 'sync_driver/non_frontend_data_type_controller_mock.h', 'sync_driver/non_ui_data_type_controller_mock.cc', 'sync_driver/non_ui_data_type_controller_mock.h', ],
diff --git a/components/sync_driver/BUILD.gn b/components/sync_driver/BUILD.gn index 9c1806c..340c766 100644 --- a/components/sync_driver/BUILD.gn +++ b/components/sync_driver/BUILD.gn
@@ -47,6 +47,8 @@ "generic_change_processor_factory.h", "glue/browser_thread_model_worker.cc", "glue/browser_thread_model_worker.h", + "glue/chrome_report_unrecoverable_error.cc", + "glue/chrome_report_unrecoverable_error.h", "glue/history_model_worker.cc", "glue/history_model_worker.h", "glue/synced_session.cc", @@ -66,6 +68,8 @@ "model_associator.h", "non_blocking_data_type_controller.cc", "non_blocking_data_type_controller.h", + "non_frontend_data_type_controller.cc", + "non_frontend_data_type_controller.h", "non_ui_data_type_controller.cc", "non_ui_data_type_controller.h", "open_tabs_ui_delegate.cc", @@ -177,6 +181,8 @@ "local_device_info_provider_mock.h", "model_associator_mock.cc", "model_associator_mock.h", + "non_frontend_data_type_controller_mock.cc", + "non_frontend_data_type_controller_mock.h", "non_ui_data_type_controller_mock.cc", "non_ui_data_type_controller_mock.h", ]
diff --git a/components/sync_driver/data_type_controller.cc b/components/sync_driver/data_type_controller.cc index 0e4bc4f..6699b98 100644 --- a/components/sync_driver/data_type_controller.cc +++ b/components/sync_driver/data_type_controller.cc
@@ -14,7 +14,8 @@ const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, const base::Closure& error_callback) : base::RefCountedDeleteOnMessageLoop<DataTypeController>(ui_thread), - error_callback_(error_callback) {} + error_callback_(error_callback), + ui_thread_(ui_thread) {} DataTypeController::~DataTypeController() { }
diff --git a/components/sync_driver/data_type_controller.h b/components/sync_driver/data_type_controller.h index 2c701c0..6604c34 100644 --- a/components/sync_driver/data_type_controller.h +++ b/components/sync_driver/data_type_controller.h
@@ -151,9 +151,16 @@ ~DataTypeController() override; + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread() const { + return ui_thread_; + } + // The callback that will be invoked when an unrecoverable error occurs. // TODO(sync): protected for use by legacy controllers. base::Closure error_callback_; + + private: + const scoped_refptr<base::SingleThreadTaskRunner> ui_thread_; }; } // namespace sync_driver
diff --git a/components/sync_driver/data_type_manager_impl.cc b/components/sync_driver/data_type_manager_impl.cc index c16e3438..b98e8804 100644 --- a/components/sync_driver/data_type_manager_impl.cc +++ b/components/sync_driver/data_type_manager_impl.cc
@@ -45,7 +45,6 @@ DataTypeManagerImpl::AssociationTypesInfo::~AssociationTypesInfo() {} DataTypeManagerImpl::DataTypeManagerImpl( - const base::Closure& unrecoverable_error_method, const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& debug_info_listener, const DataTypeController::TypeMap* controllers, @@ -61,7 +60,6 @@ model_association_manager_(controllers, this), observer_(observer), encryption_handler_(encryption_handler), - unrecoverable_error_method_(unrecoverable_error_method), catch_up_in_progress_(false), weak_ptr_factory_(this) { DCHECK(configurer_);
diff --git a/components/sync_driver/data_type_manager_impl.h b/components/sync_driver/data_type_manager_impl.h index fd9a5bc..692d27f0 100644 --- a/components/sync_driver/data_type_manager_impl.h +++ b/components/sync_driver/data_type_manager_impl.h
@@ -39,7 +39,6 @@ public ModelAssociationManagerDelegate { public: DataTypeManagerImpl( - const base::Closure& unrecoverable_error_method, const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& debug_info_listener, const DataTypeController::TypeMap* controllers, @@ -222,8 +221,6 @@ // Association and time stats of data type configuration. std::vector<syncer::DataTypeConfigurationStats> configuration_stats_; - base::Closure unrecoverable_error_method_; - // True iff we are in the process of catching up datatypes. bool catch_up_in_progress_;
diff --git a/components/sync_driver/data_type_manager_impl_unittest.cc b/components/sync_driver/data_type_manager_impl_unittest.cc index 8d810f5..dd7028bc 100644 --- a/components/sync_driver/data_type_manager_impl_unittest.cc +++ b/components/sync_driver/data_type_manager_impl_unittest.cc
@@ -239,8 +239,7 @@ const DataTypeController::TypeMap* controllers, const DataTypeEncryptionHandler* encryption_handler, DataTypeManagerObserver* observer) - : DataTypeManagerImpl(base::Closure(), - debug_info_listener, + : DataTypeManagerImpl(debug_info_listener, controllers, encryption_handler, configurer,
diff --git a/components/sync_driver/fake_sync_client.cc b/components/sync_driver/fake_sync_client.cc index 0470871..b85cc6bf 100644 --- a/components/sync_driver/fake_sync_client.cc +++ b/components/sync_driver/fake_sync_client.cc
@@ -34,6 +34,10 @@ return nullptr; } +favicon::FaviconService* FakeSyncClient::GetFaviconService() { + return nullptr; +} + history::HistoryService* FakeSyncClient::GetHistoryService() { return nullptr; } @@ -52,6 +56,10 @@ return scoped_refptr<autofill::AutofillWebDataService>(); } +BookmarkUndoService* FakeSyncClient::GetBookmarkUndoServiceIfExists() { + return nullptr; +} + base::WeakPtr<syncer::SyncableService> FakeSyncClient::GetSyncableServiceForType(syncer::ModelType type) { return base::WeakPtr<syncer::SyncableService>();
diff --git a/components/sync_driver/fake_sync_client.h b/components/sync_driver/fake_sync_client.h index 2007191..e87b116e 100644 --- a/components/sync_driver/fake_sync_client.h +++ b/components/sync_driver/fake_sync_client.h
@@ -22,10 +22,12 @@ SyncService* GetSyncService() override; PrefService* GetPrefService() override; bookmarks::BookmarkModel* GetBookmarkModel() override; + favicon::FaviconService* GetFaviconService() override; history::HistoryService* GetHistoryService() override; scoped_refptr<password_manager::PasswordStore> GetPasswordStore() override; autofill::PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<autofill::AutofillWebDataService> GetWebDataService() override; + BookmarkUndoService* GetBookmarkUndoServiceIfExists() override; base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType( syncer::ModelType type) override; SyncApiComponentFactory* GetSyncApiComponentFactory() override;
diff --git a/components/sync_driver/fake_sync_service.cc b/components/sync_driver/fake_sync_service.cc index 3c2c5e3a..f8d3719 100644 --- a/components/sync_driver/fake_sync_service.cc +++ b/components/sync_driver/fake_sync_service.cc
@@ -34,6 +34,10 @@ return syncer::ModelTypeSet(); } +SyncClient* FakeSyncService::GetSyncClient() const { + return nullptr; +} + void FakeSyncService::AddObserver(SyncServiceObserver* observer) { }
diff --git a/components/sync_driver/fake_sync_service.h b/components/sync_driver/fake_sync_service.h index 4611544c..dfd0e2c 100644 --- a/components/sync_driver/fake_sync_service.h +++ b/components/sync_driver/fake_sync_service.h
@@ -28,6 +28,7 @@ bool IsSyncAllowed() const override; bool IsSyncActive() const override; syncer::ModelTypeSet GetActiveDataTypes() const override; + SyncClient* GetSyncClient() const override; void AddObserver(SyncServiceObserver* observer) override; void RemoveObserver(SyncServiceObserver* observer) override; bool HasObserver(const SyncServiceObserver* observer) const override;
diff --git a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc b/components/sync_driver/glue/chrome_report_unrecoverable_error.cc similarity index 68% rename from chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc rename to components/sync_driver/glue/chrome_report_unrecoverable_error.cc index 4815203a..c824bd5 100644 --- a/chrome/browser/sync/glue/chrome_report_unrecoverable_error.cc +++ b/components/sync_driver/glue/chrome_report_unrecoverable_error.cc
@@ -2,19 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" +#include "components/sync_driver/glue/chrome_report_unrecoverable_error.h" #include "base/debug/dump_without_crashing.h" #include "base/rand_util.h" -#include "chrome/common/channel_info.h" -#include "chrome/common/chrome_constants.h" -#include "components/version_info/version_info.h" namespace browser_sync { -void ChromeReportUnrecoverableError() { +void ChromeReportUnrecoverableError(version_info::Channel channel) { // Only upload on canary/dev builds to avoid overwhelming crash server. - version_info::Channel channel = chrome::GetChannel(); if (channel != version_info::Channel::CANARY && channel != version_info::Channel::DEV) { return; @@ -23,7 +19,7 @@ // We only want to upload |kErrorUploadRatio| ratio of errors. const double kErrorUploadRatio = 0.01; if (kErrorUploadRatio <= 0.0) - return; // We are not allowed to upload errors. + return; // We are not allowed to upload errors. double random_number = base::RandDouble(); if (random_number > kErrorUploadRatio) return;
diff --git a/components/sync_driver/glue/chrome_report_unrecoverable_error.h b/components/sync_driver/glue/chrome_report_unrecoverable_error.h new file mode 100644 index 0000000..54e3dfad --- /dev/null +++ b/components/sync_driver/glue/chrome_report_unrecoverable_error.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_ +#define COMPONENTS_SYNC_DRIVER_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_ + +#include "components/version_info/version_info.h" + +namespace browser_sync { + +// Sends a minidump via breakpad for canary/dev channels at a hardcoded +// sampling rate. Does nothing on beta/stable builds. +void ChromeReportUnrecoverableError(version_info::Channel channel); + +} // namespace browser_sync + +#endif // COMPONENTS_SYNC_DRIVER_GLUE_CHROME_REPORT_UNRECOVERABLE_ERROR_H_
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc b/components/sync_driver/non_frontend_data_type_controller.cc similarity index 93% rename from chrome/browser/sync/glue/non_frontend_data_type_controller.cc rename to components/sync_driver/non_frontend_data_type_controller.cc index 7985cd3f..02742cb 100644 --- a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc +++ b/components/sync_driver/non_frontend_data_type_controller.cc
@@ -2,25 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h" +#include "components/sync_driver/non_frontend_data_type_controller.h" #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" #include "base/thread_task_runner_handle.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/sync_driver/change_processor.h" #include "components/sync_driver/model_associator.h" #include "components/sync_driver/sync_client.h" #include "components/sync_driver/sync_service.h" -#include "content/public/browser/browser_thread.h" #include "sync/api/sync_error.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/util/weak_handle.h" #include "sync/util/data_type_histogram.h" -using content::BrowserThread; - namespace browser_sync { class NonFrontendDataTypeController::BackendComponentsContainer { @@ -53,7 +49,6 @@ NonFrontendDataTypeController* controller) : controller_(controller), type_(controller->type()) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); controller_handle_ = syncer::MakeWeakHandle(controller_->weak_ptr_factory_.GetWeakPtr()); } @@ -166,13 +161,13 @@ model_associator_(NULL), change_processor_(NULL), weak_ptr_factory_(this) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(this->ui_thread()->RunsTasksOnCurrentThread()); DCHECK(sync_client_); } void NonFrontendDataTypeController::LoadModels( const ModelLoadCallback& model_load_callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); model_load_callback_ = model_load_callback; if (state_ != NOT_RUNNING) { model_load_callback.Run(type(), @@ -205,7 +200,7 @@ void NonFrontendDataTypeController::StartAssociating( const StartCallback& start_callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); DCHECK(!start_callback.is_null()); DCHECK(!components_container_); DCHECK_EQ(state_, MODEL_LOADED); @@ -238,7 +233,7 @@ } void NonFrontendDataTypeController::Stop() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); if (state_ == NOT_RUNNING) return; @@ -275,7 +270,7 @@ DCHECK(IsOnBackendThread()); DCHECK_EQ(type(), error.model_type()); RecordUnrecoverableError(error.location(), error.message()); - BrowserThread::PostTask(BrowserThread::UI, error.location(), + ui_thread()->PostTask(error.location(), base::Bind(&NonFrontendDataTypeController::DisableImpl, this, error)); @@ -291,13 +286,13 @@ weak_ptr_factory_(this) {} NonFrontendDataTypeController::~NonFrontendDataTypeController() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); DCHECK(!change_processor_); DCHECK(!model_associator_); } bool NonFrontendDataTypeController::StartModels() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); DCHECK_EQ(state_, MODEL_STARTING); // By default, no additional services need to be started before we can proceed // with model association, so do nothing. @@ -305,14 +300,14 @@ } bool NonFrontendDataTypeController::IsOnBackendThread() { - return !BrowserThread::CurrentlyOn(BrowserThread::UI); + return !ui_thread()->RunsTasksOnCurrentThread(); } void NonFrontendDataTypeController::StartDone( DataTypeController::ConfigureResult start_result, const syncer::SyncMergeResult& local_merge_result, const syncer::SyncMergeResult& syncer_merge_result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); DataTypeController::State new_state; if (IsSuccessfulResult(start_result)) { @@ -332,7 +327,7 @@ DataTypeController::State new_state, const syncer::SyncMergeResult& local_merge_result, const syncer::SyncMergeResult& syncer_merge_result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); state_ = new_state; if (state_ != RUNNING) { @@ -345,7 +340,7 @@ void NonFrontendDataTypeController::DisableImpl( const syncer::SyncError& error) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); if (!model_load_callback_.is_null()) { model_load_callback_.Run(type(), error); } @@ -353,7 +348,7 @@ void NonFrontendDataTypeController::RecordAssociationTime( base::TimeDelta time) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); #define PER_DATA_TYPE_MACRO(type_str) \ UMA_HISTOGRAM_TIMES("Sync." type_str "AssociationTime", time); SYNC_DATA_TYPE_HISTOGRAM(type()); @@ -361,7 +356,7 @@ } void NonFrontendDataTypeController::RecordStartFailure(ConfigureResult result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures", ModelTypeToHistogramInt(type()), syncer::MODEL_TYPE_COUNT); @@ -413,7 +408,7 @@ void NonFrontendDataTypeController::AssociationCallback( AssociationResult result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(ui_thread()->RunsTasksOnCurrentThread()); if (result.needs_crypto) { StartDone(NEEDS_CRYPTO,
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.h b/components/sync_driver/non_frontend_data_type_controller.h similarity index 95% rename from chrome/browser/sync/glue/non_frontend_data_type_controller.h rename to components/sync_driver/non_frontend_data_type_controller.h index daa04820..b75a5c9 100644 --- a/chrome/browser/sync/glue/non_frontend_data_type_controller.h +++ b/components/sync_driver/non_frontend_data_type_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__ -#define CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__ +#ifndef COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__ +#define COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__ #include <string> @@ -17,9 +17,6 @@ #include "components/sync_driver/directory_data_type_controller.h" #include "components/sync_driver/sync_api_component_factory.h" -class Profile; -class ProfileSyncService; - namespace base { class TimeDelta; class SingleThreadTaskRunner; @@ -186,4 +183,4 @@ } // namespace browser_sync -#endif // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__ +#endif // COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc b/components/sync_driver/non_frontend_data_type_controller_mock.cc similarity index 82% rename from chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc rename to components/sync_driver/non_frontend_data_type_controller_mock.cc index dfde5951..c14b9ab9 100644 --- a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc +++ b/components/sync_driver/non_frontend_data_type_controller_mock.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h" +#include "components/sync_driver/non_frontend_data_type_controller_mock.h" namespace browser_sync {
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h b/components/sync_driver/non_frontend_data_type_controller_mock.h similarity index 88% rename from chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h rename to components/sync_driver/non_frontend_data_type_controller_mock.h index 13fdd895..1867541 100644 --- a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h +++ b/components/sync_driver/non_frontend_data_type_controller_mock.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__ -#define CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__ +#ifndef COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__ +#define COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__ -#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h" +#include "components/sync_driver/non_frontend_data_type_controller.h" #include "sync/api/sync_error.h" #include "testing/gmock/include/gmock/gmock.h" @@ -60,4 +60,4 @@ } // namespace browser_sync -#endif // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__ +#endif // COMPONENTS_SYNC_DRIVER_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__
diff --git a/components/sync_driver/sync_client.h b/components/sync_driver/sync_client.h index a4788f7..870decf 100644 --- a/components/sync_driver/sync_client.h +++ b/components/sync_driver/sync_client.h
@@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "sync/internal_api/public/base/model_type.h" +class BookmarkUndoService; class PrefService; namespace autofill { @@ -22,6 +23,10 @@ class BookmarkModel; } // namespace bookmarks +namespace favicon { +class FaviconService; +} // namespace favicon + namespace history { class HistoryService; } // namespace history @@ -63,11 +68,13 @@ // DataType specific service getters. virtual bookmarks::BookmarkModel* GetBookmarkModel() = 0; + virtual favicon::FaviconService* GetFaviconService() = 0; virtual history::HistoryService* GetHistoryService() = 0; virtual scoped_refptr<password_manager::PasswordStore> GetPasswordStore() = 0; virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0; virtual scoped_refptr<autofill::AutofillWebDataService> GetWebDataService() = 0; + virtual BookmarkUndoService* GetBookmarkUndoServiceIfExists() = 0; // Returns a weak pointer to the syncable service specified by |type|. // Weak pointer may be unset if service is already destroyed.
diff --git a/components/sync_driver/sync_service.h b/components/sync_driver/sync_service.h index 4b2de8d6..bdb75233 100644 --- a/components/sync_driver/sync_service.h +++ b/components/sync_driver/sync_service.h
@@ -43,6 +43,7 @@ class DataTypeController; class LocalDeviceInfoProvider; class OpenTabsUIDelegate; +class SyncClient; class SyncService : public DataTypeEncryptionHandler { public: @@ -109,6 +110,9 @@ // be updated. virtual syncer::ModelTypeSet GetActiveDataTypes() const = 0; + // Returns the SyncClient instance associated with this service. + virtual SyncClient* GetSyncClient() const = 0; + // Adds/removes an observer. SyncService does not take ownership of the // observer. virtual void AddObserver(SyncServiceObserver* observer) = 0;
diff --git a/components/test_runner/event_sender.cc b/components/test_runner/event_sender.cc index a2e55d5..17a45cf 100644 --- a/components/test_runner/event_sender.cc +++ b/components/test_runner/event_sender.cc
@@ -2405,13 +2405,13 @@ return; } if (pointer_type_string == kPointerTypeStringUnknown) { - e->pointerType = WebMouseEvent::PointerTypeUnknown; + e->pointerType = WebMouseEvent::PointerType::Unknown; } else if (pointer_type_string == kPointerTypeStringMouse) { - e->pointerType = WebMouseEvent::PointerTypeMouse; + e->pointerType = WebMouseEvent::PointerType::Mouse; } else if (pointer_type_string == kPointerTypeStringPen) { - e->pointerType = WebMouseEvent::PointerTypePen; + e->pointerType = WebMouseEvent::PointerType::Pen; } else if (pointer_type_string == kPointerTypeStringTouch) { - e->pointerType = WebMouseEvent::PointerTypeTouch; + e->pointerType = WebMouseEvent::PointerType::Touch; } else { args->ThrowError(); return;
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc index 2a1a3dfd..c26ee0d1 100644 --- a/content/app/android/library_loader_hooks.cc +++ b/content/app/android/library_loader_hooks.cc
@@ -103,7 +103,6 @@ // Android's main browser loop is custom so we set the browser // name here as early as possible. - TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); base::trace_event::TraceLog::GetInstance()->SetProcessName("Browser"); base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventBrowserProcessSortIndex);
diff --git a/content/browser/appcache/appcache_response.h b/content/browser/appcache/appcache_response.h index 8d6c790..a4c87db 100644 --- a/content/browser/appcache/appcache_response.h +++ b/content/browser/appcache/appcache_response.h
@@ -209,8 +209,9 @@ // negative error code or the number of bytes written. The 'callback' is a // required parameter. The contents of 'info_buf' are not modified. // Should only be called where there is no Write operation in progress. - void WriteInfo(HttpResponseInfoIOBuffer* info_buf, - const net::CompletionCallback& callback); + // (virtual for testing) + virtual void WriteInfo(HttpResponseInfoIOBuffer* info_buf, + const net::CompletionCallback& callback); // Writes data to storage. Always returns the result of the write // asynchronously through the 'callback'. Returns the number of bytes written @@ -220,8 +221,10 @@ // the number of bytes written. The 'callback' is a required parameter. // The contents of 'buf' are not modified. // Should only be called where there is no Write operation in progress. - void WriteData(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback); + // (virtual for testing) + virtual void WriteData(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback); // Returns true if there is a write pending. bool IsWritePending() { return IsIOPending(); }
diff --git a/content/browser/browser_main.cc b/content/browser/browser_main.cc index 4c114b43..d0897f1d 100644 --- a/content/browser/browser_main.cc +++ b/content/browser/browser_main.cc
@@ -10,9 +10,27 @@ namespace content { +namespace { + +// Generates a pair of BrowserMain async events. We don't use the TRACE_EVENT0 +// macro because the tracing infrastructure doesn't expect synchronous events +// around the main loop of a thread. +class ScopedBrowserMainEvent { + public: + ScopedBrowserMainEvent() { + TRACE_EVENT_ASYNC_BEGIN0("startup", "BrowserMain", 0); + } + ~ScopedBrowserMainEvent() { + TRACE_EVENT_ASYNC_END0("startup", "BrowserMain", 0); + } +}; + +} // namespace + // Main routine for running as the Browser process. int BrowserMain(const MainFunctionParams& parameters) { - TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); + ScopedBrowserMainEvent scoped_browser_main_event; + base::trace_event::TraceLog::GetInstance()->SetProcessName("Browser"); base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventBrowserProcessSortIndex); @@ -27,8 +45,6 @@ main_runner->Shutdown(); - TRACE_EVENT_END_ETW("BrowserMain", 0, 0); - return exit_code; }
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index a4e2c8a..5aa0567 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -905,7 +905,9 @@ } void BrowserMainLoop::RunMainMessageLoopParts() { - TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); + // Don't use the TRACE_EVENT0 macro because the tracing infrastructure doesn't + // expect synchronous events around the main loop of a thread. + TRACE_EVENT_ASYNC_BEGIN0("toplevel", "BrowserMain:MESSAGE_LOOP", this); bool ran_main_loop = false; if (parts_) @@ -914,7 +916,7 @@ if (!ran_main_loop) MainMessageLoopRun(); - TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); + TRACE_EVENT_ASYNC_END0("toplevel", "BrowserMain:MESSAGE_LOOP", this); } void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index da62f4a..ca8dc4ce 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -51,6 +51,7 @@ #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" #include "net/http/http_util.h" +#include "net/test/url_request/url_request_failed_job.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job.h" @@ -181,6 +182,7 @@ // within the groups will be in the order that they appeared. // Note that this clears messages_. The caller takes ownership of any // SharedMemoryHandles in messages placed into |msgs|. + // TODO(mmenke): This seems really fragile. Consider reworking ownership. typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; void GetClassifiedMessages(ClassifiedMessages* msgs); @@ -340,12 +342,6 @@ } URLRequestTestDelayedStartJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - bool auto_advance) - : net::URLRequestTestJob(request, network_delegate, auto_advance) { - Init(); - } - URLRequestTestDelayedStartJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, const std::string& response_headers, const std::string& response_data, bool auto_advance) @@ -534,6 +530,7 @@ public: explicit TestURLRequestJobFactory(ResourceDispatcherHostTest* test_fixture) : test_fixture_(test_fixture), + hang_after_start_(false), delay_start_(false), delay_complete_(false), network_start_notification_(false), @@ -548,6 +545,11 @@ return url_request_jobs_created_count_; } + // When set, jobs will hang eternally once started. + void SetHangAfterStartJobGeneration(bool hang_after_start) { + hang_after_start_ = hang_after_start; + } + void SetDelayedStartJobGeneration(bool delay_job_start) { delay_start_ = delay_job_start; } @@ -588,6 +590,7 @@ private: ResourceDispatcherHostTest* test_fixture_; + bool hang_after_start_; bool delay_start_; bool delay_complete_; bool network_start_notification_; @@ -1669,9 +1672,6 @@ child_ids_.insert(test_filter->child_id()); // request 1 goes to the test delegate - ResourceHostMsg_Request request = CreateResourceRequest( - "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1()); - MakeTestRequestWithResourceType(test_filter.get(), 0, 1, net::URLRequestTestJob::test_url_1(), RESOURCE_TYPE_SUB_RESOURCE); @@ -1741,6 +1741,55 @@ EXPECT_EQ(0, network_delegate()->error_count()); } +// Tests whether the correct requests get canceled when a RenderViewHost is +// deleted. +TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderViewHostDeleted) { + // Requests all hang once started. This prevents requests from being + // destroyed due to completion. + job_factory_->SetHangAfterStartJobGeneration(true); + HandleScheme("http"); + + TestResourceDispatcherHostDelegate delegate; + host_.SetDelegate(&delegate); + host_.OnRenderViewHostCreated(filter_->child_id(), 0, true, false); + + // One RenderView issues a high priority request and a low priority one. Both + // should be started. + MakeTestRequestWithPriority(0, 1, net::HIGHEST); + MakeTestRequestWithPriority(0, 2, net::LOWEST); + KickOffRequest(); + EXPECT_EQ(2, network_delegate_.created_requests()); + EXPECT_EQ(0, network_delegate_.canceled_requests()); + + // The same RenderView issues two more low priority requests. The + // ResourceScheduler shouldn't let them start immediately. + MakeTestRequestWithPriority(0, 3, net::LOWEST); + MakeTestRequestWithPriority(0, 4, net::LOWEST); + KickOffRequest(); + EXPECT_EQ(2, network_delegate_.created_requests()); + EXPECT_EQ(0, network_delegate_.canceled_requests()); + + // Another RenderView in the same process as the old one issues a request, + // which is then started. + MakeTestRequestWithPriority(1, 5, net::LOWEST); + KickOffRequest(); + EXPECT_EQ(3, network_delegate_.created_requests()); + EXPECT_EQ(0, network_delegate_.canceled_requests()); + + // The first RenderView is destroyed. All 4 of its requests should be + // cancelled, and none of the two deferred requests should be started. + host_.OnRenderViewHostDeleted(filter_->child_id(), 0); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(3, network_delegate_.created_requests()); + EXPECT_EQ(4, network_delegate_.canceled_requests()); + + // No messages should have been sent, since none of the jobs made any + // progress. + ResourceIPCAccumulator::ClassifiedMessages msgs; + accum_.GetClassifiedMessages(&msgs); + EXPECT_EQ(0U, msgs.size()); +} + TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) { MakeTestRequestWithResourceType(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_4(), @@ -3448,6 +3497,10 @@ return new URLRequestLoadInfoJob(request, network_delegate, info->load_state, info->upload_progress); } + if (hang_after_start_) { + return new net::URLRequestFailedJob(request, network_delegate, + net::ERR_IO_PENDING); + } if (test_fixture_->response_headers_.empty()) { if (delay_start_) { return new URLRequestTestDelayedStartJob(request, network_delegate);
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index 2d90716..83055a6 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc
@@ -32,6 +32,11 @@ namespace { +enum StartMode { + START_SYNC, + START_ASYNC +}; + // Field trial constants const char kThrottleCoalesceFieldTrial[] = "RequestThrottlingAndCoalescing"; const char kThrottleCoalesceFieldTrialThrottle[] = "Throttle"; @@ -193,7 +198,8 @@ attributes_(kAttributeNone), scheduler_(scheduler), priority_(priority), - fifo_ordering_(0) { + fifo_ordering_(0), + weak_ptr_factory_(this) { DCHECK(!request_->GetUserData(kUserDataKey)); request_->SetUserData(kUserDataKey, new UnownedPointer(this)); } @@ -208,10 +214,39 @@ ->get(); } - void Start() { - ready_ = true; + // Starts the request. If |start_mode| is START_ASYNC, the request will not + // be started immediately. + void Start(StartMode start_mode) { + DCHECK(!ready_); + + // If the request was cancelled, do nothing. if (!request_->status().is_success()) return; + + bool was_deferred = deferred_; + + // If the request was deferred, need to start it. Otherwise, will just not + // defer starting it in the first place, and the value of |start_mode| + // makes no difference. + if (deferred_) { + // If can't start the request synchronously, post a task to start the + // request. + if (start_mode == START_ASYNC) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ScheduledResourceRequest::Start, + weak_ptr_factory_.GetWeakPtr(), + START_SYNC)); + return; + } + deferred_ = false; + controller()->Resume(); + } + + ready_ = true; + + // The rest of this method is just collecting histograms. + base::TimeTicks time = base::TimeTicks::Now(); ClientState current_state = scheduler_->GetClientState(client_id_); // Note: the client state isn't perfectly accurate since it won't capture @@ -227,11 +262,8 @@ } base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0); - if (deferred_) { - deferred_ = false; - controller()->Resume(); + if (was_deferred) time_was_deferred = time - time_deferred_; - } PostHistogram("RequestTimeDeferred", client_state, NULL, time_was_deferred); PostHistogram("RequestTimeThrottled", client_state, NULL, time - request_->creation_time()); @@ -297,6 +329,9 @@ uint32 fifo_ordering_; base::TimeTicks time_deferred_; + base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest> + weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); }; @@ -356,10 +391,12 @@ void ScheduleRequest(net::URLRequest* url_request, ScheduledResourceRequest* request) { SetRequestAttributes(request, DetermineRequestAttributes(request)); - if (ShouldStartRequest(request) == START_REQUEST) - StartRequest(request); - else + if (ShouldStartRequest(request) == START_REQUEST) { + // New requests can be started synchronously without issue. + StartRequest(request, START_SYNC); + } else { pending_requests_.Insert(request); + } } void RemoveRequest(ScheduledResourceRequest* request) { @@ -385,8 +422,9 @@ ScheduledResourceRequest* request = *pending_requests_.GetNextHighestIterator(); pending_requests_.Erase(request); - // StartRequest() may modify pending_requests_. TODO(ricea): Does it? - StartRequest(request); + // Starting requests asynchronously ensures no side effects, and avoids + // starting a bunch of requests that may be about to be deleted. + StartRequest(request, START_ASYNC); } RequestSet unowned_requests; for (RequestSet::iterator it = in_flight_requests_.begin(); @@ -716,9 +754,10 @@ return false; } - void StartRequest(ScheduledResourceRequest* request) { + void StartRequest(ScheduledResourceRequest* request, + StartMode start_mode) { InsertInFlightRequest(request); - request->Start(); + request->Start(start_mode); } // ShouldStartRequest is the main scheduling algorithm. @@ -890,7 +929,7 @@ if (query_result == START_REQUEST) { pending_requests_.Erase(request); - StartRequest(request); + StartRequest(request, START_ASYNC); // StartRequest can modify the pending list, so we (re)start evaluation // from the currently highest priority request. Avoid copying a singular @@ -1043,7 +1082,7 @@ // 2. Most unittests don't send the IPCs needed to register Clients. // 3. The tab is closed while a RequestResource IPC is in flight. unowned_requests_.insert(request.get()); - request->Start(); + request->Start(START_SYNC); return request.Pass(); } @@ -1086,7 +1125,7 @@ DCHECK(CalledOnValidThread()); ClientId client_id = MakeClientId(child_id, route_id); ClientMap::iterator it = client_map_.find(client_id); - CHECK(it != client_map_.end()); + DCHECK(it != client_map_.end()); Client* client = it->second; // ResourceDispatcherHost cancels all requests except for cross-renderer
diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc index 3aaf23d..e773f6ad 100644 --- a/content/browser/loader/resource_scheduler_unittest.cc +++ b/content/browser/loader/resource_scheduler_unittest.cc
@@ -282,7 +282,9 @@ EXPECT_TRUE(high->started()); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -293,8 +295,15 @@ EXPECT_TRUE(high->started()); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); + // TODO(mmenke): The name of this test implies this should be false. + // Investigate if this is now expected, remove or update this test if it is. + EXPECT_TRUE(low2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -305,9 +314,13 @@ EXPECT_TRUE(high->started()); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -319,7 +332,9 @@ EXPECT_TRUE(low->started()); EXPECT_TRUE(lowest->started()); EXPECT_FALSE(lowest2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest2->started()); } @@ -335,8 +350,10 @@ EXPECT_TRUE(low_spdy->started()); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -367,9 +384,13 @@ EXPECT_TRUE(high2->started()); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + high1.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(low2->started()); + high2.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -391,7 +412,9 @@ EXPECT_TRUE(high->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low1->started()); EXPECT_TRUE(low2->started()); EXPECT_TRUE(low4->started()); @@ -421,10 +444,14 @@ net::LOWEST)); EXPECT_FALSE(second_last_singlehost->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(second_last_singlehost->started()); EXPECT_FALSE(last_singlehost->started()); + lows_singlehost.erase(lows_singlehost.begin()); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(last_singlehost->started()); // Queue more requests from different hosts until we reach the total limit. @@ -432,6 +459,7 @@ kMaxNumDelayableRequestsPerClient - kMaxNumDelayableRequestsPerHost; EXPECT_GT(expected_slots_left, 0); ScopedVector<TestRequest> lows_different_host; + base::RunLoop().RunUntilIdle(); for (int i = 0; i < expected_slots_left; ++i) { string url = "http://host" + base::IntToString(i) + "/low"; lows_different_host.push_back(NewRequest(url.c_str(), net::LOWEST)); @@ -439,7 +467,7 @@ } scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last", - net::LOWEST)); + net::LOWEST)); EXPECT_FALSE(last_different_host->started()); } @@ -452,6 +480,7 @@ EXPECT_FALSE(request->started()); ChangeRequestPriority(request.get(), net::HIGHEST); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(request->started()); } @@ -466,6 +495,7 @@ EXPECT_FALSE(idle->started()); ChangeRequestPriority(request.get(), net::LOWEST); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_FALSE(idle->started()); @@ -478,6 +508,7 @@ scheduler()->OnWillInsertBody(kChildId, kRouteId); high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(request->started()); EXPECT_FALSE(idle->started()); @@ -494,6 +525,7 @@ EXPECT_FALSE(idle->started()); ChangeRequestPriority(request.get(), net::IDLE); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_FALSE(idle->started()); @@ -509,6 +541,7 @@ scheduler()->OnWillInsertBody(kChildId, kRouteId); high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_TRUE(idle->started()); @@ -532,14 +565,17 @@ } ChangeRequestPriority(request.get(), net::IDLE); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_FALSE(idle->started()); ChangeRequestPriority(request.get(), net::LOWEST); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_FALSE(idle->started()); scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); EXPECT_FALSE(idle->started()); } @@ -560,10 +596,12 @@ EXPECT_FALSE(request->started()); ChangeRequestPriority(request.get(), net::IDLE, 1); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); scheduler()->OnWillInsertBody(kChildId, kRouteId); high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(request->started()); } @@ -617,6 +655,7 @@ EXPECT_FALSE(request->started()); scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(request->started()); scoped_ptr<TestRequest> after(NewRequest("http://host/after", net::IDLE)); @@ -640,9 +679,11 @@ http_server_properties_.SetSupportsSpdy( net::HostPortPair("spdyhost1", 8080), true); low1_spdy.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low1->started()); low1.reset(); + base::RunLoop().RunUntilIdle(); scoped_ptr<TestRequest> low2_spdy( NewRequest("http://spdyhost2:8080/low", net::IDLE)); // Reprioritize a request after we learn the server supports SPDY. @@ -650,6 +691,7 @@ http_server_properties_.SetSupportsSpdy( net::HostPortPair("spdyhost2", 8080), true); ChangeRequestPriority(low2_spdy.get(), net::LOWEST); + base::RunLoop().RunUntilIdle(); scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); EXPECT_TRUE(low2->started()); } @@ -749,9 +791,10 @@ scheduler()->OnVisibilityChanged( kBackgroundChildId, kBackgroundRouteId, true); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, scheduler()->GetClientStateForTesting(kBackgroundChildId, - kBackgroundRouteId)); + kBackgroundRouteId)); EXPECT_TRUE(request->started()); } @@ -770,6 +813,7 @@ scheduler()->OnAudibilityChanged( kBackgroundChildId, kBackgroundRouteId, true); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, scheduler()->GetClientStateForTesting(kBackgroundChildId, kBackgroundRouteId)); @@ -843,8 +887,8 @@ EXPECT_FALSE(low->started()); EXPECT_FALSE(high->started()); - // request->CancelRequest(); request->Cancel(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(high->started()); EXPECT_FALSE(low->started()); } @@ -864,7 +908,8 @@ EXPECT_FALSE(request->started()); scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, - kBackgroundRouteId); + kBackgroundRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(request->started()); scoped_ptr<TestRequest> after( @@ -890,7 +935,8 @@ EXPECT_FALSE(request->started()); scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, - kBackgroundRouteId); + kBackgroundRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(high->started()); scoped_ptr<TestRequest> after( @@ -915,7 +961,8 @@ EXPECT_FALSE(request->started()); scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, - kBackgroundRouteId); + kBackgroundRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(request->started()); scoped_ptr<TestRequest> after( @@ -1687,6 +1734,7 @@ scheduler()->OnLoadingStateChanged( kBackgroundChildId2, kBackgroundRouteId2, true); scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(scheduler()->active_clients_loaded()); EXPECT_EQ(ResourceScheduler::THROTTLED, scheduler()->GetClientStateForTesting(kBackgroundChildId, @@ -1709,6 +1757,7 @@ // 2 visible loaded, 1 hidden loading, 1 hidden loaded scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(scheduler()->active_clients_loaded()); EXPECT_EQ(ResourceScheduler::UNTHROTTLED, scheduler()->GetClientStateForTesting(kBackgroundChildId, @@ -1725,6 +1774,7 @@ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(scheduler()->active_clients_loaded()); EXPECT_EQ(ResourceScheduler::THROTTLED, scheduler()->GetClientStateForTesting(kBackgroundChildId, @@ -1801,6 +1851,7 @@ EXPECT_FALSE(mock_timer_->IsRunning()); scheduler()->OnLoadingStateChanged( kBackgroundChildId, kBackgroundRouteId, true); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(ResourceScheduler::COALESCED, scheduler()->GetClientStateForTesting(kBackgroundChildId, kBackgroundRouteId)); @@ -2024,6 +2075,7 @@ EXPECT_FALSE(low->started()); FireCoalescingTimer(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(high->started()); EXPECT_TRUE(low->started()); @@ -2082,6 +2134,7 @@ EXPECT_FALSE(low_spdy->started()); FireCoalescingTimer(); + base::RunLoop().RunUntilIdle(); // All high priority requests should issue. EXPECT_TRUE(high->started()); @@ -2115,6 +2168,7 @@ EXPECT_FALSE(high->started()); FireCoalescingTimer(); + base::RunLoop().RunUntilIdle(); scoped_ptr<TestRequest> high2( NewBackgroundRequest("http://host/high2", net::HIGHEST)); @@ -2126,6 +2180,7 @@ EXPECT_FALSE(low->started()); FireCoalescingTimer(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(high->started()); EXPECT_TRUE(high2->started()); @@ -2257,7 +2312,9 @@ EXPECT_TRUE(high->started()); EXPECT_FALSE(low->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low->started()); EXPECT_TRUE(low2->started()); } @@ -2274,9 +2331,11 @@ scoped_ptr<TestRequest> lowest2(NewRequestWithChildAndRoute( "http://host/lowest", net::LOWEST, kChildId2, kRouteId2)); EXPECT_FALSE(lowest2->started()); + scheduler_->OnClientDeleted(kChildId2, kRouteId2); high.reset(); lowest1.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest2->started()); } @@ -2297,9 +2356,11 @@ scoped_ptr<TestRequest> lowest(NewRequestWithChildAndRoute( "http://host/lowest", net::LOWEST, kChildId2, kRouteId2)); EXPECT_FALSE(lowest->started()); + scheduler_->OnClientDeleted(kChildId2, kRouteId2); high.reset(); delayable_requests.clear(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest->started()); } @@ -2344,7 +2405,9 @@ EXPECT_TRUE(low2->started()); EXPECT_TRUE(lowest->started()); EXPECT_FALSE(lowest2->started()); + lowest.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest2->started()); } @@ -2391,14 +2454,20 @@ EXPECT_FALSE(low2->started()); EXPECT_FALSE(lowest->started()); EXPECT_FALSE(lowest2->started()); + low.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); EXPECT_FALSE(lowest->started()); EXPECT_FALSE(lowest2->started()); + low2.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest->started()); EXPECT_FALSE(lowest2->started()); + lowest.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(lowest2->started()); } @@ -2432,12 +2501,18 @@ EXPECT_TRUE(high2->started()); EXPECT_FALSE(low->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + high2.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(low2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -2473,13 +2548,19 @@ EXPECT_TRUE(high3->started()); EXPECT_FALSE(low->started()); EXPECT_FALSE(low2->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low->started()); EXPECT_FALSE(low2->started()); + high2.reset(); high3.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(low2->started()); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low2->started()); } @@ -2513,8 +2594,10 @@ EXPECT_TRUE(low->started()); EXPECT_TRUE(low2->started()); EXPECT_FALSE(low3->started()); + high.reset(); scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low3->started()); } @@ -2552,12 +2635,16 @@ EXPECT_FALSE(low->started()); EXPECT_FALSE(low2->started()); EXPECT_FALSE(low3->started()); + high.reset(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low->started()); EXPECT_TRUE(low2->started()); EXPECT_FALSE(low3->started()); + high2.reset(); scheduler()->OnWillInsertBody(kChildId, kRouteId); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(low3->started()); } @@ -2637,7 +2724,7 @@ } scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last", - net::LOWEST)); + net::LOWEST)); EXPECT_FALSE(last_different_host->started()); }
diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc index b1a9382f9..a9d0002 100644 --- a/content/browser/mojo/mojo_application_host.cc +++ b/content/browser/mojo/mojo_application_host.cc
@@ -102,11 +102,6 @@ channel_init_.WillDestroySoon(); } -void MojoApplicationHost::ShutdownOnIOThread() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - channel_init_.ShutdownOnIOThread(); -} - void MojoApplicationHost::OverrideIOTaskRunnerForTest( scoped_refptr<base::TaskRunner> io_task_runner) { io_task_runner_override_ = io_task_runner;
diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h index fffb59e..216b65a 100644 --- a/content/browser/mojo/mojo_application_host.h +++ b/content/browser/mojo/mojo_application_host.h
@@ -40,9 +40,6 @@ void WillDestroySoon(); - // Shuts down the Mojo channel. Must be called from the IO thread. - void ShutdownOnIOThread(); - ServiceRegistry* service_registry() { return &service_registry_; } #if defined(OS_ANDROID)
diff --git a/content/browser/renderer_host/input/motion_event_web.cc b/content/browser/renderer_host/input/motion_event_web.cc index 82b6ed7..ddc3037 100644 --- a/content/browser/renderer_host/input/motion_event_web.cc +++ b/content/browser/renderer_host/input/motion_event_web.cc
@@ -163,18 +163,17 @@ const WebPointerProperties& pointer = event_.touches[pointer_index]; switch (pointer.pointerType) { - case WebPointerProperties::PointerTypeUnknown: + case WebPointerProperties::PointerType::Unknown: return TOOL_TYPE_UNKNOWN; - case WebPointerProperties::PointerTypeMouse: + case WebPointerProperties::PointerType::Mouse: return TOOL_TYPE_MOUSE; - case WebPointerProperties::PointerTypePen: + case WebPointerProperties::PointerType::Pen: return TOOL_TYPE_STYLUS; - case WebPointerProperties::PointerTypeTouch: + case WebPointerProperties::PointerType::Touch: return TOOL_TYPE_FINGER; - default: - NOTREACHED() << "Unhandled pointer type " << pointer.pointerType; - return TOOL_TYPE_UNKNOWN; } + NOTREACHED() << "Unexpected pointerType"; + return TOOL_TYPE_UNKNOWN; } int MotionEventWeb::GetButtonState() const {
diff --git a/content/browser/renderer_host/media/audio_input_sync_writer.cc b/content/browser/renderer_host/media/audio_input_sync_writer.cc index 68d052e..fa0d820 100644 --- a/content/browser/renderer_host/media/audio_input_sync_writer.cc +++ b/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -244,8 +244,7 @@ } // Push parameters to fifo. - AudioInputBufferParameters params = - { volume, 0, hardware_delay_bytes, 0, key_pressed }; + OverflowParams params = { volume, hardware_delay_bytes, key_pressed }; overflow_params_.push_back(params); // Push audio data to fifo.
diff --git a/content/browser/renderer_host/media/audio_input_sync_writer.h b/content/browser/renderer_host/media/audio_input_sync_writer.h index 896a0d8..d504959 100644 --- a/content/browser/renderer_host/media/audio_input_sync_writer.h +++ b/content/browser/renderer_host/media/audio_input_sync_writer.h
@@ -152,7 +152,12 @@ // since audio processing such as echo cancelling requires that to perform // properly. ScopedVector<media::AudioBus> overflow_buses_; - std::deque<media::AudioInputBufferParameters> overflow_params_; + struct OverflowParams { + double volume; + uint32_t hardware_delay_bytes; + bool key_pressed; + }; + std::deque<OverflowParams> overflow_params_; DISALLOW_IMPLICIT_CONSTRUCTORS(AudioInputSyncWriter); };
diff --git a/content/browser/renderer_host/p2p/socket_host_udp.h b/content/browser/renderer_host/p2p/socket_host_udp.h index 1839663..8e3d70f 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp.h +++ b/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -17,6 +17,7 @@ #include "content/common/content_export.h" #include "content/common/p2p_socket_type.h" #include "net/base/ip_endpoint.h" +#include "net/udp/diff_serv_code_point.h" #include "net/udp/udp_server_socket.h" #include "third_party/webrtc/base/asyncpacketsocket.h"
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index efe1ce6..91e81fa5 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -540,19 +540,6 @@ this, id)); } -net::URLRequestContext* RenderMessageFilter::GetRequestContextForURL( - const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - net::URLRequestContext* context = - GetContentClient()->browser()->OverrideRequestContextForURL( - url, resource_context_); - if (!context) - context = request_context_->GetURLRequestContext(); - - return context; -} - void RenderMessageFilter::OnCacheableMetadataAvailable( const GURL& url, base::Time expected_response_time,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index d27b013c..4889e32 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h
@@ -101,11 +101,6 @@ int render_process_id() const { return render_process_id_; } - // Returns the correct net::URLRequestContext depending on what type of url is - // given. - // Only call on the IO thread. - net::URLRequestContext* GetRequestContextForURL(const GURL& url); - protected: ~RenderMessageFilter() override;
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index 59a104a..c1adca8 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -101,8 +101,7 @@ // Convenience function, just like RenderViewHost::FromID. static RenderViewHostImpl* FromID(int render_process_id, int render_view_id); - // |routing_id| could be a valid route id, or it could be MSG_ROUTING_NONE, in - // which case RenderWidgetHost will create a new one. |swapped_out| indicates + // |routing_id| must be a valid route id. |swapped_out| indicates // whether the view should initially be swapped out (e.g., for an opener // frame being rendered by another process). |hidden| indicates whether the // view is initially hidden or visible.
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 3489495..64d2dda 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -87,8 +87,7 @@ public TouchEmulatorClient, public IPC::Listener { public: - // routing_id can be MSG_ROUTING_NONE, in which case the next available - // routing id is taken from the RenderProcessHost. + // |routing_id| must not be MSG_ROUTING_NONE. // If this object outlives |delegate|, DetachDelegate() must be called when // |delegate| goes away. RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
diff --git a/content/browser/renderer_host/web_input_event_aura.cc b/content/browser/renderer_host/web_input_event_aura.cc index 543ec6d4..7d67025a 100644 --- a/content/browser/renderer_host/web_input_event_aura.cc +++ b/content/browser/renderer_host/web_input_event_aura.cc
@@ -37,16 +37,16 @@ ui::EventPointerType pointer_type) { switch (pointer_type) { case ui::EventPointerType::POINTER_TYPE_UNKNOWN: - return blink::WebPointerProperties::PointerType::PointerTypeUnknown; + return blink::WebPointerProperties::PointerType::Unknown; case ui::EventPointerType::POINTER_TYPE_MOUSE: - return blink::WebPointerProperties::PointerType::PointerTypeMouse; + return blink::WebPointerProperties::PointerType::Mouse; case ui::EventPointerType::POINTER_TYPE_PEN: - return blink::WebPointerProperties::PointerType::PointerTypePen; + return blink::WebPointerProperties::PointerType::Pen; case ui::EventPointerType::POINTER_TYPE_TOUCH: - return blink::WebPointerProperties::PointerType::PointerTypeTouch; + return blink::WebPointerProperties::PointerType::Touch; } NOTREACHED() << "Unexpected EventPointerType"; - return blink::WebPointerProperties::PointerType::PointerTypeUnknown; + return blink::WebPointerProperties::PointerType::Unknown; } } // namespace
diff --git a/content/browser/renderer_host/web_input_event_aura_unittest.cc b/content/browser/renderer_host/web_input_event_aura_unittest.cc index 42c6a97..43037537 100644 --- a/content/browser/renderer_host/web_input_event_aura_unittest.cc +++ b/content/browser/renderer_host/web_input_event_aura_unittest.cc
@@ -421,7 +421,7 @@ ui::EF_LEFT_MOUSE_BUTTON); blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event); - EXPECT_EQ(blink::WebPointerProperties::PointerType::PointerTypeMouse, + EXPECT_EQ(blink::WebPointerProperties::PointerType::Mouse, webkit_event.pointerType); EXPECT_EQ(0, webkit_event.tiltX); EXPECT_EQ(0, webkit_event.tiltY); @@ -447,7 +447,7 @@ /* tilt_y */ -89.5f)); blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event); - EXPECT_EQ(blink::WebPointerProperties::PointerType::PointerTypePen, + EXPECT_EQ(blink::WebPointerProperties::PointerType::Pen, webkit_event.pointerType); EXPECT_EQ(90, webkit_event.tiltX); EXPECT_EQ(-90, webkit_event.tiltY); @@ -475,7 +475,7 @@ EXPECT_EQ(blink::WebInputEvent::MouseWheel, webkit_event.type); EXPECT_FLOAT_EQ(aura_event.x_offset() / 53.0f, webkit_event.wheelTicksX); EXPECT_FLOAT_EQ(aura_event.y_offset() / 53.0f, webkit_event.wheelTicksY); - EXPECT_EQ(blink::WebPointerProperties::PointerType::PointerTypeMouse, + EXPECT_EQ(blink::WebPointerProperties::PointerType::Mouse, webkit_event.pointerType); EXPECT_EQ(0, webkit_event.tiltX); EXPECT_EQ(0, webkit_event.tiltY); @@ -500,7 +500,7 @@ EXPECT_EQ(blink::WebInputEvent::MouseWheel, webkit_event.type); EXPECT_FLOAT_EQ(aura_event.y_offset() / 53.0f, webkit_event.wheelTicksX); EXPECT_FLOAT_EQ(0, webkit_event.wheelTicksY); - EXPECT_EQ(blink::WebPointerProperties::PointerType::PointerTypeMouse, + EXPECT_EQ(blink::WebPointerProperties::PointerType::Mouse, webkit_event.pointerType); EXPECT_EQ(0, webkit_event.tiltX); EXPECT_EQ(0, webkit_event.tiltY);
diff --git a/content/browser/service_worker/service_worker_cache_writer.cc b/content/browser/service_worker/service_worker_cache_writer.cc new file mode 100644 index 0000000..e934300 --- /dev/null +++ b/content/browser/service_worker/service_worker_cache_writer.cc
@@ -0,0 +1,498 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_cache_writer.h" + +#include <algorithm> +#include <string> + +#include "content/browser/appcache/appcache_response.h" +#include "content/browser/service_worker/service_worker_disk_cache.h" +#include "content/browser/service_worker/service_worker_storage.h" + +namespace { + +const size_t kCopyBufferSize = 16 * 1024; + +// Shim class used to turn always-async functions into async-or-result +// functions. See the comments below near ReadInfoHelper. +class AsyncOnlyCompletionCallbackAdaptor + : public base::RefCounted<AsyncOnlyCompletionCallbackAdaptor> { + public: + explicit AsyncOnlyCompletionCallbackAdaptor( + const net::CompletionCallback& callback) + : async_(false), result_(net::ERR_IO_PENDING), callback_(callback) {} + + void set_async(bool async) { async_ = async; } + bool async() { return async_; } + int result() { return result_; } + + void WrappedCallback(int result) { + result_ = result; + if (async_) + callback_.Run(result); + } + + private: + friend class base::RefCounted<AsyncOnlyCompletionCallbackAdaptor>; + virtual ~AsyncOnlyCompletionCallbackAdaptor() {} + + bool async_; + int result_; + net::CompletionCallback callback_; +}; + +} // namespace + +namespace content { + +int ServiceWorkerCacheWriter::DoLoop(int status) { + do { + switch (state_) { + case STATE_START: + status = DoStart(status); + break; + case STATE_READ_HEADERS_FOR_COMPARE: + status = DoReadHeadersForCompare(status); + break; + case STATE_READ_HEADERS_FOR_COMPARE_DONE: + status = DoReadHeadersForCompareDone(status); + break; + case STATE_READ_DATA_FOR_COMPARE: + status = DoReadDataForCompare(status); + break; + case STATE_READ_DATA_FOR_COMPARE_DONE: + status = DoReadDataForCompareDone(status); + break; + case STATE_READ_HEADERS_FOR_COPY: + status = DoReadHeadersForCopy(status); + break; + case STATE_READ_HEADERS_FOR_COPY_DONE: + status = DoReadHeadersForCopyDone(status); + break; + case STATE_READ_DATA_FOR_COPY: + status = DoReadDataForCopy(status); + break; + case STATE_READ_DATA_FOR_COPY_DONE: + status = DoReadDataForCopyDone(status); + break; + case STATE_WRITE_HEADERS_FOR_PASSTHROUGH: + status = DoWriteHeadersForPassthrough(status); + break; + case STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE: + status = DoWriteHeadersForPassthroughDone(status); + break; + case STATE_WRITE_DATA_FOR_PASSTHROUGH: + status = DoWriteDataForPassthrough(status); + break; + case STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE: + status = DoWriteDataForPassthroughDone(status); + break; + case STATE_WRITE_HEADERS_FOR_COPY: + status = DoWriteHeadersForCopy(status); + break; + case STATE_WRITE_HEADERS_FOR_COPY_DONE: + status = DoWriteHeadersForCopyDone(status); + break; + case STATE_WRITE_DATA_FOR_COPY: + status = DoWriteDataForCopy(status); + break; + case STATE_WRITE_DATA_FOR_COPY_DONE: + status = DoWriteDataForCopyDone(status); + break; + case STATE_DONE: + status = DoDone(status); + break; + default: + NOTREACHED() << "Unknown state in DoLoop"; + state_ = STATE_DONE; + break; + } + } while (status >= net::OK && state_ != STATE_DONE); + io_pending_ = (status == net::ERR_IO_PENDING); + return status; +} + +ServiceWorkerCacheWriter::ServiceWorkerCacheWriter( + const ResponseReaderCreator& reader_creator, + const ResponseWriterCreator& writer_creator) + : state_(STATE_START), + io_pending_(false), + comparing_(false), + did_replace_(false), + reader_creator_(reader_creator), + writer_creator_(writer_creator), + weak_factory_(this) {} + +ServiceWorkerCacheWriter::~ServiceWorkerCacheWriter() {} + +net::Error ServiceWorkerCacheWriter::MaybeWriteHeaders( + HttpResponseInfoIOBuffer* headers, + const OnWriteCompleteCallback& callback) { + DCHECK(!io_pending_); + + headers_to_write_ = headers; + pending_callback_ = callback; + DCHECK_EQ(state_, STATE_START); + int result = DoLoop(net::OK); + + // Synchronous errors and successes always go to STATE_DONE. + if (result != net::ERR_IO_PENDING) + DCHECK_EQ(state_, STATE_DONE); + + // ERR_IO_PENDING has to have one of the STATE_*_DONE states as the next state + // (not STATE_DONE itself). + if (result == net::ERR_IO_PENDING) { + DCHECK(state_ == STATE_READ_HEADERS_FOR_COMPARE_DONE || + state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE || + state_ == STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE) + << "Unexpected state: " << state_; + io_pending_ = true; + } + + return result >= 0 ? net::OK : static_cast<net::Error>(result); +} + +net::Error ServiceWorkerCacheWriter::MaybeWriteData( + net::IOBuffer* buf, + size_t buf_size, + const OnWriteCompleteCallback& callback) { + DCHECK(!io_pending_); + + data_to_write_ = buf; + len_to_write_ = buf_size; + pending_callback_ = callback; + + if (comparing_) + state_ = STATE_READ_DATA_FOR_COMPARE; + else + state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH; + + int result = DoLoop(net::OK); + + // Synchronous completions are always STATE_DONE. + if (result != net::ERR_IO_PENDING) + DCHECK_EQ(state_, STATE_DONE); + + // Asynchronous completion means the state machine must be waiting in one of + // the Done states for an IO operation to complete: + if (result == net::ERR_IO_PENDING) { + // Note that STATE_READ_HEADERS_FOR_COMPARE_DONE is excluded because the + // headers are compared in MaybeWriteHeaders, not here, and + // STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write + // is done by MaybeWriteHeaders. + DCHECK(state_ == STATE_READ_DATA_FOR_COMPARE_DONE || + state_ == STATE_READ_HEADERS_FOR_COPY_DONE || + state_ == STATE_READ_DATA_FOR_COPY_DONE || + state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE || + state_ == STATE_WRITE_DATA_FOR_COPY_DONE || + state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE) + << "Unexpected state: " << state_; + } + + return result >= 0 ? net::OK : static_cast<net::Error>(result); +} + +int ServiceWorkerCacheWriter::DoStart(int result) { + bytes_written_ = 0; + compare_reader_ = reader_creator_.Run(); + if (compare_reader_.get()) { + state_ = STATE_READ_HEADERS_FOR_COMPARE; + comparing_ = true; + } else { + // No existing reader, just write the headers back directly. + state_ = STATE_WRITE_HEADERS_FOR_PASSTHROUGH; + comparing_ = false; + } + return net::OK; +} + +int ServiceWorkerCacheWriter::DoReadHeadersForCompare(int result) { + DCHECK(headers_to_write_); + + headers_to_read_ = new HttpResponseInfoIOBuffer; + state_ = STATE_READ_HEADERS_FOR_COMPARE_DONE; + return ReadInfoHelper(compare_reader_, headers_to_read_.get()); +} + +int ServiceWorkerCacheWriter::DoReadHeadersForCompareDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + cached_length_ = headers_to_read_->response_data_size; + bytes_compared_ = 0; + state_ = STATE_DONE; + return net::OK; +} + +int ServiceWorkerCacheWriter::DoReadDataForCompare(int result) { + DCHECK(data_to_write_); + + data_to_read_ = new net::IOBuffer(len_to_write_); + len_to_read_ = len_to_write_; + state_ = STATE_READ_DATA_FOR_COMPARE_DONE; + compare_offset_ = 0; + // If this was an EOF, don't issue a read. + if (len_to_write_ > 0) + result = ReadDataHelper(compare_reader_, data_to_read_.get(), len_to_read_); + return result; +} + +int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) { + DCHECK(data_to_read_); + DCHECK(data_to_write_); + DCHECK_EQ(len_to_read_, len_to_write_); + DCHECK_LE(result + compare_offset_, static_cast<size_t>(len_to_write_)); + + if (result < 0) { + state_ = STATE_DONE; + return result; + } + + // Premature EOF while reading the service worker script cache data to + // compare. Fail the comparison. + if (result == 0 && len_to_write_ != 0) { + comparing_ = false; + state_ = STATE_READ_HEADERS_FOR_COPY; + return net::OK; + } + + // Compare the data from the ServiceWorker script cache to the data from the + // network. + if (memcmp(data_to_read_->data(), data_to_write_->data() + compare_offset_, + result)) { + // Data mismatched. This method already validated that all the bytes through + // |bytes_compared_| were identical, so copy the first |bytes_compared_| + // over, then start writing network data back after the changed point. + comparing_ = false; + state_ = STATE_READ_HEADERS_FOR_COPY; + return net::OK; + } + + compare_offset_ += result; + + // This is a little bit tricky. It is possible that not enough data was read + // to finish comparing the entire block of data from the network (which is + // kept in len_to_write_), so this method may need to issue another read and + // return to this state. + // + // Compare isn't complete yet. Issue another read for the remaining data. Note + // that this reuses the same IOBuffer. + if (compare_offset_ < static_cast<size_t>(len_to_read_)) { + state_ = STATE_READ_DATA_FOR_COMPARE_DONE; + return ReadDataHelper(compare_reader_, data_to_read_.get(), + len_to_read_ - compare_offset_); + } + + // Cached entry is longer than the network entry but the prefix matches. Copy + // just the prefix. + if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) { + comparing_ = false; + state_ = STATE_READ_HEADERS_FOR_COPY; + return net::OK; + } + + // bytes_compared_ only gets incremented when a full block is compared, to + // avoid having to use only parts of the buffered network data. + bytes_compared_ += result; + state_ = STATE_DONE; + return net::OK; +} + +int ServiceWorkerCacheWriter::DoReadHeadersForCopy(int result) { + bytes_copied_ = 0; + copy_reader_ = reader_creator_.Run(); + headers_to_read_ = new HttpResponseInfoIOBuffer; + data_to_copy_ = new net::IOBuffer(kCopyBufferSize); + state_ = STATE_READ_HEADERS_FOR_COPY_DONE; + return ReadInfoHelper(copy_reader_, headers_to_read_.get()); +} + +int ServiceWorkerCacheWriter::DoReadHeadersForCopyDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + state_ = STATE_WRITE_HEADERS_FOR_COPY; + return net::OK; +} + +// Write the just-read headers back to the cache. +// Note that this method must create |writer_|, since the only paths to this +// state never create a writer. +// Also note that this *discards* the read headers and replaces them with the +// net headers. +int ServiceWorkerCacheWriter::DoWriteHeadersForCopy(int result) { + DCHECK(!writer_); + writer_ = writer_creator_.Run(); + state_ = STATE_WRITE_HEADERS_FOR_COPY_DONE; + return WriteInfoHelper(writer_, headers_to_write_.get()); +} + +int ServiceWorkerCacheWriter::DoWriteHeadersForCopyDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + state_ = STATE_READ_DATA_FOR_COPY; + return net::OK; +} + +int ServiceWorkerCacheWriter::DoReadDataForCopy(int result) { + size_t to_read = std::min(kCopyBufferSize, bytes_compared_ - bytes_copied_); + // At this point, all compared bytes have been read. Currently + // |data_to_write_| and |len_to_write_| hold the chunk of network input that + // caused the comparison failure, so those need to be written back and this + // object needs to go into passthrough mode. + if (to_read == 0) { + state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH; + return net::OK; + } + state_ = STATE_READ_DATA_FOR_COPY_DONE; + return ReadDataHelper(copy_reader_, data_to_copy_.get(), to_read); +} + +int ServiceWorkerCacheWriter::DoReadDataForCopyDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + state_ = STATE_WRITE_DATA_FOR_COPY; + return result; +} + +int ServiceWorkerCacheWriter::DoWriteDataForCopy(int result) { + state_ = STATE_WRITE_DATA_FOR_COPY_DONE; + DCHECK_GT(result, 0); + return WriteDataHelper(writer_, data_to_copy_.get(), result); +} + +int ServiceWorkerCacheWriter::DoWriteDataForCopyDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + bytes_written_ += result; + bytes_copied_ += result; + state_ = STATE_READ_DATA_FOR_COPY; + return result; +} + +int ServiceWorkerCacheWriter::DoWriteHeadersForPassthrough(int result) { + writer_ = writer_creator_.Run(); + state_ = STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE; + return WriteInfoHelper(writer_, headers_to_write_.get()); +} + +int ServiceWorkerCacheWriter::DoWriteHeadersForPassthroughDone(int result) { + state_ = STATE_DONE; + return net::OK; +} + +int ServiceWorkerCacheWriter::DoWriteDataForPassthrough(int result) { + state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE; + if (len_to_write_ > 0) + result = WriteDataHelper(writer_, data_to_write_.get(), len_to_write_); + return result; +} + +int ServiceWorkerCacheWriter::DoWriteDataForPassthroughDone(int result) { + if (result < 0) { + state_ = STATE_DONE; + return result; + } + bytes_written_ += result; + state_ = STATE_DONE; + return net::OK; +} + +int ServiceWorkerCacheWriter::DoDone(int result) { + state_ = STATE_DONE; + return net::OK; +} + +// These helpers adapt the AppCache "always use the callback" pattern to the +// //net "only use the callback for async" pattern using +// AsyncCompletionCallbackAdaptor. +// +// Specifically, these methods return result codes directly for synchronous +// completions, and only run their callback (which is AsyncDoLoop) for +// asynchronous completions. + +int ServiceWorkerCacheWriter::ReadInfoHelper( + const scoped_ptr<ServiceWorkerResponseReader>& reader, + HttpResponseInfoIOBuffer* buf) { + net::CompletionCallback run_callback = base::Bind( + &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr()); + scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor( + new AsyncOnlyCompletionCallbackAdaptor(run_callback)); + reader->ReadInfo( + buf, base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback, + adaptor)); + adaptor->set_async(true); + return adaptor->result(); +} + +int ServiceWorkerCacheWriter::ReadDataHelper( + const scoped_ptr<ServiceWorkerResponseReader>& reader, + net::IOBuffer* buf, + int buf_len) { + net::CompletionCallback run_callback = base::Bind( + &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr()); + scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor( + new AsyncOnlyCompletionCallbackAdaptor(run_callback)); + reader->ReadData( + buf, buf_len, + base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback, + adaptor)); + adaptor->set_async(true); + return adaptor->result(); +} + +int ServiceWorkerCacheWriter::WriteInfoHelper( + const scoped_ptr<ServiceWorkerResponseWriter>& writer, + HttpResponseInfoIOBuffer* buf) { + did_replace_ = true; + net::CompletionCallback run_callback = base::Bind( + &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr()); + scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor( + new AsyncOnlyCompletionCallbackAdaptor(run_callback)); + writer->WriteInfo( + buf, base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback, + adaptor)); + adaptor->set_async(true); + return adaptor->result(); +} + +int ServiceWorkerCacheWriter::WriteDataHelper( + const scoped_ptr<ServiceWorkerResponseWriter>& writer, + net::IOBuffer* buf, + int buf_len) { + net::CompletionCallback run_callback = base::Bind( + &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr()); + scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor( + new AsyncOnlyCompletionCallbackAdaptor(run_callback)); + writer->WriteData( + buf, buf_len, + base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback, + adaptor)); + adaptor->set_async(true); + return adaptor->result(); +} + +void ServiceWorkerCacheWriter::AsyncDoLoop(int result) { + result = DoLoop(result); + // If the result is ERR_IO_PENDING, the pending callback will be run by a + // later invocation of AsyncDoLoop. + if (result != net::ERR_IO_PENDING) { + OnWriteCompleteCallback callback = pending_callback_; + pending_callback_.Reset(); + net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result); + io_pending_ = false; + callback.Run(error); + } +} + +} // namespace content
diff --git a/content/browser/service_worker/service_worker_cache_writer.h b/content/browser/service_worker/service_worker_cache_writer.h new file mode 100644 index 0000000..dde71a6 --- /dev/null +++ b/content/browser/service_worker/service_worker_cache_writer.h
@@ -0,0 +1,230 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ + +#include <map> +#include <set> + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" + +namespace content { + +struct HttpResponseInfoIOBuffer; +class ServiceWorkerCacheWriterCore; +class ServiceWorkerResponseReader; +class ServiceWorkerResponseWriter; +class ServiceWorkerStorage; + +// This class is responsible for possibly updating the ServiceWorker script +// cache for an installed ServiceWorker main script. If there is no existing +// cache entry, this class always writes supplied data back to the cache; if +// there is an existing cache entry, this class only writes supplied data back +// if there is a cache mismatch. +// +// Note that writes done by this class cannot be "short" - ie, if they succeed, +// they always write all the supplied data back. Therefore completions are +// signalled with net::Error without a count of bytes written. +// +// This class's behavior is modelled as a state machine; see the DoLoop function +// for comments about this. +class CONTENT_EXPORT ServiceWorkerCacheWriter { + public: + using OnWriteCompleteCallback = base::Callback<void(net::Error)>; + + // The types for the factory functions passed into the constructor. These are + // responsible for creating readers from the existing cache entry and writers + // to the new cache entry when called. These are passed in as factories + // instead of passing readers and writers in directly to avoid creating + // writers to entries that won't be updated, and because this class may need + // multiple readers internally. + using ResponseReaderCreator = + base::Callback<scoped_ptr<ServiceWorkerResponseReader>(void)>; + using ResponseWriterCreator = + base::Callback<scoped_ptr<ServiceWorkerResponseWriter>(void)>; + + // The existing reader may be null, in which case this instance will + // unconditionally write back data supplied to |MaybeWriteHeaders| and + // |MaybeWriteData|. + ServiceWorkerCacheWriter(const ResponseReaderCreator& reader_creator, + const ResponseWriterCreator& writer_creator); + + ~ServiceWorkerCacheWriter(); + + // Writes the supplied |headers| back to the cache. Returns ERR_IO_PENDING if + // the write will complete asynchronously, in which case |callback| will be + // called when it completes. Otherwise, returns a code other than + // ERR_IO_PENDING and does not invoke |callback|. Note that this method will + // not necessarily write data back to the cache if the incoming data is + // equivalent to the existing cached data. See the source of this function for + // details about how this function drives the state machine. + net::Error MaybeWriteHeaders(HttpResponseInfoIOBuffer* headers, + const OnWriteCompleteCallback& callback); + + // Writes the supplied body data |data| back to the cache. Returns + // ERR_IO_PENDING if the write will complete asynchronously, in which case + // |callback| will be called when it completes. Otherwise, returns a code + // other than ERR_IO_PENDING and does not invoke |callback|. Note that this + // method will not necessarily write data back to the cache if the incoming + // data is equivalent to the existing cached data. See the source of this + // function for details about how this function drives the state machine. + net::Error MaybeWriteData(net::IOBuffer* buf, + size_t buf_size, + const OnWriteCompleteCallback& callback); + + // Returns a count of bytes written back to the cache. + size_t bytes_written() const { return bytes_written_; } + bool did_replace() const { return did_replace_; } + + private: + // States for the state machine. + // + // The state machine flows roughly like this: if there is no existing cache + // entry, incoming headers and data are written directly back to the cache + // ("passthrough mode", the PASSTHROUGH states). If there is an existing cache + // entry, incoming headers and data are compared to the existing cache entry + // ("compare mode", the COMPARE states); if at any point the incoming + // headers/data are not equal to the cached headers/data, this class copies + // the cached data up to the point where the incoming data and the cached data + // diverged ("copy mode", the COPY states), then switches to "passthrough + // mode" to write the remainder of the incoming data. The overall effect is to + // avoid rewriting the cache entry if the incoming data is identical to the + // cached data. + // + // Note that after a call to MaybeWriteHeaders or MaybeWriteData completes, + // the machine is always in STATE_DONE, indicating that the call is finished; + // those methods are responsible for setting a new initial state. + enum State { + STATE_START, + // Control flows linearly through these four states, then loops from + // READ_DATA_FOR_COMPARE_DONE to READ_DATA_FOR_COMPARE, or exits to + // READ_HEADERS_FOR_COPY. + STATE_READ_HEADERS_FOR_COMPARE, + STATE_READ_HEADERS_FOR_COMPARE_DONE, + STATE_READ_DATA_FOR_COMPARE, + STATE_READ_DATA_FOR_COMPARE_DONE, + + // Control flows linearly through these states, with each pass from + // READ_DATA_FOR_COPY to WRITE_DATA_FOR_COPY_DONE copying one block of data + // at a time. Control loops from WRITE_DATA_FOR_COPY_DONE back to + // READ_DATA_FOR_COPY if there is more data to copy, or exits to + // WRITE_DATA_FOR_PASSTHROUGH. + STATE_READ_HEADERS_FOR_COPY, + STATE_READ_HEADERS_FOR_COPY_DONE, + STATE_WRITE_HEADERS_FOR_COPY, + STATE_WRITE_HEADERS_FOR_COPY_DONE, + STATE_READ_DATA_FOR_COPY, + STATE_READ_DATA_FOR_COPY_DONE, + STATE_WRITE_DATA_FOR_COPY, + STATE_WRITE_DATA_FOR_COPY_DONE, + + // Control flows linearly through these states, with a loop between + // WRITE_DATA_FOR_PASSTHROUGH and WRITE_DATA_FOR_PASSTHROUGH_DONE. + STATE_WRITE_HEADERS_FOR_PASSTHROUGH, + STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE, + STATE_WRITE_DATA_FOR_PASSTHROUGH, + STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE, + + // This state means "done with the current call; ready for another one." + STATE_DONE, + }; + + // Drives this class's state machine. This function steps the state machine + // until one of: + // a) One of the state functions returns an error + // b) The state machine reaches STATE_DONE + // A successful value (net::OK or greater) indicates that the requested + // operation completed synchronously. A return value of ERR_IO_PENDING + // indicates that some step had to submit asynchronous IO for later + // completion, and the state machine will resume running (via AsyncDoLoop) + // when that asynchronous IO completes. Any other return value indicates that + // the requested operation failed synchronously. + int DoLoop(int result); + + // State handlers. See function comments in the corresponding source file for + // details on these. + int DoStart(int result); + int DoReadHeadersForCompare(int result); + int DoReadHeadersForCompareDone(int result); + int DoReadDataForCompare(int result); + int DoReadDataForCompareDone(int result); + int DoReadHeadersForCopy(int result); + int DoReadHeadersForCopyDone(int result); + int DoWriteHeadersForCopy(int result); + int DoWriteHeadersForCopyDone(int result); + int DoReadDataForCopy(int result); + int DoReadDataForCopyDone(int result); + int DoWriteDataForCopy(int result); + int DoWriteDataForCopyDone(int result); + int DoWriteHeadersForPassthrough(int result); + int DoWriteHeadersForPassthroughDone(int result); + int DoWriteDataForPassthrough(int result); + int DoWriteDataForPassthroughDone(int result); + int DoDone(int result); + + // Wrappers for asynchronous calls. These are responsible for scheduling a + // callback to drive the state machine if needed. These either: + // a) Return ERR_IO_PENDING, and schedule a callback to run the state + // machine's Run() later, or + // b) Return some other value and do not schedule a callback. + int ReadInfoHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, + HttpResponseInfoIOBuffer* buf); + int ReadDataHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, + net::IOBuffer* buf, + int buf_len); + int WriteInfoHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, + HttpResponseInfoIOBuffer* buf); + int WriteDataHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, + net::IOBuffer* buf, + int buf_len); + + // Callback used by the above helpers for their IO operations. This is only + // run when those IO operations complete asynchronously, in which case it + // invokes the synchronous DoLoop function and runs the client callback (the + // one passed into MaybeWriteData/MaybeWriteHeaders) if that invocation + // of DoLoop completes synchronously. + void AsyncDoLoop(int result); + + State state_; + // Note that this variable is only used for assertions; it reflects "state != + // DONE && not in synchronous DoLoop". + bool io_pending_; + bool comparing_; + + scoped_refptr<HttpResponseInfoIOBuffer> headers_to_read_; + scoped_refptr<HttpResponseInfoIOBuffer> headers_to_write_; + scoped_refptr<net::IOBuffer> data_to_read_; + int len_to_read_; + scoped_refptr<net::IOBuffer> data_to_copy_; + scoped_refptr<net::IOBuffer> data_to_write_; + int len_to_write_; + OnWriteCompleteCallback pending_callback_; + + size_t cached_length_; + + size_t bytes_compared_; + size_t bytes_copied_; + size_t bytes_written_; + + bool did_replace_; + + size_t compare_offset_; + + ResponseReaderCreator reader_creator_; + ResponseWriterCreator writer_creator_; + scoped_ptr<ServiceWorkerResponseReader> compare_reader_; + scoped_ptr<ServiceWorkerResponseReader> copy_reader_; + scoped_ptr<ServiceWorkerResponseWriter> writer_; + base::WeakPtrFactory<ServiceWorkerCacheWriter> weak_factory_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_
diff --git a/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/content/browser/service_worker/service_worker_cache_writer_unittest.cc new file mode 100644 index 0000000..c58b57b5 --- /dev/null +++ b/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -0,0 +1,697 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_cache_writer.h" + +#include <list> +#include <queue> +#include <string> + +#include "base/stl_util.h" +#include "content/browser/service_worker/service_worker_disk_cache.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +// A test implementation of ServiceWorkerResponseReader. +// +// This class exposes the ability to expect reads (see ExpectRead*() below). +// Each call to ReadInfo() or ReadData() consumes another expected read, in the +// order those reads were expected, so: +// reader->ExpectReadInfoOk(5, false); +// reader->ExpectReadDataOk("abcdef", false); +// reader->ExpectReadDataOk("ghijkl", false); +// Expects these calls, in this order: +// reader->ReadInfo(...); // reader writes 5 into +// // |info_buf->response_data_size| +// reader->ReadData(...); // reader writes "abcdef" into |buf| +// reader->ReadData(...); // reader writes "ghijkl" into |buf| +// If an unexpected call happens, this class DCHECKs. +// If an expected read is marked "async", it will not complete immediately, but +// must be completed by the test using CompletePendingRead(). +// These is a convenience method AllExpectedReadsDone() which returns whether +// there are any expected reads that have not yet happened. +class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader { + public: + MockServiceWorkerResponseReader() : ServiceWorkerResponseReader(0, nullptr) {} + ~MockServiceWorkerResponseReader() override {} + + // ServiceWorkerResponseReader overrides + void ReadInfo(HttpResponseInfoIOBuffer* info_buf, + const net::CompletionCallback& callback) override; + void ReadData(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) override; + + // Test helpers. ExpectReadInfo() and ExpectReadData() give precise control + // over both the data to be written and the result to return. + // ExpectReadInfoOk() and ExpectReadDataOk() are convenience functions for + // expecting successful reads, which always have their length as their result. + + // Expect a call to ReadInfo() on this reader. For these functions, |len| will + // be used as |response_data_size|, not as the length of this particular read. + void ExpectReadInfo(size_t len, bool async, int result); + void ExpectReadInfoOk(size_t len, bool async); + + // Expect a call to ReadData() on this reader. For these functions, |len| is + // the length of the data to be written back; in ExpectReadDataOk(), |len| is + // implicitly the length of |data|. + void ExpectReadData(const char* data, size_t len, bool async, int result); + void ExpectReadDataOk(const std::string& data, bool async); + + // Complete a pending async read. It is an error to call this function without + // a pending async read (ie, a previous call to ReadInfo() or ReadData() + // having not run its callback yet). + void CompletePendingRead(); + + // Returns whether all expected reads have occurred. + bool AllExpectedReadsDone() { return expected_reads_.size() == 0; } + + private: + struct ExpectedRead { + ExpectedRead(size_t len, bool async, int result) + : data(nullptr), len(len), info(true), async(async), result(result) {} + ExpectedRead(const char* data, size_t len, bool async, int result) + : data(data), len(len), info(false), async(async), result(result) {} + const char* data; + size_t len; + bool info; + bool async; + int result; + }; + + std::queue<ExpectedRead> expected_reads_; + scoped_refptr<net::IOBuffer> pending_buffer_; + size_t pending_buffer_len_; + scoped_refptr<HttpResponseInfoIOBuffer> pending_info_; + net::CompletionCallback pending_callback_; +}; + +void MockServiceWorkerResponseReader::ReadInfo( + HttpResponseInfoIOBuffer* info_buf, + const net::CompletionCallback& callback) { + DCHECK(!expected_reads_.empty()); + ExpectedRead expected = expected_reads_.front(); + EXPECT_TRUE(expected.info); + if (expected.async) { + pending_info_ = info_buf; + pending_callback_ = callback; + } else { + expected_reads_.pop(); + info_buf->response_data_size = expected.len; + callback.Run(expected.result); + } +} + +void MockServiceWorkerResponseReader::ReadData( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) { + DCHECK(!expected_reads_.empty()); + ExpectedRead expected = expected_reads_.front(); + EXPECT_FALSE(expected.info); + if (expected.async) { + pending_callback_ = callback; + pending_buffer_ = buf; + pending_buffer_len_ = static_cast<size_t>(buf_len); + } else { + expected_reads_.pop(); + if (expected.len > 0) { + size_t to_read = std::min(static_cast<size_t>(buf_len), expected.len); + memcpy(buf->data(), expected.data, to_read); + } + callback.Run(expected.result); + } +} + +void MockServiceWorkerResponseReader::ExpectReadInfo(size_t len, + bool async, + int result) { + expected_reads_.push(ExpectedRead(len, async, result)); +} + +void MockServiceWorkerResponseReader::ExpectReadInfoOk(size_t len, bool async) { + expected_reads_.push(ExpectedRead(len, async, len)); +} + +void MockServiceWorkerResponseReader::ExpectReadData(const char* data, + size_t len, + bool async, + int result) { + expected_reads_.push(ExpectedRead(data, len, async, result)); +} + +void MockServiceWorkerResponseReader::ExpectReadDataOk(const std::string& data, + bool async) { + expected_reads_.push( + ExpectedRead(data.data(), data.size(), async, data.size())); +} + +void MockServiceWorkerResponseReader::CompletePendingRead() { + DCHECK(!expected_reads_.empty()); + ExpectedRead expected = expected_reads_.front(); + expected_reads_.pop(); + EXPECT_TRUE(expected.async); + if (expected.info) { + pending_info_->response_data_size = expected.len; + } else { + size_t to_read = std::min(pending_buffer_len_, expected.len); + if (to_read > 0) + memcpy(pending_buffer_->data(), expected.data, to_read); + } + pending_info_ = nullptr; + pending_buffer_ = nullptr; + net::CompletionCallback callback = pending_callback_; + pending_callback_.Reset(); + callback.Run(expected.result); +} + +// A test implementation of ServiceWorkerResponseWriter. +// +// This class exposes the ability to expect writes (see ExpectWrite*Ok() below). +// Each write to this class via WriteInfo() or WriteData() consumes another +// expected write, in the order they were added, so: +// writer->ExpectWriteInfoOk(5, false); +// writer->ExpectWriteDataOk(6, false); +// writer->ExpectWriteDataOk(6, false); +// Expects these calls, in this order: +// writer->WriteInfo(...); // checks that |buf->response_data_size| == 5 +// writer->WriteData(...); // checks that 6 bytes are being written +// writer->WriteData(...); // checks that another 6 bytes are being written +// If this class receives an unexpected call to WriteInfo() or WriteData(), it +// DCHECKs. +// Expected writes marked async do not complete synchronously, but rather return +// without running their callback and need to be completed with +// CompletePendingWrite(). +// A convenience method AllExpectedWritesDone() is exposed so tests can ensure +// that all expected writes have been consumed by matching calls to WriteInfo() +// or WriteData(). +class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter { + public: + MockServiceWorkerResponseWriter() + : ServiceWorkerResponseWriter(0, nullptr), + info_written_(0), + data_written_(0) {} + ~MockServiceWorkerResponseWriter() override {} + + // ServiceWorkerResponseWriter overrides + void WriteInfo(HttpResponseInfoIOBuffer* info_buf, + const net::CompletionCallback& callback) override; + void WriteData(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) override; + + // Enqueue expected writes. + void ExpectWriteInfoOk(size_t len, bool async); + void ExpectWriteDataOk(size_t len, bool async); + + // Complete a pending asynchronous write. This method DCHECKs unless there is + // a pending write (a write for which WriteInfo() or WriteData() has been + // called but the callback has not yet been run). + void CompletePendingWrite(); + + // Returns whether all expected reads have been consumed. + bool AllExpectedWritesDone() { return expected_writes_.size() == 0; } + + private: + struct ExpectedWrite { + ExpectedWrite(bool is_info, size_t length, bool async, int result) + : is_info(is_info), length(length), async(async), result(result) {} + bool is_info; + size_t length; + bool async; + int result; + }; + + std::queue<ExpectedWrite> expected_writes_; + + size_t info_written_; + size_t data_written_; + + net::CompletionCallback pending_callback_; +}; + +void MockServiceWorkerResponseWriter::WriteInfo( + HttpResponseInfoIOBuffer* info_buf, + const net::CompletionCallback& callback) { + DCHECK(!expected_writes_.empty()); + ExpectedWrite write = expected_writes_.front(); + EXPECT_TRUE(write.is_info); + EXPECT_EQ(write.length, static_cast<size_t>(info_buf->response_data_size)); + info_written_ += info_buf->response_data_size; + if (!write.async) { + expected_writes_.pop(); + callback.Run(write.result); + } else { + pending_callback_ = callback; + } +} + +void MockServiceWorkerResponseWriter::WriteData( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) { + DCHECK(!expected_writes_.empty()); + ExpectedWrite write = expected_writes_.front(); + EXPECT_FALSE(write.is_info); + EXPECT_EQ(write.length, static_cast<size_t>(buf_len)); + data_written_ += buf_len; + if (!write.async) { + expected_writes_.pop(); + callback.Run(write.result); + } else { + pending_callback_ = callback; + } +} + +void MockServiceWorkerResponseWriter::ExpectWriteInfoOk(size_t length, + bool async) { + ExpectedWrite expected(true, length, async, length); + expected_writes_.push(expected); +} + +void MockServiceWorkerResponseWriter::ExpectWriteDataOk(size_t length, + bool async) { + ExpectedWrite expected(false, length, async, length); + expected_writes_.push(expected); +} + +void MockServiceWorkerResponseWriter::CompletePendingWrite() { + DCHECK(!expected_writes_.empty()); + ExpectedWrite write = expected_writes_.front(); + DCHECK(write.async); + expected_writes_.pop(); + pending_callback_.Run(write.result); +} + +class ServiceWorkerCacheWriterTest : public ::testing::Test { + public: + ServiceWorkerCacheWriterTest() + : readers_deleter_(&readers_), writers_deleter_(&writers_) {} + + void SetUp() override { + ::testing::Test::SetUp(); + cache_writer_.reset(new ServiceWorkerCacheWriter( + base::Bind(&ServiceWorkerCacheWriterTest::CreateReader, + base::Unretained(this)), + base::Bind(&ServiceWorkerCacheWriterTest::CreateWriter, + base::Unretained(this)))); + write_complete_ = false; + } + + MockServiceWorkerResponseReader* ExpectReader() { + scoped_ptr<MockServiceWorkerResponseReader> reader( + new MockServiceWorkerResponseReader); + MockServiceWorkerResponseReader* borrowed_reader = reader.get(); + readers_.push_back(reader.release()); // give ownership to |readers_| + return borrowed_reader; + } + + MockServiceWorkerResponseWriter* ExpectWriter() { + scoped_ptr<MockServiceWorkerResponseWriter> writer( + new MockServiceWorkerResponseWriter); + MockServiceWorkerResponseWriter* borrowed_writer = writer.get(); + writers_.push_back(writer.release()); // give ownership to |writers_| + return borrowed_writer; + } + + protected: + // TODO(ellyjones): when unique_ptr<> is allowed, make these instead: + // std::list<unique_ptr<...>> + // Right now, these cannot use scoped_ptr. + // Their elements are deleted by the STLElementDeleters below when this object + // goes out of scope. + std::list<MockServiceWorkerResponseReader*> readers_; + std::list<MockServiceWorkerResponseWriter*> writers_; + STLElementDeleter<std::list<MockServiceWorkerResponseReader*>> + readers_deleter_; + STLElementDeleter<std::list<MockServiceWorkerResponseWriter*>> + writers_deleter_; + scoped_ptr<ServiceWorkerCacheWriter> cache_writer_; + bool write_complete_; + net::Error last_error_; + + scoped_ptr<ServiceWorkerResponseReader> CreateReader() { + if (readers_.empty()) + return make_scoped_ptr<ServiceWorkerResponseReader>(nullptr); + scoped_ptr<ServiceWorkerResponseReader> reader(readers_.front()); + readers_.pop_front(); + return reader.Pass(); + } + scoped_ptr<ServiceWorkerResponseWriter> CreateWriter() { + if (writers_.empty()) + return make_scoped_ptr<ServiceWorkerResponseWriter>(nullptr); + scoped_ptr<ServiceWorkerResponseWriter> writer(writers_.front()); + writers_.pop_front(); + return writer.Pass(); + } + + ServiceWorkerCacheWriter::OnWriteCompleteCallback CreateWriteCallback() { + return base::Bind(&ServiceWorkerCacheWriterTest::OnWriteComplete, + base::Unretained(this)); + } + + void OnWriteComplete(net::Error error) { + write_complete_ = true; + last_error_ = error; + } + + net::Error WriteHeaders(size_t len) { + scoped_refptr<HttpResponseInfoIOBuffer> buf(new HttpResponseInfoIOBuffer); + buf->response_data_size = len; + return cache_writer_->MaybeWriteHeaders(buf.get(), CreateWriteCallback()); + } + + net::Error WriteData(const std::string& data) { + scoped_refptr<net::IOBuffer> buf = new net::StringIOBuffer(data); + return cache_writer_->MaybeWriteData(buf.get(), data.size(), + CreateWriteCallback()); + } +}; + +// Passthrough tests: +// In these tests, the ServiceWorkerCacheWriter under test has no existing +// reader, since no calls to ExpectReader() have been made; this means that +// there is no existing cached response and the incoming data is written back to +// the cache directly. + +TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) { + const size_t kHeaderSize = 16; + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + writer->ExpectWriteInfoOk(kHeaderSize, false); + + net::Error error = WriteHeaders(kHeaderSize); + EXPECT_EQ(net::OK, error); + EXPECT_FALSE(write_complete_); + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) { + size_t kHeaderSize = 16; + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + writer->ExpectWriteInfoOk(kHeaderSize, true); + + net::Error error = WriteHeaders(kHeaderSize); + EXPECT_EQ(net::ERR_IO_PENDING, error); + EXPECT_FALSE(write_complete_); + writer->CompletePendingWrite(); + EXPECT_TRUE(write_complete_); + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) { + const std::string data1 = "abcdef"; + const std::string data2 = "ghijklmno"; + size_t response_size = data1.size() + data2.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + writer->ExpectWriteInfoOk(response_size, false); + writer->ExpectWriteDataOk(data1.size(), false); + writer->ExpectWriteDataOk(data2.size(), false); + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::OK, error); + + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + + error = WriteData(data2); + EXPECT_EQ(net::OK, error); + EXPECT_TRUE(writer->AllExpectedWritesDone()); +} + +TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) { + const std::string data1 = "abcdef"; + const std::string data2 = "ghijklmno"; + size_t response_size = data1.size() + data2.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + writer->ExpectWriteInfoOk(response_size, false); + writer->ExpectWriteDataOk(data1.size(), true); + writer->ExpectWriteDataOk(data2.size(), true); + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::OK, error); + + error = WriteData(data1); + EXPECT_EQ(net::ERR_IO_PENDING, error); + writer->CompletePendingWrite(); + EXPECT_TRUE(write_complete_); + + write_complete_ = false; + error = WriteData(data2); + EXPECT_EQ(net::ERR_IO_PENDING, error); + writer->CompletePendingWrite(); + EXPECT_TRUE(write_complete_); + EXPECT_TRUE(writer->AllExpectedWritesDone()); +} + +// Comparison tests: +// For the Compare* tests below, the ServiceWorkerCacheWriter under test has a +// reader for an existing cached response, so it will compare the response being +// written to it against the existing cached response. + +TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) { + size_t response_size = 3; + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + MockServiceWorkerResponseReader* reader = ExpectReader(); + + reader->ExpectReadInfoOk(response_size, false); + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::OK, error); + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_TRUE(reader->AllExpectedReadsDone()); +} + +TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) { + const std::string data1 = "abcdef"; + size_t response_size = data1.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + MockServiceWorkerResponseReader* reader = ExpectReader(); + + reader->ExpectReadInfoOk(response_size, false); + reader->ExpectReadDataOk(data1, false); + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::OK, error); + + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_TRUE(reader->AllExpectedReadsDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) { + const size_t kHeaderSize = 16; + const std::string& data1 = "abcdef"; + const std::string& cache_data2 = "ghi"; + const std::string& cache_data3 = "j"; + const std::string& cache_data4 = "kl"; + const std::string& net_data2 = "ghijkl"; + const std::string& data5 = "mnopqrst"; + + MockServiceWorkerResponseReader* reader = ExpectReader(); + reader->ExpectReadInfo(kHeaderSize, false, kHeaderSize); + reader->ExpectReadDataOk(data1, false); + reader->ExpectReadDataOk(cache_data2, false); + reader->ExpectReadDataOk(cache_data3, false); + reader->ExpectReadDataOk(cache_data4, false); + reader->ExpectReadDataOk(data5, false); + + net::Error error = WriteHeaders(kHeaderSize); + EXPECT_EQ(net::OK, error); + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + error = WriteData(net_data2); + EXPECT_EQ(net::OK, error); + error = WriteData(data5); + EXPECT_EQ(net::OK, error); + EXPECT_TRUE(reader->AllExpectedReadsDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) { + const std::string data1 = "abcdef"; + size_t response_size = data1.size(); + + MockServiceWorkerResponseReader* reader = ExpectReader(); + + reader->ExpectReadInfoOk(response_size, true); + reader->ExpectReadDataOk(data1, true); + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::ERR_IO_PENDING, error); + reader->CompletePendingRead(); + + error = WriteData(data1); + EXPECT_EQ(net::ERR_IO_PENDING, error); + reader->CompletePendingRead(); + + EXPECT_TRUE(reader->AllExpectedReadsDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) { + const std::string expected_data[] = { + "abcdef", "ghijkl", "mnopqr", "stuvwxyz", + }; + size_t response_size = 0; + for (size_t i = 0; i < arraysize(expected_data); ++i) + response_size += expected_data[i].size(); + + MockServiceWorkerResponseReader* reader = ExpectReader(); + + reader->ExpectReadInfoOk(response_size, true); + for (size_t i = 0; i < arraysize(expected_data); ++i) { + reader->ExpectReadDataOk(expected_data[i], true); + } + + net::Error error = WriteHeaders(response_size); + EXPECT_EQ(net::ERR_IO_PENDING, error); + reader->CompletePendingRead(); + + for (size_t i = 0; i < arraysize(expected_data); ++i) { + error = WriteData(expected_data[i]); + EXPECT_EQ(net::ERR_IO_PENDING, error); + reader->CompletePendingRead(); + EXPECT_EQ(net::OK, last_error_); + } + + EXPECT_TRUE(reader->AllExpectedReadsDone()); + EXPECT_EQ(0U, cache_writer_->bytes_written()); +} + +// This test writes headers and three data blocks data1, data2, data3; data2 +// differs in the cached version. The writer should be asked to rewrite the +// headers and body with the new value, and the copy reader should be asked to +// read the header and data1. +TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) { + std::string data1 = "abcdef"; + std::string cache_data2 = "ghijkl"; + std::string net_data2 = "mnopqr"; + std::string data3 = "stuvwxyz"; + size_t cache_response_size = data1.size() + cache_data2.size() + data3.size(); + size_t net_response_size = data1.size() + net_data2.size() + data3.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + MockServiceWorkerResponseReader* compare_reader = ExpectReader(); + MockServiceWorkerResponseReader* copy_reader = ExpectReader(); + + compare_reader->ExpectReadInfoOk(cache_response_size, false); + compare_reader->ExpectReadDataOk(data1, false); + compare_reader->ExpectReadDataOk(cache_data2, false); + + copy_reader->ExpectReadInfoOk(cache_response_size, false); + copy_reader->ExpectReadDataOk(data1, false); + + writer->ExpectWriteInfoOk(net_response_size, false); + writer->ExpectWriteDataOk(data1.size(), false); + writer->ExpectWriteDataOk(net_data2.size(), false); + writer->ExpectWriteDataOk(data3.size(), false); + + net::Error error = WriteHeaders(net_response_size); + EXPECT_EQ(net::OK, error); + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + error = WriteData(net_data2); + EXPECT_EQ(net::OK, error); + error = WriteData(data3); + EXPECT_EQ(net::OK, error); + + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_TRUE(compare_reader->AllExpectedReadsDone()); + EXPECT_TRUE(copy_reader->AllExpectedReadsDone()); +} + +// Tests behavior when the cached data is shorter than the network data. +TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) { + std::string data1 = "abcdef"; + std::string cache_data2 = "mnop"; + std::string net_data2 = "mnopqr"; + std::string data3 = "stuvwxyz"; + size_t cache_response_size = data1.size() + cache_data2.size() + data3.size(); + size_t net_response_size = data1.size() + net_data2.size() + data3.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + MockServiceWorkerResponseReader* compare_reader = ExpectReader(); + MockServiceWorkerResponseReader* copy_reader = ExpectReader(); + + compare_reader->ExpectReadInfoOk(cache_response_size, false); + compare_reader->ExpectReadDataOk(data1, false); + compare_reader->ExpectReadDataOk(cache_data2, false); + compare_reader->ExpectReadDataOk("", false); // EOF read + + copy_reader->ExpectReadInfoOk(cache_response_size, false); + copy_reader->ExpectReadDataOk(data1, false); + + writer->ExpectWriteInfoOk(net_response_size, false); + writer->ExpectWriteDataOk(data1.size(), false); + writer->ExpectWriteDataOk(net_data2.size(), false); + writer->ExpectWriteDataOk(data3.size(), false); + + net::Error error = WriteHeaders(net_response_size); + EXPECT_EQ(net::OK, error); + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + error = WriteData(net_data2); + EXPECT_EQ(net::OK, error); + error = WriteData(data3); + EXPECT_EQ(net::OK, error); + + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_TRUE(compare_reader->AllExpectedReadsDone()); + EXPECT_TRUE(copy_reader->AllExpectedReadsDone()); +} + +// Tests behavior when the cached data is longer than the network data. +TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) { + std::string data1 = "abcdef"; + std::string cache_data2 = "mnop"; + std::string net_data2 = "mnop"; + std::string cache_data3 = "qr"; + size_t cached_size = data1.size() + cache_data2.size() + cache_data3.size(); + size_t net_size = data1.size() + net_data2.size(); + + MockServiceWorkerResponseWriter* writer = ExpectWriter(); + MockServiceWorkerResponseReader* compare_reader = ExpectReader(); + MockServiceWorkerResponseReader* copy_reader = ExpectReader(); + + compare_reader->ExpectReadInfoOk(cached_size, false); + compare_reader->ExpectReadDataOk(data1, false); + compare_reader->ExpectReadDataOk(cache_data2, false); + + // The comparison should fail at the end of |cache_data2|, when the cache + // writer realizes the two responses are different sizes, and then the network + // data should be written back starting with |net_data2|. + copy_reader->ExpectReadInfoOk(cached_size, false); + copy_reader->ExpectReadDataOk(data1, false); + copy_reader->ExpectReadDataOk(net_data2, false); + + writer->ExpectWriteInfoOk(net_size, false); + writer->ExpectWriteDataOk(data1.size(), false); + writer->ExpectWriteDataOk(net_data2.size(), false); + + net::Error error = WriteHeaders(net_size); + EXPECT_EQ(net::OK, error); + error = WriteData(data1); + EXPECT_EQ(net::OK, error); + error = WriteData(net_data2); + EXPECT_EQ(net::OK, error); + error = WriteData(""); + EXPECT_EQ(net::OK, error); + + EXPECT_TRUE(writer->AllExpectedWritesDone()); + EXPECT_TRUE(compare_reader->AllExpectedReadsDone()); + EXPECT_TRUE(copy_reader->AllExpectedReadsDone()); +} + +} // namespace +} // namespace content
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc index 1f98d99e..7a960d0 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.cc +++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -4,10 +4,11 @@ #include "content/browser/service_worker/service_worker_write_to_cache_job.h" -#include <algorithm> - +#include "base/bind.h" +#include "base/callback.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" +#include "content/browser/service_worker/service_worker_cache_writer.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_disk_cache.h" #include "content/browser/service_worker/service_worker_metrics.h" @@ -18,7 +19,6 @@ #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" -#include "net/http/http_util.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_status.h" @@ -40,260 +40,8 @@ "The script resource is behind a redirect, which is disallowed."; const char kServiceWorkerAllowed[] = "Service-Worker-Allowed"; -const int kBufferSize = 16 * 1024; - } // namespace -// Reads an existing resource and copies it via -// ServiceWorkerWriteToCacheJob::WriteData. -class ServiceWorkerWriteToCacheJob::Copier : public base::RefCounted<Copier> { - public: - Copier(base::WeakPtr<ServiceWorkerWriteToCacheJob> owner, - scoped_ptr<ServiceWorkerResponseReader> reader, - int bytes_to_copy, - const base::Callback<void(ServiceWorkerStatusCode)>& callback) - : owner_(owner), - reader_(reader.release()), - bytes_to_copy_(bytes_to_copy), - callback_(callback) { - DCHECK_LT(0, bytes_to_copy_); - } - - void Start() { - io_buffer_ = new net::IOBuffer(kBufferSize); - ReadSomeData(); - } - - private: - friend class base::RefCounted<Copier>; - ~Copier() {} - - void ReadSomeData() { - reader_->ReadData(io_buffer_.get(), kBufferSize, - base::Bind(&Copier::OnReadDataComplete, this)); - } - - void OnReadDataComplete(int result) { - if (!owner_) - return; - if (result <= 0) { - // We hit EOF or error but weren't done copying. - Complete(SERVICE_WORKER_ERROR_FAILED); - return; - } - - int bytes_to_write = std::min(bytes_to_copy_, result); - owner_->WriteData(io_buffer_.get(), bytes_to_write, - base::Bind(&Copier::OnWriteDataComplete, this)); - } - - void OnWriteDataComplete(int result) { - if (result < 0) { - Complete(SERVICE_WORKER_ERROR_FAILED); - return; - } - - DCHECK_LE(result, bytes_to_copy_); - bytes_to_copy_ -= result; - if (bytes_to_copy_ == 0) { - Complete(SERVICE_WORKER_OK); - return; - } - - ReadSomeData(); - } - - void Complete(ServiceWorkerStatusCode status) { - if (!owner_) - return; - callback_.Run(status); - } - - base::WeakPtr<ServiceWorkerWriteToCacheJob> owner_; - scoped_ptr<ServiceWorkerResponseReader> reader_; - int bytes_to_copy_ = 0; - base::Callback<void(ServiceWorkerStatusCode)> callback_; - scoped_refptr<net::IOBuffer> io_buffer_; -}; - -// Abstract consumer for ServiceWorkerWriteToCacheJob that processes data from -// the network. -class ServiceWorkerWriteToCacheJob::NetDataConsumer { - public: - virtual ~NetDataConsumer() {} - - // Called by |owner_|'s OnResponseStarted. - virtual void OnResponseStarted() = 0; - - // HandleData should call |owner_|->NotifyReadComplete() when done. - virtual void HandleData(net::IOBuffer* buf, int size) = 0; -}; - -// Dumb consumer that just writes everything it sees to disk. -class ServiceWorkerWriteToCacheJob::PassThroughConsumer - : public ServiceWorkerWriteToCacheJob::NetDataConsumer { - public: - explicit PassThroughConsumer(ServiceWorkerWriteToCacheJob* owner) - : owner_(owner), weak_factory_(this) {} - ~PassThroughConsumer() override {} - - void OnResponseStarted() override { - owner_->WriteHeaders( - base::Bind(&PassThroughConsumer::OnWriteHeadersComplete, - weak_factory_.GetWeakPtr())); - owner_->SetPendingIO(); - } - - void HandleData(net::IOBuffer* buf, int size) override { - if (size == 0) { - owner_->OnPassThroughComplete(); - return; - } - - owner_->WriteData(buf, size, - base::Bind(&PassThroughConsumer::OnWriteDataComplete, - weak_factory_.GetWeakPtr())); - owner_->SetPendingIO(); - } - - private: - void OnWriteHeadersComplete() { - owner_->ClearPendingIO(); - owner_->CommitHeadersAndNotifyHeadersComplete(); - } - - void OnWriteDataComplete(int result) { - owner_->ClearPendingIO(); - owner_->NotifyReadComplete(result); - } - - ServiceWorkerWriteToCacheJob* owner_; - base::WeakPtrFactory<PassThroughConsumer> weak_factory_; -}; - -// Compares an existing resource with data progressively fed to it. -// Calls back to |owner|->OnCompareComplete once done. -class ServiceWorkerWriteToCacheJob::Comparer - : public ServiceWorkerWriteToCacheJob::NetDataConsumer { - public: - Comparer(ServiceWorkerWriteToCacheJob* owner, - scoped_ptr<ServiceWorkerResponseReader> reader) - : owner_(owner), reader_(reader.release()), weak_factory_(this) {} - ~Comparer() override {} - - void OnResponseStarted() override { - owner_->CommitHeadersAndNotifyHeadersComplete(); - } - - void HandleData(net::IOBuffer* buf, int size) override { - net_data_ = buf; - net_data_offset_ = 0; - net_data_size_ = size; - - if (size == 0 && info_) { - Complete(bytes_matched_ == info_->response_data_size); - return; - } - - if (!info_) { - read_buffer_ = new net::IOBuffer(kBufferSize); - info_ = new HttpResponseInfoIOBuffer; - reader_->ReadInfo(info_.get(), base::Bind(&Comparer::OnReadInfoComplete, - weak_factory_.GetWeakPtr())); - owner_->SetPendingIO(); - return; - } - - ReadSomeData(); - owner_->SetPendingIO(); - } - - private: - int bytes_remaining() { - DCHECK(net_data_); - DCHECK_LE(0, net_data_offset_); - DCHECK_LE(net_data_offset_, net_data_size_); - return net_data_size_ - net_data_offset_; - } - - void OnReadInfoComplete(int result) { - if (result < 0) { - Complete(false); - return; - } - - if (bytes_remaining() == 0) { - Complete(bytes_matched_ == info_->response_data_size); - return; - } - - ReadSomeData(); - } - - void ReadSomeData() { - DCHECK_LT(0, bytes_remaining()); - int bytes_to_read = std::min(bytes_remaining(), kBufferSize); - reader_->ReadData( - read_buffer_.get(), bytes_to_read, - base::Bind(&Comparer::OnReadDataComplete, weak_factory_.GetWeakPtr())); - } - - void OnReadDataComplete(int result) { - if (result <= 0) { - // We hit error or EOF but had more to compare. - Complete(false); - return; - } - - DCHECK_LE(result, bytes_remaining()); - if (memcmp(net_data_->data() + net_data_offset_, read_buffer_->data(), - result) != 0) { - Complete(false); - return; - } - - net_data_offset_ += result; - if (bytes_remaining() == 0) { - NotifyReadComplete(); - return; - } - - ReadSomeData(); - } - - // Completes one HandleData() call. - void NotifyReadComplete() { - int size = net_data_size_; - net_data_ = nullptr; - net_data_offset_ = 0; - net_data_size_ = 0; - - bytes_matched_ += size; - owner_->ClearPendingIO(); - owner_->NotifyReadComplete(size); - } - - // Completes the entire Comparer. - void Complete(bool is_equal) { - owner_->OnCompareComplete(bytes_matched_, is_equal); - } - - ServiceWorkerWriteToCacheJob* owner_; - scoped_ptr<ServiceWorkerResponseReader> reader_; - scoped_refptr<net::IOBuffer> read_buffer_; - scoped_refptr<HttpResponseInfoIOBuffer> info_; - - // Cumulative number of bytes successfully compared. - int bytes_matched_ = 0; - - // State used for one HandleData() call. - scoped_refptr<net::IOBuffer> net_data_; - int net_data_offset_ = 0; - int net_data_size_ = 0; - - base::WeakPtrFactory<Comparer> weak_factory_; -}; - ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, @@ -331,15 +79,14 @@ net::URLRequestStatus::FAILED, net::ERR_FAILED)); return; } - if (incumbent_response_id_ != kInvalidServiceWorkerResourceId && - !version_->skip_script_comparison()) { - scoped_ptr<ServiceWorkerResponseReader> incumbent_reader = - context_->storage()->CreateResponseReader(incumbent_response_id_); - consumer_.reset(new Comparer(this, incumbent_reader.Pass())); - } else { - consumer_.reset(new PassThroughConsumer(this)); - } + // These uses of Unretained are safe because this object is the sole owner of + // |cache_writer_|, which in turn is the sole user of these callbacks. + cache_writer_.reset(new ServiceWorkerCacheWriter( + base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseReader, + base::Unretained(this)), + base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter, + base::Unretained(this)))); version_->script_cache_map()->NotifyStartedCaching( url_, response_id_); did_notify_started_ = true; @@ -352,12 +99,9 @@ weak_factory_.InvalidateWeakPtrs(); has_been_killed_ = true; net_request_.reset(); - if (did_notify_started_ && !did_notify_finished_) { - version_->script_cache_map()->NotifyFinishedCaching( - url_, -1, - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_ABORTED), - kKilledError); - did_notify_finished_ = true; + if (did_notify_started_) { + NotifyFinishedCaching(net::URLRequestStatus::FromError(net::ERR_ABORTED), + kKilledError); } writer_.reset(); context_.reset(); @@ -413,17 +157,31 @@ return false; if (!status.is_success()) { - AsyncNotifyDoneHelper(status, kFetchScriptError); + NotifyDoneHelper(status, kFetchScriptError); return false; } - DCHECK_EQ(0, *bytes_read); - consumer_->HandleData(buf, 0); - if (did_notify_finished_) - return GetStatus().is_success(); - if (GetStatus().is_io_pending()) + HandleNetData(*bytes_read); + status = GetStatus(); + + // Synchronous EOFs that do not replace the incumbent entry are considered + // failures. Since normally the URLRequestJob's status would be set by + // ReadNetData or HandleNetData, this code has to manually fix up the status + // to match the failure this function is about to return. + if (status.status() == net::URLRequestStatus::SUCCESS && + *bytes_read == 0 && !cache_writer_->did_replace()) { + status = net::URLRequestStatus::FromError(net::ERR_FAILED); + } + + if (!status.is_success()) { + NotifyDoneHelper(status, ""); return false; - return status.is_success(); + } + + // Since URLRequestStatus::is_success() means "SUCCESS or IO_PENDING", but the + // contract of this function is "return true for synchronous successes only", + // it is important to test against SUCCESS explicitly here. + return status.status() == net::URLRequestStatus::SUCCESS; } const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const { @@ -462,104 +220,14 @@ int* bytes_read) { DCHECK_GT(buf_size, 0); DCHECK(bytes_read); - *bytes_read = 0; io_buffer_ = buf; io_buffer_bytes_ = 0; - int net_bytes_read = 0; - if (!net_request_->Read(buf, buf_size, &net_bytes_read)) { - if (net_request_->status().is_io_pending()) - return net_request_->status(); - DCHECK(!net_request_->status().is_success()); - return net_request_->status(); - } + if (!net_request_->Read(buf, buf_size, bytes_read)) + DCHECK_NE(net::URLRequestStatus::SUCCESS, net_request_->status().status()); - if (net_bytes_read != 0) { - HandleNetData(net_bytes_read); - DCHECK(GetStatus().is_io_pending()); - return GetStatus(); - } - - DCHECK(net_request_->status().is_success()); return net_request_->status(); } -void ServiceWorkerWriteToCacheJob::WriteHeaders(const base::Closure& callback) { - if (!context_) { - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), - kFetchScriptError); - return; - } - TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", - "ServiceWorkerWriteToCacheJob::ExecutingJob", - this, "WriteHeaders"); - writer_ = context_->storage()->CreateResponseWriter(response_id_); - scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = - new HttpResponseInfoIOBuffer( - new net::HttpResponseInfo(net_request_->response_info())); - writer_->WriteInfo( - info_buffer.get(), - base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete, - weak_factory_.GetWeakPtr(), callback)); -} - -void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete( - const base::Closure& callback, - int result) { - if (result < 0) { - ServiceWorkerMetrics::CountWriteResponseResult( - ServiceWorkerMetrics::WRITE_HEADERS_ERROR); - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, result), - kFetchScriptError); - return; - } - TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", - "ServiceWorkerWriteToCacheJob::ExecutingJob", - this, "WriteHeadersCompleted"); - callback.Run(); -} - -void ServiceWorkerWriteToCacheJob::WriteData( - net::IOBuffer* buf, - int bytes_to_write, - const base::Callback<void(int result)>& callback) { - DCHECK_LT(0, bytes_to_write); - TRACE_EVENT_ASYNC_STEP_INTO1( - "ServiceWorker", "ServiceWorkerWriteToCacheJob::ExecutingJob", this, - "WriteData", "Amount to write", bytes_to_write); - - writer_->WriteData( - buf, bytes_to_write, - base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, - weak_factory_.GetWeakPtr(), callback)); -} - -void ServiceWorkerWriteToCacheJob::OnWriteDataComplete( - const base::Callback<void(int result)>& callback, - int result) { - DCHECK_NE(0, result); - if (!context_) { - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), - kFetchScriptError); - return; - } - if (result < 0) { - ServiceWorkerMetrics::CountWriteResponseResult( - ServiceWorkerMetrics::WRITE_DATA_ERROR); - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, result), - kFetchScriptError); - return; - } - ServiceWorkerMetrics::CountWriteResponseResult( - ServiceWorkerMetrics::WRITE_OK); - callback.Run(result); - TRACE_EVENT_ASYNC_END0("ServiceWorker", - "ServiceWorkerWriteToCacheJob::ExecutingJob", this); -} - void ServiceWorkerWriteToCacheJob::OnReceivedRedirect( net::URLRequest* request, const net::RedirectInfo& redirect_info, @@ -568,9 +236,9 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnReceivedRedirect"); // Script resources can't redirect. - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_UNSAFE_REDIRECT), - kRedirectError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_UNSAFE_REDIRECT), + kRedirectError); } void ServiceWorkerWriteToCacheJob::OnAuthRequired( @@ -580,7 +248,7 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnAuthRequired"); // TODO(michaeln): Pass this thru to our jobs client. - AsyncNotifyDoneHelper( + NotifyDoneHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -593,7 +261,7 @@ "ServiceWorkerWriteToCacheJob::OnCertificateRequested"); // TODO(michaeln): Pass this thru to our jobs client. // see NotifyCertificateRequested. - AsyncNotifyDoneHelper( + NotifyDoneHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -607,9 +275,9 @@ "ServiceWorkerWriteToCacheJob::OnSSLCertificateError"); // TODO(michaeln): Pass this thru to our jobs client, // see NotifySSLCertificateError. - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); } void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart( @@ -625,15 +293,15 @@ net::URLRequest* request) { DCHECK_EQ(net_request_, request); if (!request->status().is_success()) { - AsyncNotifyDoneHelper(request->status(), kFetchScriptError); + NotifyDoneHelper(request->status(), kFetchScriptError); return; } if (request->GetResponseCode() / 100 != 2) { std::string error_message = base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode()); - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INVALID_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INVALID_RESPONSE), + error_message); // TODO(michaeln): Instead of error'ing immediately, send the net // response to our consumer, just don't cache it? return; @@ -644,9 +312,9 @@ const net::HttpNetworkSession::Params* session_params = request->context()->GetNetworkSessionParams(); if (!session_params || !session_params->ignore_certificate_errors) { - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); return; } } @@ -661,9 +329,9 @@ mime_type.empty() ? kNoMIMEError : base::StringPrintf(kBadMIMEError, mime_type.c_str()); - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return; } @@ -676,17 +344,46 @@ if (net_request_->response_info().network_accessed) version_->embedded_worker()->OnNetworkAccessedForScriptLoad(); - consumer_->OnResponseStarted(); + http_info_.reset(new net::HttpResponseInfo(net_request_->response_info())); + scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = + new HttpResponseInfoIOBuffer( + new net::HttpResponseInfo(net_request_->response_info())); + net::Error error = cache_writer_->MaybeWriteHeaders( + info_buffer.get(), + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete, + weak_factory_.GetWeakPtr())); + SetStatus(net::URLRequestStatus::FromError(error)); + if (error != net::ERR_IO_PENDING) + NotifyHeadersComplete(); } -void ServiceWorkerWriteToCacheJob::CommitHeadersAndNotifyHeadersComplete() { - http_info_.reset(new net::HttpResponseInfo(net_request_->response_info())); +void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) { + SetStatus(net::URLRequestStatus::FromError(error)); NotifyHeadersComplete(); } void ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { io_buffer_bytes_ = bytes_read; - consumer_->HandleData(io_buffer_.get(), bytes_read); + net::Error error = cache_writer_->MaybeWriteData( + io_buffer_.get(), bytes_read, + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, + weak_factory_.GetWeakPtr())); + SetStatus(net::URLRequestStatus::FromError(error)); + + // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete. + if (error != net::ERR_IO_PENDING && bytes_read == 0) { + NotifyFinishedCaching(net::URLRequestStatus::FromError(error), + std::string()); + } +} + +void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) { + SetStatus(net::URLRequestStatus::FromError(error)); + DCHECK_NE(net::ERR_IO_PENDING, error); + if (io_buffer_bytes_ == 0) { + NotifyDoneHelper(net::URLRequestStatus::FromError(error), std::string()); + } + NotifyReadComplete(error == net::OK ? io_buffer_bytes_ : error); } void ServiceWorkerWriteToCacheJob::OnReadCompleted( @@ -695,18 +392,23 @@ DCHECK_EQ(net_request_, request); if (bytes_read < 0) { DCHECK(!request->status().is_success()); - AsyncNotifyDoneHelper(request->status(), kFetchScriptError); + NotifyDoneHelper(request->status(), kFetchScriptError); return; } - if (bytes_read > 0) { - HandleNetData(bytes_read); - DCHECK(GetStatus().is_io_pending()); - return; + HandleNetData(bytes_read); + // HandleNetData can cause status of this job to change. If the status changes + // to IO_PENDING, that means HandleNetData has pending IO, and + // NotifyReadComplete will be called later by the appropriate callback. + if (!GetStatus().is_io_pending()) { + int result = GetStatus().status() == net::URLRequestStatus::SUCCESS + ? bytes_read + : GetStatus().error(); + // If bytes_read is 0, HandleNetData synchronously completed and this job is + // at EOF. + if (bytes_read == 0) + NotifyDoneHelper(GetStatus(), std::string()); + NotifyReadComplete(result); } - - // No more data to process, the job is complete. - DCHECK(request->status().is_success()); - HandleNetData(0); } bool ServiceWorkerWriteToCacheJob::CheckPathRestriction( @@ -720,107 +422,74 @@ if (!ServiceWorkerUtils::IsPathRestrictionSatisfied( version_->scope(), url_, has_header ? &service_worker_allowed : nullptr, &error_message)) { - AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return false; } return true; } -void ServiceWorkerWriteToCacheJob::SetPendingIO() { - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); -} - -void ServiceWorkerWriteToCacheJob::ClearPendingIO() { - SetStatus(net::URLRequestStatus()); -} - -void ServiceWorkerWriteToCacheJob::OnPassThroughComplete() { - NotifyFinishedCaching(net::URLRequestStatus(), std::string()); - if (GetStatus().is_io_pending()) { - ClearPendingIO(); - NotifyReadComplete(0); - } -} - -void ServiceWorkerWriteToCacheJob::OnCompareComplete(int bytes_matched, - bool is_equal) { - if (is_equal) { - // This version is identical to the incumbent, so discard it and fail this - // job. - version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), - kFetchScriptError); - return; - } - - // We must switch to the pass through consumer. Write what is known - // (headers + bytes matched) to disk. - WriteHeaders(base::Bind(&ServiceWorkerWriteToCacheJob::CopyIncumbent, - weak_factory_.GetWeakPtr(), bytes_matched)); - SetPendingIO(); -} - -void ServiceWorkerWriteToCacheJob::CopyIncumbent(int bytes_to_copy) { - if (bytes_to_copy == 0) { - OnCopyComplete(SERVICE_WORKER_OK); - return; - } - scoped_ptr<ServiceWorkerResponseReader> incumbent_reader = - context_->storage()->CreateResponseReader(incumbent_response_id_); - scoped_refptr<Copier> copier = new Copier( - weak_factory_.GetWeakPtr(), incumbent_reader.Pass(), bytes_to_copy, - base::Bind(&ServiceWorkerWriteToCacheJob::OnCopyComplete, - weak_factory_.GetWeakPtr())); - copier->Start(); // It deletes itself when done. - DCHECK(GetStatus().is_io_pending()); -} - -void ServiceWorkerWriteToCacheJob::OnCopyComplete( - ServiceWorkerStatusCode status) { - if (status != SERVICE_WORKER_OK) { - AsyncNotifyDoneHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), - kFetchScriptError); - return; - } - - // Continue processing the net data that triggered the comparison fail and - // copy. - if (io_buffer_bytes_ > 0) { - consumer_.reset(new PassThroughConsumer(this)); - consumer_->HandleData(io_buffer_.get(), io_buffer_bytes_); - return; - } - - // The copy was triggered by EOF from the network, which - // means the job is now done. - NotifyFinishedCaching(net::URLRequestStatus(), std::string()); - ClearPendingIO(); - NotifyReadComplete(0); -} - -void ServiceWorkerWriteToCacheJob::AsyncNotifyDoneHelper( +void ServiceWorkerWriteToCacheJob::NotifyDoneHelper( const net::URLRequestStatus& status, const std::string& status_message) { DCHECK(!status.is_io_pending()); + + // Note that NotifyFinishedCaching has logic in it to detect the special case + // mentioned below as well. NotifyFinishedCaching(status, status_message); - SetStatus(status); - NotifyDone(status); + + net::URLRequestStatus reported_status = status; + std::string reported_status_message = status_message; + + // A strange special case: requests that successfully fetch the entire + // ServiceWorker and write it back, but which did not replace the incumbent + // script because the new script was identical, are considered to have failed. + if (status.is_success() && !cache_writer_->did_replace()) { + reported_status = net::URLRequestStatus::FromError(net::ERR_FAILED); + reported_status_message = ""; + } + + SetStatus(reported_status); + NotifyDone(reported_status); } void ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( net::URLRequestStatus status, const std::string& status_message) { - DCHECK(!did_notify_finished_); + if (did_notify_finished_) + return; + + // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the + // incumbent entry wasn't actually replaced because the new entry was + // equivalent, the new version didn't actually install because it already + // exists. + if (status.status() == net::URLRequestStatus::SUCCESS && + !cache_writer_->did_replace()) { + status = + net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED); + version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); + } + int size = -1; if (status.is_success()) - size = writer_ ? writer_->amount_written() : 0; + size = cache_writer_->bytes_written(); + version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, status_message); did_notify_finished_ = true; } +scoped_ptr<ServiceWorkerResponseReader> +ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() { + if (incumbent_response_id_ != kInvalidServiceWorkerResponseId) + return context_->storage()->CreateResponseReader(incumbent_response_id_); + return nullptr; +} + +scoped_ptr<ServiceWorkerResponseWriter> +ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter() { + return context_->storage()->CreateResponseWriter(response_id_); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h index 9fcd4b86..deee1070 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.h +++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -15,13 +15,14 @@ #include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/common/resource_type.h" +#include "net/base/net_errors.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" namespace content { +class ServiceWorkerCacheWriter; class ServiceWorkerContextCore; -class ServiceWorkerResponseWriter; class ServiceWorkerVersions; // A URLRequestJob derivative used to cache the main script @@ -58,10 +59,6 @@ UpdateAfter24Hours); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache); - class NetDataConsumer; - class PassThroughConsumer; - class Comparer; - class Copier; ~ServiceWorkerWriteToCacheJob() override; @@ -86,14 +83,12 @@ int buf_size, int* bytes_read); - void CommitHeadersAndNotifyHeadersComplete(); - void WriteHeaders(const base::Closure& callback); - void OnWriteHeadersComplete(const base::Closure& callback, int result); - void WriteData(net::IOBuffer* buf, - int amount_to_write, - const base::Callback<void(int result)>& callback); - void OnWriteDataComplete(const base::Callback<void(int result)>& callback, - int result); + // Callbacks for writing headers and data via |cache_writer_|. Note that since + // the MaybeWriteHeaders and MaybeWriteData methods on |cache_writer_| are + // guaranteed not to do short writes, these functions only receive a + // net::Error indicating success or failure, not a count of bytes written. + void OnWriteHeadersComplete(net::Error error); + void OnWriteDataComplete(net::Error error); // net::URLRequest::Delegate overrides that observe the net request. void OnReceivedRedirect(net::URLRequest* request, @@ -113,20 +108,23 @@ bool CheckPathRestriction(net::URLRequest* request); - void SetPendingIO(); - void ClearPendingIO(); - void OnPassThroughComplete(); - void OnCompareComplete(int bytes_matched, bool is_equal); - void CopyIncumbent(int bytes_to_copy); - void OnCopyComplete(ServiceWorkerStatusCode status); + // Writes network data back to the script cache if needed, and notifies the + // script cache of fetch completion at EOF. This function might need to do + // asynchronous IO; if so, it signals this through setting the URLRequestJob's + // status to IO_PENDING. After this function returns, if the URLRequestJob + // isn't IO_PENDING, all of the data in |io_buffer_| has been written back to + // the script cache if necessary. void HandleNetData(int bytes_read); - void AsyncNotifyDoneHelper(const net::URLRequestStatus& status, - const std::string& status_message); + void NotifyDoneHelper(const net::URLRequestStatus& status, + const std::string& status_message); void NotifyFinishedCaching(net::URLRequestStatus status, const std::string& status_message); + scoped_ptr<ServiceWorkerResponseReader> CreateCacheResponseReader(); + scoped_ptr<ServiceWorkerResponseWriter> CreateCacheResponseWriter(); + ResourceType resource_type_; // Differentiate main script and imports scoped_refptr<net::IOBuffer> io_buffer_; int io_buffer_bytes_; @@ -138,7 +136,7 @@ scoped_ptr<net::HttpResponseInfo> http_info_; scoped_ptr<ServiceWorkerResponseWriter> writer_; scoped_refptr<ServiceWorkerVersion> version_; - scoped_ptr<NetDataConsumer> consumer_; + scoped_ptr<ServiceWorkerCacheWriter> cache_writer_; bool has_been_killed_; bool did_notify_started_; bool did_notify_finished_;
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc index a43fa5d..2fdd365 100644 --- a/content/browser/utility_process_host_impl.cc +++ b/content/browser/utility_process_host_impl.cc
@@ -122,13 +122,6 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (is_batch_mode_) EndBatchMode(); - - // We could be destroyed as a result of Chrome shutdown. When that happens, - // the Mojo channel doesn't get the opportunity to shut down cleanly because - // it posts to the IO thread (the current thread) which is being destroyed. - // To guarantee proper shutdown of the Mojo channel, do it explicitly here. - if (mojo_application_host_) - mojo_application_host_->ShutdownOnIOThread(); } base::WeakPtr<UtilityProcessHost> UtilityProcessHostImpl::AsWeakPtr() {
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc index ff58da2f..cf01997 100644 --- a/content/browser/web_contents/web_contents_android.cc +++ b/content/browser/web_contents/web_contents_android.cc
@@ -351,6 +351,11 @@ return web_contents_->ShowingInterstitialPage(); } +jboolean WebContentsAndroid::FocusLocationBarByDefault(JNIEnv* env, + jobject obj) { + return web_contents_->FocusLocationBarByDefault(); +} + jboolean WebContentsAndroid::IsRenderWidgetHostViewReady( JNIEnv* env, jobject obj) {
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h index 5088d97..2e2659ef 100644 --- a/content/browser/web_contents/web_contents_android.h +++ b/content/browser/web_contents/web_contents_android.h
@@ -66,6 +66,7 @@ void ShowInterstitialPage( JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr); jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj); + jboolean FocusLocationBarByDefault(JNIEnv* env, jobject obj); jboolean IsRenderWidgetHostViewReady(JNIEnv* env, jobject obj); void ExitFullscreen(JNIEnv* env, jobject obj); void UpdateTopControlsState(
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc index f05a253a..7b14aeb 100644 --- a/content/common/cc_messages.cc +++ b/content/common/cc_messages.cc
@@ -800,7 +800,6 @@ const param_type& p) { for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { WriteParam(m, p.size_in_pixels[i]); - WriteParam(m, p.allow_overlay[i]); } } @@ -811,8 +810,6 @@ for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { if (!ReadParam(m, iter, &p->size_in_pixels[i])) return false; - if (!ReadParam(m, iter, &p->allow_overlay[i])) - return false; } return true; } @@ -823,8 +820,6 @@ l->append("StreamVideoDrawQuad::OverlayResources(["); for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { LogParam(p.size_in_pixels[i], l); - l->append(", "); - LogParam(p.allow_overlay[i], l); if (i < (cc::DrawQuad::Resources::kMaxResourceIdCount - 1)) l->append(", "); } @@ -836,7 +831,6 @@ const param_type& p) { for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { WriteParam(m, p.size_in_pixels[i]); - WriteParam(m, p.allow_overlay[i]); } } @@ -847,8 +841,6 @@ for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { if (!ReadParam(m, iter, &p->size_in_pixels[i])) return false; - if (!ReadParam(m, iter, &p->allow_overlay[i])) - return false; } return true; } @@ -859,8 +851,6 @@ l->append("TextureDrawQuad::OverlayResources(["); for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) { LogParam(p.size_in_pixels[i], l); - l->append(", "); - LogParam(p.allow_overlay[i], l); if (i < (cc::DrawQuad::Resources::kMaxResourceIdCount - 1)) l->append(", "); }
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index 55a8c497..2dac19f 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h
@@ -187,7 +187,6 @@ IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad) IPC_STRUCT_TRAITS_MEMBER(io_surface_size) IPC_STRUCT_TRAITS_MEMBER(orientation) - IPC_STRUCT_TRAITS_MEMBER(allow_overlay) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassDrawQuad) @@ -269,7 +268,7 @@ IPC_STRUCT_TRAITS_MEMBER(read_lock_fences_enabled) IPC_STRUCT_TRAITS_MEMBER(is_repeated) IPC_STRUCT_TRAITS_MEMBER(is_software) - IPC_STRUCT_TRAITS_MEMBER(allow_overlay) + IPC_STRUCT_TRAITS_MEMBER(is_overlay_candidate) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource)
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc index 4cb3dc6..1a20504 100644 --- a/content/common/cc_messages_unittest.cc +++ b/content/common/cc_messages_unittest.cc
@@ -131,7 +131,6 @@ EXPECT_EQ(a->io_surface_size.ToString(), b->io_surface_size.ToString()); EXPECT_EQ(a->io_surface_resource_id(), b->io_surface_resource_id()); EXPECT_EQ(a->orientation, b->orientation); - EXPECT_EQ(a->allow_overlay, b->allow_overlay); } void Compare(const RenderPassDrawQuad* a, const RenderPassDrawQuad* b) { @@ -161,7 +160,6 @@ void Compare(const StreamVideoDrawQuad* a, const StreamVideoDrawQuad* b) { EXPECT_EQ(a->resource_id(), b->resource_id()); EXPECT_EQ(a->resource_size_in_pixels(), b->resource_size_in_pixels()); - EXPECT_EQ(a->allow_overlay(), b->allow_overlay()); EXPECT_EQ(a->matrix, b->matrix); } @@ -172,7 +170,6 @@ void Compare(const TextureDrawQuad* a, const TextureDrawQuad* b) { EXPECT_EQ(a->resource_id(), b->resource_id()); EXPECT_EQ(a->resource_size_in_pixels(), b->resource_size_in_pixels()); - EXPECT_EQ(a->allow_overlay(), b->allow_overlay()); EXPECT_EQ(a->premultiplied_alpha, b->premultiplied_alpha); EXPECT_EQ(a->uv_top_left, b->uv_top_left); EXPECT_EQ(a->uv_bottom_right, b->uv_bottom_right); @@ -216,7 +213,7 @@ } EXPECT_EQ(a.mailbox_holder.texture_target, b.mailbox_holder.texture_target); EXPECT_EQ(a.mailbox_holder.sync_point, b.mailbox_holder.sync_point); - EXPECT_EQ(a.allow_overlay, b.allow_overlay); + EXPECT_EQ(a.is_overlay_candidate, b.is_overlay_candidate); } }; @@ -269,7 +266,6 @@ SkXfermode::Mode arbitrary_blend_mode3 = SkXfermode::kOverlay_Mode; IOSurfaceDrawQuad::Orientation arbitrary_orientation = IOSurfaceDrawQuad::UNFLIPPED; - bool arbitrary_allow_overlay = true; ResourceId arbitrary_resourceid1 = 55; ResourceId arbitrary_resourceid2 = 47; ResourceId arbitrary_resourceid3 = 23; @@ -339,8 +335,7 @@ arbitrary_bool1, arbitrary_size1, arbitrary_resourceid3, - arbitrary_orientation, - arbitrary_allow_overlay); + arbitrary_orientation); pass_cmp->CopyFromAndAppendDrawQuad(iosurface_in, iosurface_in->shared_quad_state); @@ -389,7 +384,7 @@ streamvideo_in->SetAll( shared_state3_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid2, - arbitrary_size1, arbitrary_bool2, arbitrary_matrix1); + arbitrary_size1, arbitrary_matrix1); pass_cmp->CopyFromAndAppendDrawQuad(streamvideo_in, streamvideo_in->shared_quad_state); @@ -412,7 +407,7 @@ texture_in->SetAll(shared_state3_in, arbitrary_rect2, arbitrary_rect2_inside_rect2, arbitrary_rect1_inside_rect2, arbitrary_bool1, arbitrary_resourceid1, arbitrary_size1, - arbitrary_bool2, arbitrary_bool3, arbitrary_pointf1, + arbitrary_bool2, arbitrary_pointf1, arbitrary_pointf2, arbitrary_color, arbitrary_float_array, arbitrary_bool4, arbitrary_bool5); pass_cmp->CopyFromAndAppendDrawQuad(texture_in, @@ -645,7 +640,7 @@ arbitrary_resource1.mailbox_holder.mailbox.SetName(arbitrary_mailbox1); arbitrary_resource1.mailbox_holder.texture_target = GL_TEXTURE_2D; arbitrary_resource1.mailbox_holder.sync_point = arbitrary_uint1; - arbitrary_resource1.allow_overlay = true; + arbitrary_resource1.is_overlay_candidate = true; TransferableResource arbitrary_resource2; arbitrary_resource2.id = 789132; @@ -655,7 +650,7 @@ arbitrary_resource2.mailbox_holder.mailbox.SetName(arbitrary_mailbox2); arbitrary_resource2.mailbox_holder.texture_target = GL_TEXTURE_EXTERNAL_OES; arbitrary_resource2.mailbox_holder.sync_point = arbitrary_uint2; - arbitrary_resource2.allow_overlay = false; + arbitrary_resource2.is_overlay_candidate = false; scoped_ptr<RenderPass> renderpass_in = RenderPass::Create(); renderpass_in->SetNew(
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index acff5d4a..8f09dc4 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc
@@ -72,8 +72,10 @@ scoped_refptr<GpuChannelMessageQueue> GpuChannelMessageQueue::Create( const base::WeakPtr<GpuChannel>& gpu_channel, - base::SingleThreadTaskRunner* task_runner) { - return new GpuChannelMessageQueue(gpu_channel, task_runner); + base::SingleThreadTaskRunner* task_runner, + gpu::SyncPointManager* sync_point_manager) { + return new GpuChannelMessageQueue(gpu_channel, task_runner, + sync_point_manager); } scoped_refptr<gpu::SyncPointOrderData> @@ -83,11 +85,13 @@ GpuChannelMessageQueue::GpuChannelMessageQueue( const base::WeakPtr<GpuChannel>& gpu_channel, - base::SingleThreadTaskRunner* task_runner) + base::SingleThreadTaskRunner* task_runner, + gpu::SyncPointManager* sync_point_manager) : enabled_(true), sync_point_order_data_(gpu::SyncPointOrderData::Create()), gpu_channel_(gpu_channel), - task_runner_(task_runner) {} + task_runner_(task_runner), + sync_point_manager_(sync_point_manager) {} GpuChannelMessageQueue::~GpuChannelMessageQueue() { DCHECK(channel_messages_.empty()); @@ -101,17 +105,13 @@ return sync_point_order_data_->processed_order_num(); } -void GpuChannelMessageQueue::PushBackMessage( - gpu::SyncPointManager* sync_point_manager, const IPC::Message& message) { +void GpuChannelMessageQueue::PushBackMessage(const IPC::Message& message) { base::AutoLock auto_lock(channel_messages_lock_); - if (enabled_) { - PushMessageHelper(sync_point_manager, - make_scoped_ptr(new GpuChannelMessage(message))); - } + if (enabled_) + PushMessageHelper(make_scoped_ptr(new GpuChannelMessage(message))); } bool GpuChannelMessageQueue::GenerateSyncPointMessage( - gpu::SyncPointManager* sync_point_manager, const IPC::Message& message, bool retire_sync_point, uint32_t* sync_point) { @@ -119,13 +119,13 @@ DCHECK(sync_point); base::AutoLock auto_lock(channel_messages_lock_); if (enabled_) { - *sync_point = sync_point_manager->GenerateSyncPoint(); + *sync_point = sync_point_manager_->GenerateSyncPoint(); scoped_ptr<GpuChannelMessage> msg(new GpuChannelMessage(message)); msg->retire_sync_point = retire_sync_point; msg->sync_point = *sync_point; - PushMessageHelper(sync_point_manager, msg.Pass()); + PushMessageHelper(msg.Pass()); return true; } return false; @@ -170,8 +170,7 @@ return !channel_messages_.empty(); } -void GpuChannelMessageQueue::DeleteAndDisableMessages( - GpuChannelManager* gpu_channel_manager) { +void GpuChannelMessageQueue::DeleteAndDisableMessages() { { base::AutoLock auto_lock(channel_messages_lock_); DCHECK(enabled_); @@ -188,10 +187,8 @@ // This needs to clean up both GpuCommandBufferMsg_InsertSyncPoint and // GpuCommandBufferMsg_RetireSyncPoint messages, safer to just check // if we have a sync point number here. - if (msg->sync_point) { - gpu_channel_manager->sync_point_manager()->RetireSyncPoint( - msg->sync_point); - } + if (msg->sync_point) + sync_point_manager_->RetireSyncPoint(msg->sync_point); } if (sync_point_order_data_) { @@ -206,13 +203,12 @@ } void GpuChannelMessageQueue::PushMessageHelper( - gpu::SyncPointManager* sync_point_manager, scoped_ptr<GpuChannelMessage> msg) { channel_messages_lock_.AssertAcquired(); DCHECK(enabled_); msg->order_number = sync_point_order_data_->GenerateUnprocessedOrderNumber( - sync_point_manager); + sync_point_manager_); msg->time_received = base::TimeTicks::Now(); bool had_messages = !channel_messages_.empty(); @@ -224,7 +220,6 @@ GpuChannelMessageFilter::GpuChannelMessageFilter( const base::WeakPtr<GpuChannel>& gpu_channel, GpuChannelMessageQueue* message_queue, - gpu::SyncPointManager* sync_point_manager, base::SingleThreadTaskRunner* task_runner, gpu::PreemptionFlag* preempting_flag, bool future_sync_points) @@ -233,7 +228,6 @@ message_queue_(message_queue), sender_(nullptr), peer_pid_(base::kNullProcessId), - sync_point_manager_(sync_point_manager), task_runner_(task_runner), preempting_flag_(preempting_flag), a_stub_is_descheduled_(false), @@ -345,8 +339,8 @@ // Message queue must handle the entire sync point generation because the // message queue could be disabled from the main thread during generation. uint32_t sync_point = 0u; - if (!message_queue_->GenerateSyncPointMessage( - sync_point_manager_, message, retire_sync_point, &sync_point)) { + if (!message_queue_->GenerateSyncPointMessage(message, retire_sync_point, + &sync_point)) { DLOG(ERROR) << "GpuChannel has been destroyed."; reply->set_reply_error(); Send(reply); @@ -367,7 +361,7 @@ base::Bind(&GpuChannel::HandleOutOfOrderMessage, gpu_channel_, message)); } else { - message_queue_->PushBackMessage(sync_point_manager_, message); + message_queue_->PushBackMessage(message); } handled = true; } @@ -551,6 +545,7 @@ } GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, + gpu::SyncPointManager* sync_point_manager, GpuWatchdog* watchdog, gfx::GLShareGroup* share_group, gpu::gles2::MailboxManager* mailbox, @@ -562,6 +557,7 @@ bool allow_future_sync_points, bool allow_real_time_streams) : gpu_channel_manager_(gpu_channel_manager), + sync_point_manager_(sync_point_manager), channel_id_(IPC::Channel::GenerateVerifiedChannelID("gpu")), preempting_flag_(preempting_flag), client_id_(client_id), @@ -580,13 +576,12 @@ DCHECK(gpu_channel_manager); DCHECK(client_id); - message_queue_ = - GpuChannelMessageQueue::Create(weak_factory_.GetWeakPtr(), task_runner); + message_queue_ = GpuChannelMessageQueue::Create( + weak_factory_.GetWeakPtr(), task_runner, sync_point_manager); filter_ = new GpuChannelMessageFilter( - weak_factory_.GetWeakPtr(), message_queue_.get(), - gpu_channel_manager_->sync_point_manager(), task_runner_.get(), - preempting_flag, allow_future_sync_points_); + weak_factory_.GetWeakPtr(), message_queue_.get(), task_runner, + preempting_flag, allow_future_sync_points); subscription_ref_set_->AddObserver(this); } @@ -595,7 +590,7 @@ // Clear stubs first because of dependencies. stubs_.clear(); - message_queue_->DeleteAndDisableMessages(gpu_channel_manager_); + message_queue_->DeleteAndDisableMessages(); subscription_ref_set_->RemoveObserver(this); if (preempting_flag_.get()) @@ -727,11 +722,12 @@ bool offscreen = false; scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( - this, task_runner_.get(), share_group, window, mailbox_manager_.get(), - preempted_flag_.get(), subscription_ref_set_.get(), - pending_valuebuffer_state_.get(), gfx::Size(), disallowed_features_, - init_params.attribs, init_params.gpu_preference, stream_id, route_id, - offscreen, watchdog_, init_params.active_url)); + this, sync_point_manager_, task_runner_.get(), share_group, window, + mailbox_manager_.get(), preempted_flag_.get(), + subscription_ref_set_.get(), pending_valuebuffer_state_.get(), + gfx::Size(), disallowed_features_, init_params.attribs, + init_params.gpu_preference, stream_id, route_id, offscreen, watchdog_, + init_params.active_url)); if (!router_.AddRoute(route_id, stub.get())) { DLOG(ERROR) << "GpuChannel::CreateViewCommandBuffer(): " @@ -839,8 +835,7 @@ if (stub) { stub->AddSyncPoint(m->sync_point, m->retire_sync_point); } else { - gpu_channel_manager_->sync_point_manager()->RetireSyncPoint( - m->sync_point); + sync_point_manager_->RetireSyncPoint(m->sync_point); } handled = true; } else { @@ -945,8 +940,8 @@ bool offscreen = true; scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( - this, task_runner_.get(), share_group, gfx::GLSurfaceHandle(), - mailbox_manager_.get(), preempted_flag_.get(), + this, sync_point_manager_, task_runner_.get(), share_group, + gfx::GLSurfaceHandle(), mailbox_manager_.get(), preempted_flag_.get(), subscription_ref_set_.get(), pending_valuebuffer_state_.get(), size, disallowed_features_, init_params.attribs, init_params.gpu_preference, init_params.stream_id, route_id, offscreen, watchdog_,
diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index 53b706b..2ca82ee 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h
@@ -65,6 +65,7 @@ public: // Takes ownership of the renderer process handle. GpuChannel(GpuChannelManager* gpu_channel_manager, + gpu::SyncPointManager* sync_point_manager, GpuWatchdog* watchdog, gfx::GLShareGroup* share_group, gpu::gles2::MailboxManager* mailbox_manager, @@ -233,6 +234,10 @@ // are destroyed. So a raw pointer is safe. GpuChannelManager* gpu_channel_manager_; + // Sync point manager. Outlives the channel and is guaranteed to outlive the + // message loop. + gpu::SyncPointManager* sync_point_manager_; + scoped_ptr<IPC::SyncChannel> channel_; // Uniquely identifies the channel within this GPU process. @@ -307,7 +312,6 @@ public: GpuChannelMessageFilter(const base::WeakPtr<GpuChannel>& gpu_channel, GpuChannelMessageQueue* message_queue, - gpu::SyncPointManager* sync_point_manager, base::SingleThreadTaskRunner* task_runner, gpu::PreemptionFlag* preempting_flag, bool future_sync_points); @@ -369,7 +373,6 @@ scoped_refptr<GpuChannelMessageQueue> message_queue_; IPC::Sender* sender_; base::ProcessId peer_pid_; - gpu::SyncPointManager* sync_point_manager_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<gpu::PreemptionFlag> preempting_flag_; std::vector<scoped_refptr<IPC::MessageFilter>> channel_filters_; @@ -408,7 +411,8 @@ public: static scoped_refptr<GpuChannelMessageQueue> Create( const base::WeakPtr<GpuChannel>& gpu_channel, - base::SingleThreadTaskRunner* task_runner); + base::SingleThreadTaskRunner* task_runner, + gpu::SyncPointManager* sync_point_manager); scoped_refptr<gpu::SyncPointOrderData> GetSyncPointOrderData(); @@ -430,27 +434,25 @@ // Returns true if there are more messages on the queue. bool MessageProcessed(); - void PushBackMessage(gpu::SyncPointManager* sync_point_manager, - const IPC::Message& message); + void PushBackMessage(const IPC::Message& message); - bool GenerateSyncPointMessage(gpu::SyncPointManager* sync_point_manager, - const IPC::Message& message, + bool GenerateSyncPointMessage(const IPC::Message& message, bool retire_sync_point, uint32_t* sync_point_number); - void DeleteAndDisableMessages(GpuChannelManager* gpu_channel_manager); + void DeleteAndDisableMessages(); private: friend class base::RefCountedThreadSafe<GpuChannelMessageQueue>; GpuChannelMessageQueue(const base::WeakPtr<GpuChannel>& gpu_channel, - base::SingleThreadTaskRunner* task_runner); + base::SingleThreadTaskRunner* task_runner, + gpu::SyncPointManager* sync_point_manager); ~GpuChannelMessageQueue(); void ScheduleHandleMessage(); - void PushMessageHelper(gpu::SyncPointManager* sync_point_manager, - scoped_ptr<GpuChannelMessage> msg); + void PushMessageHelper(scoped_ptr<GpuChannelMessage> msg); bool enabled_; @@ -465,6 +467,7 @@ base::WeakPtr<GpuChannel> gpu_channel_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + gpu::SyncPointManager* sync_point_manager_; DISALLOW_COPY_AND_ASSIGN(GpuChannelMessageQueue); };
diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index eec5185..4d9c4351 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc
@@ -163,11 +163,11 @@ bool preempts, bool allow_future_sync_points, bool allow_real_time_streams) { - return make_scoped_ptr( - new GpuChannel(this, watchdog_, share_group(), mailbox_manager(), - preempts ? preemption_flag() : nullptr, task_runner_.get(), - io_task_runner_.get(), client_id, client_tracing_id, - allow_future_sync_points, allow_real_time_streams)); + return make_scoped_ptr(new GpuChannel( + this, sync_point_manager(), watchdog_, share_group(), mailbox_manager(), + preempts ? preemption_flag() : nullptr, task_runner_.get(), + io_task_runner_.get(), client_id, client_tracing_id, + allow_future_sync_points, allow_real_time_streams)); } void GpuChannelManager::OnEstablishChannel(
diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index f2674f3..19cec9d 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h
@@ -95,10 +95,6 @@ GpuChannel* LookupChannel(int32 client_id) const; - gpu::SyncPointManager* sync_point_manager() { - return sync_point_manager_; - } - gfx::GLSurface* GetDefaultOffscreenSurface(); GpuMemoryBufferFactory* gpu_memory_buffer_factory() { @@ -124,6 +120,10 @@ bool allow_future_sync_points, bool allow_real_time_streams); + gpu::SyncPointManager* sync_point_manager() const { + return sync_point_manager_; + } + gfx::GLShareGroup* share_group() const { return share_group_.get(); } gpu::gles2::MailboxManager* mailbox_manager() const { return mailbox_manager_.get();
diff --git a/content/common/gpu/gpu_channel_test_common.cc b/content/common/gpu/gpu_channel_test_common.cc index d2e236e..7fe0375 100644 --- a/content/common/gpu/gpu_channel_test_common.cc +++ b/content/common/gpu/gpu_channel_test_common.cc
@@ -43,7 +43,7 @@ bool allow_future_sync_points, bool allow_real_time_streams) { return make_scoped_ptr(new TestGpuChannel( - sink_, this, share_group(), mailbox_manager(), + sink_, this, sync_point_manager(), share_group(), mailbox_manager(), preempts ? preemption_flag() : nullptr, task_runner_.get(), io_task_runner_.get(), client_id, client_tracing_id, allow_future_sync_points, allow_real_time_streams)); @@ -51,6 +51,7 @@ TestGpuChannel::TestGpuChannel(IPC::TestSink* sink, GpuChannelManager* gpu_channel_manager, + gpu::SyncPointManager* sync_point_manager, gfx::GLShareGroup* share_group, gpu::gles2::MailboxManager* mailbox_manager, gpu::PreemptionFlag* preempting_flag, @@ -61,6 +62,7 @@ bool allow_future_sync_points, bool allow_real_time_streams) : GpuChannel(gpu_channel_manager, + sync_point_manager, nullptr, share_group, mailbox_manager,
diff --git a/content/common/gpu/gpu_channel_test_common.h b/content/common/gpu/gpu_channel_test_common.h index dd95f17..33d92fc6 100644 --- a/content/common/gpu/gpu_channel_test_common.h +++ b/content/common/gpu/gpu_channel_test_common.h
@@ -47,6 +47,7 @@ public: TestGpuChannel(IPC::TestSink* sink, GpuChannelManager* gpu_channel_manager, + gpu::SyncPointManager* sync_point_manager, gfx::GLShareGroup* share_group, gpu::gles2::MailboxManager* mailbox_manager, gpu::PreemptionFlag* preempting_flag,
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 381f354a..2115049b 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -24,8 +24,8 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "gpu/command_buffer/common/constants.h" -#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gl_state_restorer_impl.h" #include "gpu/command_buffer/service/image_factory.h" @@ -175,6 +175,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( GpuChannel* channel, + gpu::SyncPointManager* sync_point_manager, base::SingleThreadTaskRunner* task_runner, GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, @@ -192,6 +193,7 @@ GpuWatchdog* watchdog, const GURL& active_url) : channel_(channel), + sync_point_manager_(sync_point_manager), task_runner_(task_runner), initialized_(false), handle_(handle), @@ -529,14 +531,11 @@ GpuChannelManager* manager = channel_->gpu_channel_manager(); DCHECK(manager); - gpu::SyncPointManager* sync_point_manager = manager->sync_point_manager(); - DCHECK(sync_point_manager); - decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group_.get())); scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(), decoder_.get(), decoder_.get())); - sync_point_client_ = sync_point_manager->CreateSyncPointClient( + sync_point_client_ = sync_point_manager_->CreateSyncPointClient( channel_->GetSyncPointOrderData(), gpu::CommandBufferNamespace::GPU_IO, command_buffer_id_); @@ -940,13 +939,13 @@ // We can simply use the global sync point number as the release count with // 0 for the command buffer ID (under normal circumstances 0 is invalid so // will not be used) until the old sync points are replaced. - gpu::gles2::SyncToken sync_token = {gpu::CommandBufferNamespace::GPU_IO, 0, - sync_point}; + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, + 0, + sync_point); mailbox_manager->PushTextureUpdates(sync_token); } - GpuChannelManager* manager = channel_->gpu_channel_manager(); - manager->sync_point_manager()->RetireSyncPoint(sync_point); + sync_point_manager_->RetireSyncPoint(sync_point); } bool GpuCommandBufferStub::OnWaitSyncPoint(uint32 sync_point) { @@ -954,8 +953,7 @@ DCHECK(scheduler_->scheduled()); if (!sync_point) return true; - GpuChannelManager* manager = channel_->gpu_channel_manager(); - if (manager->sync_point_manager()->IsSyncPointRetired(sync_point)) { + if (sync_point_manager_->IsSyncPointRetired(sync_point)) { // Old sync points are global and do not have a command buffer ID, // We can simply use the global sync point number as the release count with // 0 for the command buffer ID (under normal circumstances 0 is invalid so @@ -969,7 +967,7 @@ scheduler_->SetScheduled(false); waiting_for_sync_point_ = true; - manager->sync_point_manager()->AddSyncPointCallback( + sync_point_manager_->AddSyncPointCallback( sync_point, base::Bind(&RunOnThread, task_runner_, base::Bind(&GpuCommandBufferStub::OnWaitSyncPointCompleted, @@ -998,15 +996,13 @@ gpu::gles2::MailboxManager* mailbox_manager = context_group_->mailbox_manager(); if (mailbox_manager->UsesSync() && MakeCurrent()) { - gpu::gles2::SyncToken sync_token = {namespace_id, command_buffer_id, - release}; + gpu::SyncToken sync_token(namespace_id, command_buffer_id, release); mailbox_manager->PullTextureUpdates(sync_token); } } void GpuCommandBufferStub::OnSignalSyncPoint(uint32 sync_point, uint32 id) { - GpuChannelManager* manager = channel_->gpu_channel_manager(); - manager->sync_point_manager()->AddSyncPointCallback( + sync_point_manager_->AddSyncPointCallback( sync_point, base::Bind(&RunOnThread, task_runner_, base::Bind(&GpuCommandBufferStub::OnSignalSyncPointAck, @@ -1045,8 +1041,9 @@ gpu::gles2::MailboxManager* mailbox_manager = context_group_->mailbox_manager(); if (mailbox_manager->UsesSync() && MakeCurrent()) { - gpu::gles2::SyncToken sync_token = {gpu::CommandBufferNamespace::GPU_IO, - command_buffer_id_, release}; + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, + command_buffer_id_, + release); mailbox_manager->PushTextureUpdates(sync_token); } @@ -1060,15 +1057,9 @@ DCHECK(!waiting_for_sync_point_); DCHECK(scheduler_->scheduled()); - GpuChannelManager* manager = channel_->gpu_channel_manager(); - DCHECK(manager); - - gpu::SyncPointManager* sync_point_manager = manager->sync_point_manager(); - DCHECK(sync_point_manager); - scoped_refptr<gpu::SyncPointClientState> release_state = - sync_point_manager->GetSyncPointClientState(namespace_id, - command_buffer_id); + sync_point_manager_->GetSyncPointClientState(namespace_id, + command_buffer_id); if (!release_state) return true;
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h index b139a78..3ac3840 100644 --- a/content/common/gpu/gpu_command_buffer_stub.h +++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -35,6 +35,7 @@ namespace gpu { struct Mailbox; class SyncPointClient; +class SyncPointManager; class ValueStateMap; namespace gles2 { class MailboxManager; @@ -70,6 +71,7 @@ GpuCommandBufferStub( GpuChannel* channel, + gpu::SyncPointManager* sync_point_manager, base::SingleThreadTaskRunner* task_runner, GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, @@ -250,6 +252,9 @@ // are destroyed. So a raw pointer is safe. GpuChannel* channel_; + // Outlives the stub. + gpu::SyncPointManager* sync_point_manager_; + // Task runner for main thread. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/content/common/gpu/gpu_memory_buffer_factory.h b/content/common/gpu/gpu_memory_buffer_factory.h index 7edb0e4..3054075e 100644 --- a/content/common/gpu/gpu_memory_buffer_factory.h +++ b/content/common/gpu/gpu_memory_buffer_factory.h
@@ -45,6 +45,15 @@ int client_id, gfx::PluginWindowHandle surface_handle) = 0; + // Creates a new GPU memory buffer instance from an existing handle. A valid + // handle is returned on success. It can be called on any thread. + virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) = 0; + // Destroys GPU memory buffer identified by |id|. // It can be called on any thread. virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
diff --git a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc index a6b41f3..7590f32 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
@@ -175,6 +175,17 @@ return handle; } +gfx::GpuMemoryBufferHandle +GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) { + NOTIMPLEMENTED(); + return gfx::GpuMemoryBufferHandle(); +} + void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer( gfx::GpuMemoryBufferId id, int client_id) {
diff --git a/content/common/gpu/gpu_memory_buffer_factory_io_surface.h b/content/common/gpu/gpu_memory_buffer_factory_io_surface.h index 1cafa79..05db205 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_io_surface.h +++ b/content/common/gpu/gpu_memory_buffer_factory_io_surface.h
@@ -47,6 +47,12 @@ gfx::BufferUsage usage, int client_id, gfx::PluginWindowHandle surface_handle) override; + gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) override; void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id) override; gpu::ImageFactory* AsImageFactory() override;
diff --git a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc index 952e6c50..c7030d1 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc
@@ -64,6 +64,17 @@ return handle; } +gfx::GpuMemoryBufferHandle +GpuMemoryBufferFactoryOzoneNativePixmap::CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) { + NOTIMPLEMENTED(); + return gfx::GpuMemoryBufferHandle(); +} + void GpuMemoryBufferFactoryOzoneNativePixmap::DestroyGpuMemoryBuffer( gfx::GpuMemoryBufferId id, int client_id) {
diff --git a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h index 19f35c1a..e3b53a2a 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h +++ b/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h
@@ -36,6 +36,12 @@ gfx::BufferUsage usage, int client_id, gfx::PluginWindowHandle surface_handle) override; + gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) override; void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id) override; gpu::ImageFactory* AsImageFactory() override;
diff --git a/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc b/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc index 3648817d..e745e348 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc
@@ -66,6 +66,17 @@ return handle; } +gfx::GpuMemoryBufferHandle +GpuMemoryBufferFactorySurfaceTexture::CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) { + NOTIMPLEMENTED(); + return gfx::GpuMemoryBufferHandle(); +} + void GpuMemoryBufferFactorySurfaceTexture::DestroyGpuMemoryBuffer( gfx::GpuMemoryBufferId id, int client_id) {
diff --git a/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h b/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h index 57c3cd9a..1696df3 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h +++ b/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h
@@ -41,6 +41,12 @@ gfx::BufferUsage usage, int client_id, gfx::PluginWindowHandle surface_handle) override; + gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + int client_id) override; void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id) override; gpu::ImageFactory* AsImageFactory() override;
diff --git a/content/common/gpu/image_transport_surface_overlay_mac.mm b/content/common/gpu/image_transport_surface_overlay_mac.mm index 1a18d0b..d0e14067 100644 --- a/content/common/gpu/image_transport_surface_overlay_mac.mm +++ b/content/common/gpu/image_transport_surface_overlay_mac.mm
@@ -362,8 +362,7 @@ dip_damage_rect.Subtract(plane->dip_frame_rect); ScopedCAActionDisabler disabler; - if (swap->root_plane.get()) - UpdateRootAndPartialDamagePlanes(swap->root_plane, dip_damage_rect); + UpdateRootAndPartialDamagePlanes(swap->root_plane, dip_damage_rect); UpdateOverlayPlanes(swap->overlay_planes); UpdateCALayerTree(); swap->overlay_planes.clear(); @@ -410,6 +409,16 @@ old_partial_damage_planes.swap(current_partial_damage_planes_); linked_ptr<OverlayPlane> plane_for_swap; + // If there is no new root plane, destroy the old one. + if (!new_root_plane.get()) { + for (auto& old_plane : old_partial_damage_planes) + old_plane->Destroy(); + if (current_root_plane_.get()) + current_root_plane_->Destroy(); + current_root_plane_.reset(); + return; + } + // If the frame's size changed, if we haven't updated the root layer, or if // we have full damage, then use the root layer directly. if (!current_root_plane_.get() ||
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc index a33bc22..6114331 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.cc +++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -1283,7 +1283,7 @@ return; } } - TRACE_EVENT_END_ETW("DXVAVideoDecodeAccelerator.Decoding", this, ""); + TRACE_EVENT_ASYNC_END0("gpu", "DXVAVideoDecodeAccelerator.Decoding", this); TRACE_COUNTER1("DXVA Decoding", "TotalPacketsBeforeDecode", inputs_before_decode_); @@ -1613,7 +1613,8 @@ } if (!inputs_before_decode_) { - TRACE_EVENT_BEGIN_ETW("DXVAVideoDecodeAccelerator.Decoding", this, ""); + TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", + this); } inputs_before_decode_++;
diff --git a/content/common/gpu/media/vt_video_decode_accelerator.cc b/content/common/gpu/media/vt_video_decode_accelerator.cc index c98853dd..722a969 100644 --- a/content/common/gpu/media/vt_video_decode_accelerator.cc +++ b/content/common/gpu/media/vt_video_decode_accelerator.cc
@@ -22,6 +22,7 @@ #include "media/base/limits.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_image_io_surface.h" +#include "ui/gl/gl_implementation.h" #include "ui/gl/scoped_binders.h" using content_common_gpu_media::kModuleVt; @@ -1019,7 +1020,8 @@ } IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get()); - glEnable(GL_TEXTURE_RECTANGLE_ARB); + if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile) + glEnable(GL_TEXTURE_RECTANGLE_ARB); gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_RECTANGLE_ARB, picture_info->service_texture_id); CGLContextObj cgl_context = @@ -1034,7 +1036,8 @@ GL_UNSIGNED_SHORT_8_8_APPLE, // type surface, // io_surface 0); // plane - glDisable(GL_TEXTURE_RECTANGLE_ARB); + if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile) + glDisable(GL_TEXTURE_RECTANGLE_ARB); if (status != kCGLNoError) { NOTIFY_STATUS("CGLTexImageIOSurface2D()", status, SFT_PLATFORM_ERROR); return false;
diff --git a/content/common/mojo/channel_init.cc b/content/common/mojo/channel_init.cc index e81515c..39aa1d05 100644 --- a/content/common/mojo/channel_init.cc +++ b/content/common/mojo/channel_init.cc
@@ -42,13 +42,6 @@ mojo::embedder::WillDestroyChannelSoon(channel_info_); } -void ChannelInit::ShutdownOnIOThread() { - if (channel_info_) - mojo::embedder::DestroyChannelOnIOThread(channel_info_); - channel_info_ = nullptr; - ipc_support_.reset(); -} - // static void ChannelInit::OnCreatedChannel( base::WeakPtr<ChannelInit> self,
diff --git a/content/common/mojo/channel_init.h b/content/common/mojo/channel_init.h index 2660a7b..6a9f5bfc 100644 --- a/content/common/mojo/channel_init.h +++ b/content/common/mojo/channel_init.h
@@ -35,9 +35,6 @@ // Notifies the channel that we (hence it) will soon be destroyed. void WillDestroySoon(); - // Shuts down the channel. Must be called from the IO thread. - void ShutdownOnIOThread(); - private: // Invoked on the thread on which this object lives once the channel has been // established. This is a static method that takes a weak pointer to self,
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index acc71de4..d1a1886 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -655,7 +655,7 @@ *base::CommandLine::ForCurrentProcess(); std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType); - TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess", 0, type_str); + TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); // Propagate the --allow-no-job flag if present. if (browser_command_line.HasSwitch(switches::kAllowNoSandboxJob) && @@ -797,17 +797,16 @@ return base::Process(); } - TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); + TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); PROCESS_INFORMATION temp_process_info = {}; result = g_broker_services->SpawnTarget( - cmd_line->GetProgram().value().c_str(), - cmd_line->GetCommandLineString().c_str(), - policy, &temp_process_info); + cmd_line->GetProgram().value().c_str(), + cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); DWORD last_error = ::GetLastError(); base::win::ScopedProcessInformation target(temp_process_info); - TRACE_EVENT_END_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); + TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); if (sandbox::SBOX_ALL_OK != result) { if (result == sandbox::SBOX_ERROR_GENERIC) @@ -833,7 +832,6 @@ delegate->PostSpawnTarget(target.process_handle()); CHECK(ResumeThread(target.thread_handle()) != -1); - TRACE_EVENT_END_ETW("StartProcessWithAccess", 0, type_str); return base::Process(target.TakeProcessHandle()); }
diff --git a/content/common/site_isolation_policy.cc b/content/common/site_isolation_policy.cc index afe4f14..d36786e 100644 --- a/content/common/site_isolation_policy.cc +++ b/content/common/site_isolation_policy.cc
@@ -73,7 +73,7 @@ // static bool SiteIsolationPolicy::IsSwappedOutStateForbidden() { - return AreCrossProcessFramesPossible(); + return true; } // static
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index a2b2be9..9cd395f 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -1379,6 +1379,8 @@ 'browser/service_worker/embedded_worker_instance.h', 'browser/service_worker/embedded_worker_registry.cc', 'browser/service_worker/embedded_worker_registry.h', + 'browser/service_worker/service_worker_cache_writer.cc', + 'browser/service_worker/service_worker_cache_writer.h', 'browser/service_worker/service_worker_context_core.cc', 'browser/service_worker/service_worker_context_core.h', 'browser/service_worker/service_worker_context_observer.h',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index f626594e..d93e029 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -560,6 +560,7 @@ 'browser/service_worker/embedded_worker_instance_unittest.cc', 'browser/service_worker/embedded_worker_test_helper.cc', 'browser/service_worker/embedded_worker_test_helper.h', + 'browser/service_worker/service_worker_cache_writer_unittest.cc', 'browser/service_worker/service_worker_context_request_handler_unittest.cc', 'browser/service_worker/service_worker_context_unittest.cc', 'browser/service_worker/service_worker_controllee_request_handler_unittest.cc',
diff --git a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java index 390ab99d..fd7da07 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java +++ b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
@@ -14,6 +14,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeClassQualifiedName; import org.chromium.net.NetworkChangeNotifierAutoDetect; +import org.chromium.net.RegistrationPolicyAlwaysRegister; import java.util.ArrayList; import java.util.List; @@ -73,8 +74,8 @@ // Create the NetworkChangeNotifierAutoDetect if it does not exist already. if (mNotifier == null) { - mNotifier = - new NetworkChangeNotifierAutoDetect(this, mContext, true /* always listen */); + mNotifier = new NetworkChangeNotifierAutoDetect(this, mContext, + new RegistrationPolicyAlwaysRegister()); } mNativePtrs.add(nativePtr);
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 1f60a547..7835908 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -232,6 +232,11 @@ } @Override + public boolean focusLocationBarByDefault() { + return nativeFocusLocationBarByDefault(mNativeWebContentsAndroid); + } + + @Override public boolean isReady() { return nativeIsRenderWidgetHostViewReady(mNativeWebContentsAndroid); } @@ -426,6 +431,7 @@ private native void nativeShowInterstitialPage(long nativeWebContentsAndroid, String url, long nativeInterstitialPageDelegateAndroid); private native boolean nativeIsShowingInterstitialPage(long nativeWebContentsAndroid); + private native boolean nativeFocusLocationBarByDefault(long nativeWebContentsAndroid); private native boolean nativeIsRenderWidgetHostViewReady(long nativeWebContentsAndroid); private native void nativeExitFullscreen(long nativeWebContentsAndroid); private native void nativeUpdateTopControlsState(long nativeWebContentsAndroid,
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java index 99a5cb9..2cc9e5f 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -140,6 +140,11 @@ boolean isShowingInterstitialPage(); /** + * @return Whether the location bar should be focused by default for this page. + */ + boolean focusLocationBarByDefault(); + + /** * If the view is ready to draw contents to the screen. In hardware mode, * the initialization of the surface texture may not occur until after the * view has been added to the layout. This method will return {@code true}
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 245776d..973cfe2 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -216,10 +216,6 @@ return nullptr; } -std::string ContentRendererClient::GetUserAgentOverrideForURL(const GURL& url) { - return std::string(); -} - scoped_ptr<blink::WebAppBannerClient> ContentRendererClient::CreateAppBannerClient(RenderFrame* render_frame) { return nullptr;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 5adc6ff..8b385814 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -289,10 +289,6 @@ // Returns true if dev channel APIs are available for plugins. virtual bool IsPluginAllowedToUseDevChannelAPIs(); - // Returns a user agent override specific for |url|, or empty string if - // default user agent should be used. - virtual std::string GetUserAgentOverrideForURL(const GURL& url); - // Records a sample string to a Rappor privacy-preserving metric. // See: https://www.chromium.org/developers/design-documents/rappor virtual void RecordRappor(const std::string& metric,
diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc index b7e92302..63f256d 100644 --- a/content/renderer/media/android/webmediaplayer_android.cc +++ b/content/renderer/media/android/webmediaplayer_android.cc
@@ -538,10 +538,6 @@ double WebMediaPlayerAndroid::duration() const { DCHECK(main_thread_checker_.CalledOnValidThread()); - // HTML5 spec requires duration to be NaN if readyState is HAVE_NOTHING - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) - return std::numeric_limits<double>::quiet_NaN(); - if (duration_ == media::kInfiniteDuration()) return std::numeric_limits<double>::infinity();
diff --git a/content/renderer/media/media_recorder_handler.cc b/content/renderer/media/media_recorder_handler.cc index 6fee4603..f8d9de12 100644 --- a/content/renderer/media/media_recorder_handler.cc +++ b/content/renderer/media/media_recorder_handler.cc
@@ -32,8 +32,9 @@ bool MediaRecorderHandler::canSupportMimeType( const blink::WebString& mimeType) { DCHECK(main_render_thread_checker_.CalledOnValidThread()); - // TODO(mcasas): For the time being only empty or "video/vp8" are supported. - return mimeType.isEmpty() || mimeType.utf8().compare("video/vp8") == 0; + // TODO(mcasas): So far only empty or "video/vp{8,9}" are supported. + return mimeType.isEmpty() || mimeType.utf8().compare("video/vp8") == 0 || + mimeType.utf8().compare("video/vp9") == 0; } bool MediaRecorderHandler::initialize( @@ -49,6 +50,7 @@ DLOG(ERROR) << "Can't support type " << mimeType.utf8(); return false; } + use_vp9_ = mimeType.utf8().compare("video/vp9") == 0; media_stream_ = media_stream; DCHECK(client); client_ = client; @@ -68,8 +70,10 @@ DCHECK(!media_stream_.isNull()); DCHECK(!webm_muxer_); - webm_muxer_.reset(new media::WebmMuxer(base::Bind( - &MediaRecorderHandler::WriteData, weak_factory_.GetWeakPtr()))); + webm_muxer_.reset( + new media::WebmMuxer(use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, + base::Bind(&MediaRecorderHandler::WriteData, + weak_factory_.GetWeakPtr()))); blink::WebVector<blink::WebMediaStreamTrack> video_tracks; media_stream_.videoTracks(video_tracks); @@ -93,7 +97,8 @@ media::BindToCurrentLoop(base::Bind(&MediaRecorderHandler::OnEncodedVideo, weak_factory_.GetWeakPtr())); - video_recorders_.push_back(new VideoTrackRecorder(video_track, + video_recorders_.push_back(new VideoTrackRecorder(use_vp9_, + video_track, on_encoded_video_cb)); recording_ = true;
diff --git a/content/renderer/media/media_recorder_handler.h b/content/renderer/media/media_recorder_handler.h index db6b12b..4d1e519 100644 --- a/content/renderer/media/media_recorder_handler.h +++ b/content/renderer/media/media_recorder_handler.h
@@ -70,6 +70,9 @@ // Bound to the main render thread. base::ThreadChecker main_render_thread_checker_; + // Force using VP9 for video encoding, otherwise VP8 will be used by default. + bool use_vp9_; + bool recording_; blink::WebMediaStream media_stream_; // The MediaStream being recorded.
diff --git a/content/renderer/media/media_recorder_handler_unittest.cc b/content/renderer/media/media_recorder_handler_unittest.cc index 12870f06..b3ac9d1 100644 --- a/content/renderer/media/media_recorder_handler_unittest.cc +++ b/content/renderer/media/media_recorder_handler_unittest.cc
@@ -19,6 +19,8 @@ using ::testing::InSequence; using ::testing::Lt; using ::testing::Mock; +using ::testing::TestWithParam; +using ::testing::ValuesIn; using blink::WebString; @@ -31,9 +33,18 @@ static const std::string kTestStreamUrl = "stream_url"; static const std::string kTestVideoTrackId = "video_track_id"; -class MediaRecorderHandlerTest - : public testing::Test - , public blink::WebMediaRecorderHandlerClient { +struct MediaRecorderTestParams { + const char* const mime_type; + const size_t first_encoded_frame_size; + const size_t second_encoded_frame_size; +}; + +static const MediaRecorderTestParams kMediaRecorderTestParams[] = { + {"video/vp8", 52, 32}, + {"video/vp9", 33, 18}}; + +class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>, + public blink::WebMediaRecorderHandlerClient { public: MediaRecorderHandlerTest() : media_recorder_handler_(new MediaRecorderHandler()) { @@ -79,8 +90,11 @@ // Checks that canSupportMimeType() works as expected. // TODO(mcasas): revisit this when canSupportMimeType() is fully implemented. TEST_F(MediaRecorderHandlerTest, CanSupportMimeType) { - const WebString good_mime_type(base::UTF8ToUTF16("video/vp8")); - EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type)); + const WebString good_mime_type_vp8(base::UTF8ToUTF16("video/vp8")); + EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp8)); + + const WebString good_mime_type_vp9(base::UTF8ToUTF16("video/vp9")); + EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp9)); const WebString bad_mime_type(base::UTF8ToUTF16("video/unsupportedcodec")); EXPECT_FALSE(media_recorder_handler_->canSupportMimeType(bad_mime_type)); @@ -90,11 +104,11 @@ } // Checks that the initialization-destruction sequence works fine. -TEST_F(MediaRecorderHandlerTest, InitializeStartStop) { - const WebString mime_type(base::UTF8ToUTF16("")); +TEST_P(MediaRecorderHandlerTest, InitializeStartStop) { + const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); EXPECT_TRUE(media_recorder_handler_->initialize(this, - registry_.test_stream(), - mime_type)); + registry_.test_stream(), + mime_type)); EXPECT_FALSE(recording()); EXPECT_FALSE(hasVideoRecorders()); @@ -112,8 +126,8 @@ } // Sends 2 frames and expect them as WebM contained encoded data in writeData(). -TEST_F(MediaRecorderHandlerTest, EncodeVideoFrames) { - const WebString mime_type(base::UTF8ToUTF16("video/vp8")); +TEST_P(MediaRecorderHandlerTest, EncodeVideoFrames) { + const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(), mime_type)); EXPECT_TRUE(media_recorder_handler_->start()); @@ -127,10 +141,10 @@ base::Closure quit_closure = run_loop.QuitClosure(); // writeData() is pinged a number of times as the WebM header is written; // the last time it is called it has the encoded data. - const size_t kEncodedDataSize = 52; - EXPECT_CALL(*this, writeData(_, Lt(kEncodedDataSize), false)) + const size_t encoded_data_size = GetParam().first_encoded_frame_size; + EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), false)) .Times(AtLeast(1)); - EXPECT_CALL(*this, writeData(_, kEncodedDataSize, false)) + EXPECT_CALL(*this, writeData(_, encoded_data_size, false)) .Times(1) .WillOnce(RunClosure(quit_closure)); @@ -143,10 +157,10 @@ base::Closure quit_closure = run_loop.QuitClosure(); // The second time around writeData() is called a number of times to write // the WebM frame header, and then is pinged with the encoded data. - const size_t kSecondEncodedDataSize = 32; - EXPECT_CALL(*this, writeData(_, Lt(kSecondEncodedDataSize), false)) + const size_t encoded_data_size = GetParam().second_encoded_frame_size; + EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), false)) .Times(AtLeast(1)); - EXPECT_CALL(*this, writeData(_, kSecondEncodedDataSize, false)) + EXPECT_CALL(*this, writeData(_, encoded_data_size, false)) .Times(1) .WillOnce(RunClosure(quit_closure)); @@ -161,4 +175,8 @@ media_recorder_handler_.reset(); } +INSTANTIATE_TEST_CASE_P(, + MediaRecorderHandlerTest, + ValuesIn(kMediaRecorderTestParams)); + } // namespace content
diff --git a/content/renderer/media/video_track_recorder.cc b/content/renderer/media/video_track_recorder.cc index 52368b3..a2755bdd 100644 --- a/content/renderer/media/video_track_recorder.cc +++ b/content/renderer/media/video_track_recorder.cc
@@ -75,7 +75,7 @@ static void ShutdownEncoder(scoped_ptr<base::Thread> encoding_thread, ScopedVpxCodecCtxPtr encoder); - explicit VpxEncoder(const OnEncodedVideoCB& on_encoded_video_callback); + VpxEncoder(bool use_vp9, const OnEncodedVideoCB& on_encoded_video_callback); void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, base::TimeTicks capture_timestamp); @@ -87,7 +87,7 @@ void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame, base::TimeTicks capture_timestamp); - void ConfigureVp8Encoding(const gfx::Size& size); + void ConfigureEncoding(const gfx::Size& size); // Returns true if |codec_config_| has been filled in at least once. bool IsInitialized() const; @@ -96,6 +96,9 @@ base::TimeDelta CalculateFrameDuration( const scoped_refptr<VideoFrame>& frame); + // Force usage of VP9 for encoding, instead of VP8 which is the default. + const bool use_vp9_; + // Used to shutdown properly on the same thread we were created. const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; @@ -131,8 +134,10 @@ } VideoTrackRecorder::VpxEncoder::VpxEncoder( + bool use_vp9, const OnEncodedVideoCB& on_encoded_video_callback) - : main_task_runner_(base::MessageLoop::current()->task_runner()), + : use_vp9_(use_vp9), + main_task_runner_(base::MessageLoop::current()->task_runner()), on_encoded_video_callback_(on_encoded_video_callback), encoding_thread_(new base::Thread("EncodingThread")) { DCHECK(!on_encoded_video_callback_.is_null()); @@ -173,7 +178,7 @@ const gfx::Size frame_size = frame->visible_rect().size(); if (!IsInitialized() || gfx::Size(codec_config_.g_w, codec_config_.g_h) != frame_size) { - ConfigureVp8Encoding(frame_size); + ConfigureEncoding(frame_size); } vpx_image_t vpx_image; @@ -225,19 +230,19 @@ keyframe)); } -void VideoTrackRecorder::VpxEncoder::ConfigureVp8Encoding( - const gfx::Size& size) { +void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) { if (IsInitialized()) { // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less- // than-or-equal than the old size, in terms of area, the existing encoder // instance could be reused after changing |codec_config_.{g_w,g_h}|. DVLOG(1) << "Destroying/Re-Creating encoder for new frame size: " << gfx::Size(codec_config_.g_w, codec_config_.g_h).ToString() - << " --> " << size.ToString(); + << " --> " << size.ToString() << (use_vp9_ ? " vp9" : " vp8"); encoder_.reset(); } - const vpx_codec_iface_t* interface = vpx_codec_vp8_cx(); + const vpx_codec_iface_t* interface = + use_vp9_ ? vpx_codec_vp9_cx() : vpx_codec_vp8_cx(); const vpx_codec_err_t result = vpx_codec_enc_config_default(interface, &codec_config_, 0 /* reserved */); @@ -248,7 +253,20 @@ DCHECK_EQ(240u, codec_config_.g_h); DCHECK_EQ(256u, codec_config_.rc_target_bitrate); codec_config_.rc_target_bitrate = size.GetArea() * - codec_config_.rc_target_bitrate / codec_config_.g_w / codec_config_.g_h; + codec_config_.rc_target_bitrate / + codec_config_.g_w / codec_config_.g_h; + // Both VP8/VP9 configuration should be Variable BitRate by default. + DCHECK_EQ(VPX_VBR, codec_config_.rc_end_usage); + if (use_vp9_) { + // Number of frames to consume before producing output. + codec_config_.g_lag_in_frames = 0; + + // DCHECK that the profile selected by default is I420 (magic number 0). + DCHECK_EQ(0u, codec_config_.g_profile); + } else { + // VP8 always produces frames instantaneously. + DCHECK_EQ(0u, codec_config_.g_lag_in_frames); + } DCHECK(size.width()); DCHECK(size.height()); @@ -318,10 +336,11 @@ } VideoTrackRecorder::VideoTrackRecorder( + bool use_vp9, const blink::WebMediaStreamTrack& track, const OnEncodedVideoCB& on_encoded_video_callback) : track_(track), - encoder_(new VpxEncoder(on_encoded_video_callback)) { + encoder_(new VpxEncoder(use_vp9, on_encoded_video_callback)) { DCHECK(main_render_thread_checker_.CalledOnValidThread()); DCHECK(!track_.isNull()); DCHECK(track_.extraData());
diff --git a/content/renderer/media/video_track_recorder.h b/content/renderer/media/video_track_recorder.h index 7148765..49b5cbe 100644 --- a/content/renderer/media/video_track_recorder.h +++ b/content/renderer/media/video_track_recorder.h
@@ -32,7 +32,9 @@ base::TimeTicks capture_timestamp, bool is_key_frame)>; - VideoTrackRecorder(const blink::WebMediaStreamTrack& track, + // |use_vp9| forces using VP9, otherwise VP8 will be used by default. + VideoTrackRecorder(bool use_vp9, + const blink::WebMediaStreamTrack& track, const OnEncodedVideoCB& on_encoded_video_cb); ~VideoTrackRecorder() override;
diff --git a/content/renderer/media/video_track_recorder_unittest.cc b/content/renderer/media/video_track_recorder_unittest.cc index 791beb1f..ddddf2bb 100644 --- a/content/renderer/media/video_track_recorder_unittest.cc +++ b/content/renderer/media/video_track_recorder_unittest.cc
@@ -19,12 +19,16 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebHeap.h" +using media::VideoFrame; + using ::testing::_; using ::testing::DoAll; using ::testing::InSequence; using ::testing::Mock; using ::testing::Return; using ::testing::SaveArg; +using ::testing::TestWithParam; +using ::testing::ValuesIn; namespace content { @@ -32,19 +36,17 @@ closure.Run(); } -// Dummy interface class to be able to MOCK its methods. -class EncodedVideoHandlerInterface { - public: - virtual void OnEncodedVideo( - const scoped_refptr<media::VideoFrame>& video_frame, - scoped_ptr<std::string> encoded_data, - base::TimeTicks timestamp, - bool is_key_frame) = 0; - virtual ~EncodedVideoHandlerInterface() {} +struct TrackRecorderTestParams { + const bool use_vp9; + const size_t first_encoded_frame_size; + const size_t second_encoded_frame_size; + const size_t third_encoded_frame_size; }; -class VideoTrackRecorderTest : public testing::Test, - public EncodedVideoHandlerInterface { +const TrackRecorderTestParams kTrackRecorderTestParams[] = {{false, 52, 32, 57}, + {true, 33, 18, 33}}; + +class VideoTrackRecorderTest : public TestWithParam<TrackRecorderTestParams> { public: VideoTrackRecorderTest() : mock_source_(new MockMediaStreamVideoSource(false)) { @@ -63,10 +65,10 @@ blink_track_.setExtraData(track_); video_track_recorder_.reset(new VideoTrackRecorder( + GetParam().use_vp9 /* use_vp9 */, blink_track_, base::Bind(&VideoTrackRecorderTest::OnEncodedVideo, base::Unretained(this)))); - // Paranoia checks. EXPECT_EQ(blink_track_.source().extraData(), blink_source_.extraData()); EXPECT_TRUE(message_loop_.IsCurrent()); @@ -80,19 +82,18 @@ } MOCK_METHOD4(DoOnEncodedVideo, - void(const scoped_refptr<media::VideoFrame>& frame, + void(const scoped_refptr<VideoFrame>& frame, std::string encoded_data, base::TimeTicks timestamp, bool keyframe)); - void OnEncodedVideo( - const scoped_refptr<media::VideoFrame>& video_frame, - scoped_ptr<std::string> encoded_data, - base::TimeTicks timestamp, - bool is_key_frame) override { + void OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame, + scoped_ptr<std::string> encoded_data, + base::TimeTicks timestamp, + bool is_key_frame) { DoOnEncodedVideo(video_frame, *encoded_data, timestamp, is_key_frame); } - void Encode(const scoped_refptr<media::VideoFrame>& frame, + void Encode(const scoped_refptr<VideoFrame>& frame, base::TimeTicks capture_time) { EXPECT_TRUE(message_loop_.IsCurrent()); video_track_recorder_->OnVideoFrameForTesting(frame, capture_time); @@ -118,16 +119,16 @@ // Construct and destruct all objects, in particular |video_track_recorder_| and // its inner object(s). This is a non trivial sequence. -TEST_F(VideoTrackRecorderTest, ConstructAndDestruct) {} +TEST_P(VideoTrackRecorderTest, ConstructAndDestruct) {} // Creates the encoder and encodes 2 frames of the same size; the encoder should // be initialised and produce a keyframe, then a non-keyframe. Finally a frame // of larger size is sent and is expected to be encoded as a keyframe. -TEST_F(VideoTrackRecorderTest, VideoEncoding) { +TEST_P(VideoTrackRecorderTest, VideoEncoding) { // |frame_size| cannot be arbitrarily small, should be reasonable. const gfx::Size frame_size(160, 80); - const scoped_refptr<media::VideoFrame> video_frame = - media::VideoFrame::CreateBlackFrame(frame_size); + const scoped_refptr<VideoFrame> video_frame = + VideoFrame::CreateBlackFrame(frame_size); const double kFrameRate = 60.0f; video_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, kFrameRate); @@ -150,8 +151,8 @@ // Send another Video Frame and expect only an DoOnEncodedVideo() callback. const gfx::Size frame_size2(180, 80); - const scoped_refptr<media::VideoFrame> video_frame2 = - media::VideoFrame::CreateBlackFrame(frame_size2); + const scoped_refptr<VideoFrame> video_frame2 = + VideoFrame::CreateBlackFrame(frame_size2); base::RunLoop run_loop; base::Closure quit_closure = run_loop.QuitClosure(); @@ -165,14 +166,18 @@ run_loop.Run(); - const size_t kFirstEncodedDataSize = 52; - EXPECT_EQ(first_frame_encoded_data.size(), kFirstEncodedDataSize); - const size_t kSecondEncodedDataSize = 32; - EXPECT_EQ(second_frame_encoded_data.size(), kSecondEncodedDataSize); - const size_t kThirdEncodedDataSize = 57; - EXPECT_EQ(third_frame_encoded_data.size(), kThirdEncodedDataSize); + EXPECT_EQ(GetParam().first_encoded_frame_size, + first_frame_encoded_data.size()); + EXPECT_EQ(GetParam().second_encoded_frame_size, + second_frame_encoded_data.size()); + EXPECT_EQ(GetParam().third_encoded_frame_size, + third_frame_encoded_data.size()); Mock::VerifyAndClearExpectations(this); } +INSTANTIATE_TEST_CASE_P(, + VideoTrackRecorderTest, + ValuesIn(kTrackRecorderTestParams)); + } // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc b/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc index 5826505..81ac6fc 100644 --- a/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc +++ b/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
@@ -140,44 +140,12 @@ return audio_processor_.get(); } -std::vector<int> WebRtcLocalAudioTrackAdapter::VoeChannels() const { - DCHECK(capture_thread_.CalledOnValidThread()); - base::AutoLock auto_lock(lock_); - return voe_channels_; -} - void WebRtcLocalAudioTrackAdapter::SetSignalLevel(int signal_level) { DCHECK(capture_thread_.CalledOnValidThread()); base::AutoLock auto_lock(lock_); signal_level_ = signal_level; } -void WebRtcLocalAudioTrackAdapter::AddChannel(int channel_id) { - DCHECK(signaling_thread_checker_.CalledOnValidThread()); - DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id=" - << channel_id << ")"; - base::AutoLock auto_lock(lock_); - if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) != - voe_channels_.end()) { - // We need to handle the case when the same channel is connected to the - // track more than once. - return; - } - - voe_channels_.push_back(channel_id); -} - -void WebRtcLocalAudioTrackAdapter::RemoveChannel(int channel_id) { - DCHECK(signaling_thread_checker_.CalledOnValidThread()); - DVLOG(1) << "WebRtcLocalAudioTrack::RemoveChannel(channel_id=" - << channel_id << ")"; - base::AutoLock auto_lock(lock_); - std::vector<int>::iterator iter = - std::find(voe_channels_.begin(), voe_channels_.end(), channel_id); - DCHECK(iter != voe_channels_.end()); - voe_channels_.erase(iter); -} - webrtc::AudioSourceInterface* WebRtcLocalAudioTrackAdapter::GetSource() const { DCHECK(signaling_thread_checker_.CalledOnValidThread()); return track_source_;
diff --git a/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h b/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h index 52bcd92..e27a4caf 100644 --- a/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h +++ b/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
@@ -32,8 +32,7 @@ class WebRtcLocalAudioTrack; class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter - : NON_EXPORTED_BASE(public cricket::AudioRenderer), - NON_EXPORTED_BASE( + : NON_EXPORTED_BASE( public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>) { public: static scoped_refptr<WebRtcLocalAudioTrackAdapter> Create( @@ -49,8 +48,6 @@ void Initialize(WebRtcLocalAudioTrack* owner); - std::vector<int> VoeChannels() const; - // Called on the audio thread by the WebRtcLocalAudioTrack to set the signal // level of the audio data. void SetSignalLevel(int signal_level); @@ -73,12 +70,6 @@ bool GetSignalLevel(int* level) override; rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor() override; - - // cricket::AudioCapturer implementation. - void AddChannel(int channel_id) override; - void RemoveChannel(int channel_id) override; - - // webrtc::AudioTrackInterface implementation. webrtc::AudioSourceInterface* GetSource() const override; cricket::AudioRenderer* GetRenderer() override;
diff --git a/content/renderer/media/webrtc_local_audio_track.cc b/content/renderer/media/webrtc_local_audio_track.cc index a51b37fb..4f5295a 100644 --- a/content/renderer/media/webrtc_local_audio_track.cc +++ b/content/renderer/media/webrtc_local_audio_track.cc
@@ -90,7 +90,6 @@ // disabled. This is currently done so to feed input to WebRTC typing // detection and should be changed when audio processing is moved from // WebRTC to the track. - std::vector<int> voe_channels = adapter_->VoeChannels(); for (const auto& sink : sinks) sink->OnData(audio_bus, estimated_capture_time); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index c783b8e..8226e912 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -3700,14 +3700,9 @@ return true; } -blink::WebString RenderFrameImpl::userAgentOverride(blink::WebLocalFrame* frame, - const blink::WebURL& url) { +blink::WebString RenderFrameImpl::userAgentOverride( + blink::WebLocalFrame* frame) { DCHECK(!frame_ || frame_ == frame); - std::string user_agent_override_for_url = - GetContentClient()->renderer()->GetUserAgentOverrideForURL(GURL(url)); - if (!user_agent_override_for_url.empty()) - return WebString::fromUTF8(user_agent_override_for_url); - if (!render_view_->webview() || !render_view_->webview()->mainFrame() || render_view_->renderer_preferences_.user_agent_override.empty()) { return blink::WebString();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index f6837da..68c42c4 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -530,8 +530,7 @@ blink::WebFrame* target_frame, blink::WebSecurityOrigin target_origin, blink::WebDOMMessageEvent event) override; - blink::WebString userAgentOverride(blink::WebLocalFrame* frame, - const blink::WebURL& url) override; + blink::WebString userAgentOverride(blink::WebLocalFrame* frame) override; blink::WebString doNotTrackValue(blink::WebLocalFrame* frame) override; bool allowWebGL(blink::WebLocalFrame* frame, bool default_value) override; void didLoseWebGLContext(blink::WebLocalFrame* frame,
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index c8ca4bdb..8f374649 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -553,7 +553,7 @@ } void RenderThreadImpl::Init() { - TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, ""); + TRACE_EVENT0("startup", "RenderThreadImpl::Init"); base::trace_event::TraceLog::GetInstance()->SetThreadSortIndex( base::PlatformThread::CurrentId(), @@ -760,8 +760,6 @@ base::Bind(CreateRenderFrameSetup)); service_registry()->AddService<EmbeddedWorkerSetup>( base::Bind(CreateEmbeddedWorkerSetup)); - - TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, ""); } RenderThreadImpl::~RenderThreadImpl() {
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index 3a463ea..0f44527 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc
@@ -78,7 +78,10 @@ // mainline routine for running as the Renderer process int RendererMain(const MainFunctionParams& parameters) { - TRACE_EVENT_BEGIN_ETW("RendererMain", 0, ""); + // Don't use the TRACE_EVENT0 macro because the tracing infrastructure doesn't + // expect synchronous events around the main loop of a thread. + TRACE_EVENT_ASYNC_BEGIN0("startup", "RendererMain", 0); + base::trace_event::TraceLog::GetInstance()->SetProcessName("Renderer"); base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventRendererProcessSortIndex); @@ -204,9 +207,9 @@ if (pool) pool->Recycle(); #endif - TRACE_EVENT_BEGIN_ETW("RendererMain.START_MSG_LOOP", 0, 0); + TRACE_EVENT_ASYNC_BEGIN0("toplevel", "RendererMain.START_MSG_LOOP", 0); base::MessageLoop::current()->Run(); - TRACE_EVENT_END_ETW("RendererMain.START_MSG_LOOP", 0, 0); + TRACE_EVENT_ASYNC_END0("toplevel", "RendererMain.START_MSG_LOOP", 0); } #if defined(LEAK_SANITIZER) // Run leak detection before RenderProcessImpl goes out of scope. This helps @@ -215,7 +218,7 @@ #endif } platform.PlatformUninitialize(); - TRACE_EVENT_END_ETW("RendererMain", 0, ""); + TRACE_EVENT_ASYNC_END0("startup", "RendererMain", 0); return 0; }
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java index e20c9d3a..f002c553 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java
@@ -36,7 +36,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; /** * Base test class for all ContentShell based tests. @@ -110,33 +109,17 @@ final ContentShellActivity activity = getActivity(); // Wait for the Content Shell to be initialized. - return CriteriaHelper.pollForCriteria(new Criteria() { + return CriteriaHelper.pollForUIThreadCriteria(new Criteria() { @Override public boolean isSatisfied() { - try { - final AtomicBoolean isLoaded = new AtomicBoolean(false); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - Shell shell = activity.getActiveShell(); - if (shell != null) { - // There are two cases here that need to be accounted for. - // The first is that we've just created a Shell and it isn't - // loading because it has no URL set yet. The second is that - // we've set a URL and it actually is loading. - isLoaded.set(!shell.isLoading() - && !TextUtils.isEmpty(shell.getContentViewCore() - .getWebContents().getUrl())); - } else { - isLoaded.set(false); - } - } - }); - - return isLoaded.get(); - } catch (Throwable e) { - return false; - } + Shell shell = activity.getActiveShell(); + // There are two cases here that need to be accounted for. + // The first is that we've just created a Shell and it isn't + // loading because it has no URL set yet. The second is that + // we've set a URL and it actually is loading. + if (shell == null) return false; + return !shell.isLoading() && !TextUtils.isEmpty(shell.getContentViewCore() + .getWebContents().getUrl()); } }, WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL); }
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 3e3df9e..371afa2 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -41,6 +41,7 @@ self.Skip('deqp/functional/gles3/framebufferblit.html', bug=483282) self.Skip('deqp/functional/gles3/indexedstatequery.html', bug=483282) self.Skip('deqp/functional/gles3/instancedrendering.html', bug=483282) + self.Skip('deqp/functional/gles3/integerstatequery.html', bug=483282) self.Skip('deqp/functional/gles3/internalformatquery.html', bug=483282) self.Skip('deqp/functional/gles3/lifetime.html', bug=483282) self.Skip('deqp/functional/gles3/multisample.html', bug=483282) @@ -61,6 +62,7 @@ self.Skip('deqp/functional/gles3/shaderindexing.html', bug=483282) self.Skip('deqp/functional/gles3/shaderloop.html', bug=483282) self.Skip('deqp/functional/gles3/shadermatrix.html', bug=483282) + self.Skip('deqp/functional/gles3/shaderoperator.html', bug=483282) self.Skip('deqp/functional/gles3/shaderpackingfunction.html', bug=483282) self.Skip('deqp/functional/gles3/shaderprecision.html', bug=483282) self.Skip('deqp/functional/gles3/shaderstatequery.html', bug=483282) @@ -97,6 +99,8 @@ # Windows only. self.Skip('deqp/functional/gles3/readpixel.html', ['win'], bug=483282) + self.Skip('deqp/functional/gles3/texturestatequery.html', + ['win'], bug=483282) self.Fail('conformance2/glsl3/array-in-complex-expression.html', ['win'], bug=483282) self.Fail('conformance2/glsl3/short-circuiting-in-loop-condition.html', @@ -116,6 +120,8 @@ ['win'], bug=483282) self.Fail('conformance2/textures/misc/tex-input-validation.html', ['win'], bug=483282) + self.Skip('conformance2/transform_feedback/transform_feedback.html', + ['win'], bug=483282) # Windows 8 only. self.Fail('conformance2/textures/image_data/tex-image-and-sub-image-2d' + '-with-image-data-rgb565-rgb-unsigned_byte.html', @@ -149,6 +155,10 @@ ['mac'], bug=483282) self.Skip('deqp/functional/gles3/defaultvertexattribute.html', ['mac'], bug=483282) + self.Skip('deqp/functional/gles3/floatstatequery.html', + ['mac'], bug=483282) + self.Skip('deqp/functional/gles3/texturestatequery.html', + ['mac'], bug=483282) self.Skip('deqp/functional/gles3/vertexarrayobject.html', ['mac'], bug=483282) self.Skip('deqp/functional/gles3/shaderswitch.html', @@ -215,6 +225,8 @@ ['linux'], bug=483282) self.Fail('conformance2/samplers/samplers.html', ['linux'], bug=483282) + self.Fail('conformance2/state/gl-object-get-calls.html', + ['linux'], bug=483282) # Linux NVIDIA only. self.Skip('deqp/functional/gles3/shaderswitch.html', ['linux', 'nvidia'], bug=483282)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 282925e3..adef3b3a 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -100,7 +100,7 @@ # Win / OpenGL / AMD failures self.Skip('conformance/glsl/misc/shader-struct-scope.html', ['win', 'amd', 'opengl'], bug=1007) # angle bug ID - self.Fail('conformance/glsl/misc/shaders-with-invariance.html', + self.Skip('conformance/glsl/misc/shaders-with-invariance.html', ['win', 'amd', 'opengl'], bug=1007) # angle bug ID self.Fail('conformance/glsl/misc/struct-nesting-of-variable-names.html', ['win', 'amd', 'opengl'], bug=1007) # angle bug ID
diff --git a/content/test/gpu_memory_buffer_factory_test_template.h b/content/test/gpu_memory_buffer_factory_test_template.h index e4240128..4d1ce4c 100644 --- a/content/test/gpu_memory_buffer_factory_test_template.h +++ b/content/test/gpu_memory_buffer_factory_test_template.h
@@ -50,6 +50,48 @@ // from a GpuMemoryBuffer factory in order to be conformant. REGISTER_TYPED_TEST_CASE_P(GpuMemoryBufferFactoryTest, CreateGpuMemoryBuffer); +template <typename GpuMemoryBufferFactoryType> +class GpuMemoryBufferFactoryImportTest + : public GpuMemoryBufferFactoryTest<GpuMemoryBufferFactoryType> {}; + +TYPED_TEST_CASE_P(GpuMemoryBufferFactoryImportTest); + +TYPED_TEST_P(GpuMemoryBufferFactoryImportTest, + CreateGpuMemoryBufferFromHandle) { + const int kClientId = 1; + + gfx::Size buffer_size(2, 2); + + for (auto format : gfx::GetBufferFormats()) { + if (!TypeParam::IsGpuMemoryBufferConfigurationSupported( + format, gfx::BufferUsage::SCANOUT)) { + continue; + } + + const gfx::GpuMemoryBufferId kBufferId1(1); + gfx::GpuMemoryBufferHandle handle1 = + TestFixture::factory_.CreateGpuMemoryBuffer( + kBufferId1, buffer_size, format, gfx::BufferUsage::SCANOUT, + kClientId, gfx::kNullPluginWindow); + EXPECT_NE(handle1.type, gfx::EMPTY_BUFFER); + + // Create new buffer from |handle1|. + const gfx::GpuMemoryBufferId kBufferId2(2); + gfx::GpuMemoryBufferHandle handle2 = + TestFixture::factory_.CreateGpuMemoryBufferFromHandle( + handle1, kBufferId2, buffer_size, format, kClientId); + EXPECT_NE(handle2.type, gfx::EMPTY_BUFFER); + + TestFixture::factory_.DestroyGpuMemoryBuffer(kBufferId1, kClientId); + TestFixture::factory_.DestroyGpuMemoryBuffer(kBufferId2, kClientId); + } +} + +// The GpuMemoryBufferFactoryImportTest test case verifies that the +// GpuMemoryBufferFactory implementation handles import of buffers correctly. +REGISTER_TYPED_TEST_CASE_P(GpuMemoryBufferFactoryImportTest, + CreateGpuMemoryBufferFromHandle); + } // namespace content #endif // CONTENT_TEST_GPU_MEMORY_BUFFER_FACTORY_TEST_TEMPLATE_H_
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc index 368232d1..2aa9688 100644 --- a/device/bluetooth/bluetooth_device_unittest.cc +++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -122,7 +122,7 @@ ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); ASSERT_EQ(1u, gatt_connections_.size()); @@ -144,8 +144,8 @@ ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(1, gatt_connection_attempt_count_); - CompleteGattConnection(device); + EXPECT_EQ(1, gatt_connection_attempts_); + SimulateGattConnection(device); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); ASSERT_EQ(1u, gatt_connections_.size()); @@ -158,7 +158,7 @@ GetConnectErrorCallback()); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(0, gatt_connection_attempt_count_); + EXPECT_EQ(0, gatt_connection_attempts_); EXPECT_EQ(2, callback_count_); EXPECT_EQ(0, error_callback_count_); ASSERT_EQ(3u, gatt_connections_.size()); @@ -177,12 +177,12 @@ EXPECT_FALSE(gatt_connections_[0]->IsConnected()); EXPECT_TRUE(gatt_connections_[1]->IsConnected()); EXPECT_TRUE(device->IsGattConnected()); - EXPECT_EQ(0, gatt_disconnection_attempt_count_); + EXPECT_EQ(0, gatt_disconnection_attempts_); // Delete device, connection objects should all be disconnected. - gatt_disconnection_attempt_count_ = 0; + gatt_disconnection_attempts_ = 0; DeleteDevice(device); - EXPECT_EQ(1, gatt_disconnection_attempt_count_); + EXPECT_EQ(1, gatt_disconnection_attempts_); EXPECT_FALSE(gatt_connections_[0]->IsConnected()); EXPECT_FALSE(gatt_connections_[1]->IsConnected()); @@ -205,16 +205,16 @@ ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); - CompleteGattConnection(device); - EXPECT_EQ(1, gatt_connection_attempt_count_); + SimulateGattConnection(device); + SimulateGattConnection(device); + EXPECT_EQ(1, gatt_connection_attempts_); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); EXPECT_TRUE(gatt_connections_[0]->IsConnected()); // Become disconnected: ResetEventCounts(); - CompleteGattDisconnection(device); + SimulateGattDisconnection(device); EXPECT_EQ(0, callback_count_); EXPECT_EQ(0, error_callback_count_); EXPECT_FALSE(gatt_connections_[0]->IsConnected()); @@ -231,14 +231,14 @@ // Be already connected: device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); EXPECT_TRUE(gatt_connections_[0]->IsConnected()); // Then CreateGattConnection: ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(0, gatt_connection_attempt_count_); + EXPECT_EQ(0, gatt_connection_attempts_); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); EXPECT_TRUE(gatt_connections_[1]->IsConnected()); @@ -256,16 +256,16 @@ // Create connection: device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); // Disconnect connection: gatt_connections_[0]->Disconnect(); - CompleteGattDisconnection(device); + SimulateGattDisconnection(device); // Create 2nd connection: device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); EXPECT_FALSE(gatt_connections_[0]->IsConnected()) << "The disconnected connection shouldn't become connected when another " @@ -286,12 +286,12 @@ GetConnectErrorCallback()); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); // Delete all CreateGattConnection objects, observe disconnection: ResetEventCounts(); gatt_connections_.clear(); - EXPECT_EQ(1, gatt_disconnection_attempt_count_); + EXPECT_EQ(1, gatt_disconnection_attempts_); } #endif // defined(OS_ANDROID) @@ -307,19 +307,19 @@ GetConnectErrorCallback()); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - CompleteGattConnection(device); + SimulateGattConnection(device); // Disconnect all CreateGattConnection objects & create a new connection. // But, don't yet simulate the device disconnecting: ResetEventCounts(); for (BluetoothGattConnection* connection : gatt_connections_) connection->Disconnect(); - EXPECT_EQ(1, gatt_disconnection_attempt_count_); + EXPECT_EQ(1, gatt_disconnection_attempts_); // Create a connection. device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(0, gatt_connection_attempt_count_); // No connection attempt. + EXPECT_EQ(0, gatt_connection_attempts_); // No connection attempt. EXPECT_EQ(1, callback_count_); // Device is assumed still connected. EXPECT_EQ(0, error_callback_count_); EXPECT_FALSE(gatt_connections_.front()->IsConnected()); @@ -327,7 +327,7 @@ // Actually disconnect: ResetEventCounts(); - CompleteGattDisconnection(device); + SimulateGattDisconnection(device); EXPECT_EQ(0, callback_count_); EXPECT_EQ(0, error_callback_count_); for (BluetoothGattConnection* connection : gatt_connections_) @@ -346,8 +346,8 @@ ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(1, gatt_connection_attempt_count_); - CompleteGattDisconnection(device); + EXPECT_EQ(1, gatt_connection_attempts_); + SimulateGattDisconnection(device); EXPECT_EQ(0, callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_code_); @@ -367,14 +367,14 @@ device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); device->DisconnectGatt(); - EXPECT_EQ(1, gatt_connection_attempt_count_); - EXPECT_EQ(1, gatt_disconnection_attempt_count_); - CompleteGattConnection(device); + EXPECT_EQ(1, gatt_connection_attempts_); + EXPECT_EQ(1, gatt_disconnection_attempts_); + SimulateGattConnection(device); EXPECT_EQ(1, callback_count_); EXPECT_EQ(0, error_callback_count_); EXPECT_TRUE(gatt_connections_.back()->IsConnected()); ResetEventCounts(); - CompleteGattDisconnection(device); + SimulateGattDisconnection(device); EXPECT_EQ(0, callback_count_); EXPECT_EQ(0, error_callback_count_); } @@ -392,9 +392,9 @@ device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); device->DisconnectGatt(); - EXPECT_EQ(1, gatt_connection_attempt_count_); - EXPECT_EQ(1, gatt_disconnection_attempt_count_); - CompleteGattDisconnection(device); + EXPECT_EQ(1, gatt_connection_attempts_); + EXPECT_EQ(1, gatt_disconnection_attempts_); + SimulateGattDisconnection(device); EXPECT_EQ(0, callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_code_); @@ -414,9 +414,9 @@ ResetEventCounts(); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - EXPECT_EQ(1, gatt_connection_attempt_count_); - FailGattConnection(device, BluetoothDevice::ERROR_AUTH_FAILED); - FailGattConnection(device, BluetoothDevice::ERROR_FAILED); + EXPECT_EQ(1, gatt_connection_attempts_); + SimulateGattConnectionError(device, BluetoothDevice::ERROR_AUTH_FAILED); + SimulateGattConnectionError(device, BluetoothDevice::ERROR_FAILED); EXPECT_EQ(0, callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_EQ(BluetoothDevice::ERROR_AUTH_FAILED, last_connect_error_code_);
diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 5ebb63d..67ee3ef 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
@@ -218,7 +218,7 @@ "BluetoothGattWrapper doesn't support calls to connectGatt() with " + "multiple distinct callbacks."); } - nativeOnBluetoothDeviceConnectGattCalled(mAdapter.mNativeBluetoothTestAndroid); + nativeOnFakeBluetoothDeviceConnectGattCalled(mAdapter.mNativeBluetoothTestAndroid); mGattCallback = callback; return new FakeBluetoothGatt(this); } @@ -264,8 +264,8 @@ // --------------------------------------------------------------------------------------------- // BluetoothTestAndroid C++ methods declared for access from java: - // Binds to BluetoothAdapterAndroid::OnBluetoothDeviceConnectGattCalled. - private static native void nativeOnBluetoothDeviceConnectGattCalled( + // Binds to BluetoothAdapterAndroid::OnFakeBluetoothDeviceConnectGattCalled. + private static native void nativeOnFakeBluetoothDeviceConnectGattCalled( long nativeBluetoothTestAndroid); // Binds to BluetoothAdapterAndroid::OnFakeBluetoothGattDisconnect.
diff --git a/device/bluetooth/test/bluetooth_test.cc b/device/bluetooth/test/bluetooth_test.cc index f1ed4c5c..98589c25 100644 --- a/device/bluetooth/test/bluetooth_test.cc +++ b/device/bluetooth/test/bluetooth_test.cc
@@ -103,8 +103,8 @@ last_connect_error_code_ = BluetoothDevice::ERROR_UNKNOWN; callback_count_ = 0; error_callback_count_ = 0; - gatt_connection_attempt_count_ = 0; - gatt_disconnection_attempt_count_ = 0; + gatt_connection_attempts_ = 0; + gatt_disconnection_attempts_ = 0; } } // namespace device
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h index e331b42..275fbbb8 100644 --- a/device/bluetooth/test/bluetooth_test.h +++ b/device/bluetooth/test/bluetooth_test.h
@@ -75,14 +75,14 @@ virtual BluetoothDevice* DiscoverLowEnergyDevice(int device_ordinal); // Simulates success of implementation details of CreateGattConnection. - virtual void CompleteGattConnection(BluetoothDevice* device) {} + virtual void SimulateGattConnection(BluetoothDevice* device) {} // Simulates failure of CreateGattConnection with the given error code. - virtual void FailGattConnection(BluetoothDevice* device, - BluetoothDevice::ConnectErrorCode) {} + virtual void SimulateGattConnectionError(BluetoothDevice* device, + BluetoothDevice::ConnectErrorCode) {} // Simulates GattConnection disconnecting. - virtual void CompleteGattDisconnection(BluetoothDevice* device) {} + virtual void SimulateGattDisconnection(BluetoothDevice* device) {} // Remove the device from the adapter and delete it. virtual void DeleteDevice(BluetoothDevice* device); @@ -115,8 +115,8 @@ BluetoothDevice::ERROR_UNKNOWN; int callback_count_ = 0; int error_callback_count_ = 0; - int gatt_connection_attempt_count_ = 0; - int gatt_disconnection_attempt_count_ = 0; + int gatt_connection_attempts_ = 0; + int gatt_disconnection_attempts_ = 0; base::WeakPtrFactory<BluetoothTestBase> weak_factory_; };
diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc index 8e0951d..34dbdb6 100644 --- a/device/bluetooth/test/bluetooth_test_android.cc +++ b/device/bluetooth/test/bluetooth_test_android.cc
@@ -57,7 +57,7 @@ return observer.last_device(); } -void BluetoothTestAndroid::CompleteGattConnection(BluetoothDevice* device) { +void BluetoothTestAndroid::SimulateGattConnection(BluetoothDevice* device) { BluetoothDeviceAndroid* device_android = static_cast<BluetoothDeviceAndroid*>(device); @@ -67,7 +67,7 @@ true); // connected } -void BluetoothTestAndroid::FailGattConnection( +void BluetoothTestAndroid::SimulateGattConnectionError( BluetoothDevice* device, BluetoothDevice::ConnectErrorCode error) { int android_error_value = 0; @@ -96,7 +96,7 @@ false); // connected } -void BluetoothTestAndroid::CompleteGattDisconnection(BluetoothDevice* device) { +void BluetoothTestAndroid::SimulateGattDisconnection(BluetoothDevice* device) { BluetoothDeviceAndroid* device_android = static_cast<BluetoothDeviceAndroid*>(device); @@ -106,16 +106,15 @@ false); // disconnected } -// Records that Java FakeBluetoothDevice connectGatt was called. -void BluetoothTestAndroid::OnBluetoothDeviceConnectGattCalled(JNIEnv* env, - jobject caller) { - gatt_connection_attempt_count_++; +void BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled( + JNIEnv* env, + jobject caller) { + gatt_connection_attempts_++; } -// Records that Java FakeBluetoothGatt disconnect was called. void BluetoothTestAndroid::OnFakeBluetoothGattDisconnect(JNIEnv* env, jobject caller) { - gatt_disconnection_attempt_count_++; + gatt_disconnection_attempts_++; } } // namespace device
diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h index f525323..910825c 100644 --- a/device/bluetooth/test/bluetooth_test_android.h +++ b/device/bluetooth/test/bluetooth_test_android.h
@@ -27,13 +27,13 @@ void InitWithoutDefaultAdapter() override; void InitWithFakeAdapter() override; BluetoothDevice* DiscoverLowEnergyDevice(int device_ordinal) override; - void CompleteGattConnection(BluetoothDevice* device) override; - void FailGattConnection(BluetoothDevice* device, - BluetoothDevice::ConnectErrorCode) override; - void CompleteGattDisconnection(BluetoothDevice* device) override; + void SimulateGattConnection(BluetoothDevice* device) override; + void SimulateGattConnectionError(BluetoothDevice* device, + BluetoothDevice::ConnectErrorCode) override; + void SimulateGattDisconnection(BluetoothDevice* device) override; // Records that Java FakeBluetoothDevice connectGatt was called. - void OnBluetoothDeviceConnectGattCalled(JNIEnv* env, jobject caller); + void OnFakeBluetoothDeviceConnectGattCalled(JNIEnv* env, jobject caller); // Records that Java FakeBluetoothGatt disconnect was called. void OnFakeBluetoothGattDisconnect(JNIEnv* env, jobject caller);
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 27bdd8a..bdeaef4 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -30,6 +30,7 @@ #include "gpu/command_buffer/client/vertex_array_object_manager.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/common/id_allocator.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/common/trace_event.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" @@ -5388,9 +5389,9 @@ SyncToken* sync_token_data = reinterpret_cast<SyncToken*>(sync_token); memset(sync_token_data, 0, sizeof(SyncToken)); - sync_token_data->namespace_id = gpu_control_->GetNamespaceID(); - sync_token_data->command_buffer_id = gpu_control_->GetCommandBufferID(); - sync_token_data->release_count = fence_sync; + sync_token_data->SetData(gpu_control_->GetNamespaceID(), + gpu_control_->GetCommandBufferID(), + fence_sync); } void GLES2Implementation::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) { @@ -5401,9 +5402,9 @@ const SyncToken* sync_token_data = reinterpret_cast<const SyncToken*>(sync_token); - helper_->WaitSyncTokenCHROMIUM(sync_token_data->namespace_id, - sync_token_data->command_buffer_id, - sync_token_data->release_count); + helper_->WaitSyncTokenCHROMIUM(sync_token_data->GetNamespaceId(), + sync_token_data->GetCommandBufferId(), + sync_token_data->GetReleaseCount()); } namespace {
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc index 6d33d858..2eb2b1f 100644 --- a/gpu/command_buffer/client/program_info_manager.cc +++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -510,7 +510,6 @@ LocalGetAs<const TransformFeedbackVaryingsHeader*>( result, 0, header_size); DCHECK(header); - transform_feedback_buffer_mode_ = header->transform_feedback_buffer_mode; if (header->num_transform_feedback_varyings == 0) { DCHECK_EQ(result.size(), header_size); // TODO(zmo): Here we can't tell if no TransformFeedback varyings are @@ -518,6 +517,7 @@ return; } transform_feedback_varyings_.resize(header->num_transform_feedback_varyings); + transform_feedback_buffer_mode_ = header->transform_feedback_buffer_mode; uint32_t entry_size = sizeof(TransformFeedbackVaryingInfo) * header->num_transform_feedback_varyings;
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn index 6f3ec0c..ec19850 100644 --- a/gpu/command_buffer/common/BUILD.gn +++ b/gpu/command_buffer/common/BUILD.gn
@@ -44,6 +44,8 @@ "mailbox.h", "mailbox_holder.cc", "mailbox_holder.h", + "sync_token.cc", + "sync_token.h", "thread_local.h", "time.h", "value_state.cc",
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h index 0d3180140..e14c06d 100644 --- a/gpu/command_buffer/common/constants.h +++ b/gpu/command_buffer/common/constants.h
@@ -8,11 +8,6 @@ #include <stddef.h> #include <stdint.h> -// From glextchromium.h. -#ifndef GL_SYNC_TOKEN_SIZE_CHROMIUM -#define GL_SYNC_TOKEN_SIZE_CHROMIUM 24 -#endif - namespace gpu { typedef int32_t CommandBufferOffset;
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h index 09b87a9..05d1d48 100644 --- a/gpu/command_buffer/common/gles2_cmd_format.h +++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -203,23 +203,6 @@ // UniformES3Info uniforms[num_uniforms]; }; -// The format of fence sync tokens. -struct SyncToken { - CommandBufferNamespace namespace_id; - uint64_t command_buffer_id; - uint64_t release_count; - - bool operator<(const SyncToken& other) const { - // TODO(dyen): Once all our compilers support c++11, we can replace this - // long list of comparisons with std::tie(). - return (namespace_id < other.namespace_id) || - ((namespace_id == other.namespace_id) && - ((command_buffer_id < other.command_buffer_id) || - ((command_buffer_id == other.command_buffer_id) && - (release_count < other.release_count)))); - } -}; - // The format of QuerySync used by EXT_occlusion_query_boolean struct QuerySync { void Reset() { @@ -314,9 +297,6 @@ static_assert(offsetof(UniformBlocksHeader, num_uniform_blocks) == 0, "offset of UniformBlocksHeader.num_uniform_blocks should be 0"); -static_assert(sizeof(SyncToken) <= GL_SYNC_TOKEN_SIZE_CHROMIUM, - "size of SyncToken must not exceed GL_SYNC_TOKEN_SIZE_CHROMIUM"); - namespace cmds { #include "../common/gles2_cmd_format_autogen.h"
diff --git a/gpu/command_buffer/common/sync_token.cc b/gpu/command_buffer/common/sync_token.cc new file mode 100644 index 0000000..15a7e34 --- /dev/null +++ b/gpu/command_buffer/common/sync_token.cc
@@ -0,0 +1,81 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/common/sync_token.h" + +#include <string.h> + +#include "base/logging.h" +#include "base/rand_util.h" + +namespace gpu { + +namespace { + +struct SyncTokenInternal { + CommandBufferNamespace namespace_id; + uint64_t command_buffer_id; + uint64_t release_count; + + bool operator<(const SyncTokenInternal& other) const { + // TODO(dyen): Once all our compilers support c++11, we can replace this + // long list of comparisons with std::tie(). + return (namespace_id < other.namespace_id) || + ((namespace_id == other.namespace_id) && + ((command_buffer_id < other.command_buffer_id) || + ((command_buffer_id == other.command_buffer_id) && + (release_count < other.release_count)))); + } +}; + +static_assert(sizeof(SyncTokenInternal) <= GL_SYNC_TOKEN_SIZE_CHROMIUM, + "SyncTokenInternal must not exceed GL_SYNC_TOKEN_SIZE_CHROMIUM"); +static_assert(sizeof(SyncToken) == GL_SYNC_TOKEN_SIZE_CHROMIUM, + "No additional members other than data are allowed in SyncToken"); + +} // namespace + +SyncToken::SyncToken() { + memset(data, 0, sizeof(data)); +} + +SyncToken::SyncToken(CommandBufferNamespace namespace_id, + uint64_t command_buffer_id, + uint64_t release_count) { + memset(data, 0, sizeof(data)); + SetData(namespace_id, command_buffer_id, release_count); +} + +CommandBufferNamespace SyncToken::GetNamespaceId() const { + return reinterpret_cast<const SyncTokenInternal*>(data)->namespace_id; +} + +uint64_t SyncToken::GetCommandBufferId() const { + return reinterpret_cast<const SyncTokenInternal*>(data)->command_buffer_id; +} + +uint64_t SyncToken::GetReleaseCount() const { + return reinterpret_cast<const SyncTokenInternal*>(data)->release_count; +} + +void SyncToken::SetData(CommandBufferNamespace namespace_id, + uint64_t command_buffer_id, + uint64_t release_count) { + SyncTokenInternal* sync_token_internal = + reinterpret_cast<SyncTokenInternal*>(data); + sync_token_internal->namespace_id = namespace_id; + sync_token_internal->command_buffer_id = command_buffer_id; + sync_token_internal->release_count = release_count; +} + +bool SyncToken::operator<(const SyncToken& other) const { + const SyncTokenInternal* sync_token_internal = + reinterpret_cast<const SyncTokenInternal*>(data); + const SyncTokenInternal* other_sync_token_internal = + reinterpret_cast<const SyncTokenInternal*>(other.data); + + return *sync_token_internal < *other_sync_token_internal; +} + +} // namespace gpu
diff --git a/gpu/command_buffer/common/sync_token.h b/gpu/command_buffer/common/sync_token.h new file mode 100644 index 0000000..380b49d --- /dev/null +++ b/gpu/command_buffer/common/sync_token.h
@@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_COMMON_SYNC_TOKEN_H_ +#define GPU_COMMAND_BUFFER_COMMON_SYNC_TOKEN_H_ + +#include <stdint.h> + +#include "gpu/command_buffer/common/constants.h" +#include "gpu/gpu_export.h" + +// From glextchromium.h. +#ifndef GL_SYNC_TOKEN_SIZE_CHROMIUM +#define GL_SYNC_TOKEN_SIZE_CHROMIUM 24 +#endif + +namespace gpu { + +// A Sync Token is a binary blob which represents a waitable fence sync +// on a particular command buffer namespace and id. +// See src/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt for more +// details. +struct GPU_EXPORT SyncToken { + using Data = int8_t[GL_SYNC_TOKEN_SIZE_CHROMIUM]; + + SyncToken(); + SyncToken(CommandBufferNamespace namespace_id, + uint64_t command_buffer_id, + uint64_t release_count); + + CommandBufferNamespace GetNamespaceId() const; + uint64_t GetCommandBufferId() const; + uint64_t GetReleaseCount() const; + + void SetData(CommandBufferNamespace namespace_id, + uint64_t command_buffer_id, + uint64_t release_count); + + bool operator<(const SyncToken& other) const; + + Data data; +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_SYNC_TOKEN_H_ +
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index 13fc8ad..a798710d 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -19,7 +19,7 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" -#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/common/value_state.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/context_group.h" @@ -817,8 +817,7 @@ // We can simply use the GPUIO namespace with 0 for the command buffer ID // (under normal circumstances 0 is invalid so will not be used) until // the old sync points are replaced. - gles2::SyncToken sync_token = {gpu::CommandBufferNamespace::GPU_IO, 0, - sync_point}; + SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, sync_point); mailbox_manager->PushTextureUpdates(sync_token); } } @@ -842,8 +841,7 @@ // We can simply use the GPUIO namespace with 0 for the command buffer ID // (under normal circumstances 0 is invalid so will not be used) until // the old sync points are replaced. - gles2::SyncToken sync_token = {gpu::CommandBufferNamespace::GPU_IO, 0, - sync_point}; + SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, sync_point); mailbox_manager->PullTextureUpdates(sync_token); return true; } @@ -859,8 +857,7 @@ make_current_success = MakeCurrent(); } if (make_current_success) { - gles2::SyncToken sync_token = {GetNamespaceID(), GetCommandBufferID(), - release}; + SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(), release); mailbox_manager->PushTextureUpdates(sync_token); } } @@ -893,7 +890,7 @@ gles2::MailboxManager* mailbox_manager = decoder_->GetContextGroup()->mailbox_manager(); - gles2::SyncToken sync_token = {namespace_id, command_buffer_id, release}; + SyncToken sync_token(namespace_id, command_buffer_id, release); mailbox_manager->PullTextureUpdates(sync_token); return true; }
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h index 78fb8f8..a914f5e8 100644 --- a/gpu/command_buffer/service/mailbox_manager.h +++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -10,10 +10,12 @@ #include "gpu/gpu_export.h" namespace gpu { + +struct SyncToken; + namespace gles2 { class Texture; -struct SyncToken; // Manages resources scoped beyond the context or context group level. class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> {
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc index 383cbb5c..424dcce 100644 --- a/gpu/command_buffer/service/mailbox_manager_sync.cc +++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -9,7 +9,7 @@ #include "base/memory/linked_ptr.h" #include "base/synchronization/lock.h" -#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_implementation.h" @@ -41,7 +41,7 @@ std::queue<SyncTokenToFenceMap::iterator>& sync_points = g_sync_points.Get(); SyncTokenToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get(); - if (sync_token.release_count) { + if (sync_token.GetReleaseCount()) { while (!sync_points.empty() && sync_points.front()->second->HasCompleted()) { sync_point_to_fence.erase(sync_points.front());
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc index 5101604..82e0d61 100644 --- a/gpu/command_buffer/service/mailbox_manager_unittest.cc +++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" @@ -17,8 +18,8 @@ using namespace ::testing; -static const SyncToken g_sync_token = {gpu::CommandBufferNamespace::GPU_IO, 123, - 0}; +static const SyncToken g_sync_token(gpu::CommandBufferNamespace::GPU_IO, 123, + 0); class MailboxManagerTest : public GpuServiceTest { public:
diff --git a/gpu/command_buffer/tests/gl_fence_sync_unittest.cc b/gpu/command_buffer/tests/gl_fence_sync_unittest.cc index ad21f34..5c86dc3 100644 --- a/gpu/command_buffer/tests/gl_fence_sync_unittest.cc +++ b/gpu/command_buffer/tests/gl_fence_sync_unittest.cc
@@ -7,6 +7,7 @@ #include <GLES2/gl2extchromium.h> #include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/tests/gl_manager.h" #include "gpu/command_buffer/tests/gl_test_utils.h" @@ -44,9 +45,9 @@ gl1_.MakeCurrent(); const GLuint64 fence_sync = glInsertFenceSyncCHROMIUM(); - GLbyte sync_token[GL_SYNC_TOKEN_SIZE_CHROMIUM]; + SyncToken sync_token; glFlush(); - glGenSyncTokenCHROMIUM(fence_sync, sync_token); + glGenSyncTokenCHROMIUM(fence_sync, sync_token.data); ASSERT_TRUE(GL_NO_ERROR == glGetError()); // Make sure it is actually released. @@ -56,7 +57,7 @@ EXPECT_TRUE(gl1_client_state->IsFenceSyncReleased(fence_sync)); gl2_.MakeCurrent(); - glWaitSyncTokenCHROMIUM(sync_token); + glWaitSyncTokenCHROMIUM(sync_token.data); glFinish(); // gl2 should not have released anything.
diff --git a/gpu/command_buffer_common.gypi b/gpu/command_buffer_common.gypi index d793b48..3e0172b 100644 --- a/gpu/command_buffer_common.gypi +++ b/gpu/command_buffer_common.gypi
@@ -29,6 +29,8 @@ 'command_buffer/common/mailbox.h', 'command_buffer/common/mailbox_holder.cc', 'command_buffer/common/mailbox_holder.h', + 'command_buffer/common/sync_token.cc', + 'command_buffer/common/sync_token.h', 'command_buffer/common/thread_local.h', 'command_buffer/common/time.h', 'command_buffer/common/value_state.cc',
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 6519e39..a19c673 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "8.26", + "version": "8.27", "entries": [ { "id": 1, @@ -1270,10 +1270,11 @@ }, { "id": 109, - "description": "MakeCurrent is slow on Linux", + "description": "MakeCurrent is slow on Linux with NVIDIA drivers", "os": { "type": "linux" }, + "gl_vendor": "NVIDIA.*", "features": [ "use_virtualized_gl_contexts" ]
diff --git a/gpu/ipc/gpu_command_buffer_traits.cc b/gpu/ipc/gpu_command_buffer_traits.cc index 8d2148de..9613aa1 100644 --- a/gpu/ipc/gpu_command_buffer_traits.cc +++ b/gpu/ipc/gpu_command_buffer_traits.cc
@@ -5,6 +5,7 @@ #include "gpu/ipc/gpu_command_buffer_traits.h" #include "gpu/command_buffer/common/mailbox_holder.h" +#include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/common/value_state.h" // Generate param traits write methods. @@ -55,6 +56,29 @@ l->append("<CommandBuffer::State>"); } +void ParamTraits<gpu::SyncToken>::Write(Message* m, const param_type& p) { + m->WriteBytes(p.data, sizeof(p.data)); +} + +bool ParamTraits<gpu::SyncToken> ::Read(const Message* m, + base::PickleIterator* iter, + param_type* p) { + const char* bytes = NULL; + if (!iter->ReadBytes(&bytes, sizeof(p->data))) + return false; + DCHECK(bytes); + memcpy(p->data, bytes, sizeof(p->data)); + return true; +} + +void ParamTraits<gpu::SyncToken>::Log(const param_type& p, std::string* l) { + *l += base::StringPrintf( + "[%d:%llX] %llu", + static_cast<int>(p.GetNamespaceId()), + static_cast<unsigned long long>(p.GetCommandBufferId()), + static_cast<unsigned long long>(p.GetReleaseCount())); +} + void ParamTraits<gpu::Mailbox>::Write(Message* m, const param_type& p) { m->WriteBytes(p.name, sizeof(p.name)); }
diff --git a/gpu/ipc/gpu_command_buffer_traits.h b/gpu/ipc/gpu_command_buffer_traits.h index d99d465..880625e 100644 --- a/gpu/ipc/gpu_command_buffer_traits.h +++ b/gpu/ipc/gpu_command_buffer_traits.h
@@ -13,6 +13,7 @@ namespace gpu { struct Mailbox; struct MailboxHolder; +struct SyncToken; union ValueState; } @@ -27,6 +28,14 @@ }; template<> +struct GPU_EXPORT ParamTraits<gpu::SyncToken> { + typedef gpu::SyncToken param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +template<> struct GPU_EXPORT ParamTraits<gpu::Mailbox> { typedef gpu::Mailbox param_type; static void Write(Message* m, const param_type& p);
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index c20f7960..50fc7ce6 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -48,6 +48,10 @@ builders { name: "linux_chromium_compile_dbg_32_ng" } builders { name: "linux_chromium_gn_chromeos_rel" } builders { name: "linux_chromium_rel_ng" } + builders { + name: "linux_chromium_compile_dbg_ng" + experiment_percentage: 10 + } } buckets { name: "tryserver.chromium.mac"
diff --git a/media/capture/webm_muxer.cc b/media/capture/webm_muxer.cc index c59bbae..a2285efa 100644 --- a/media/capture/webm_muxer.cc +++ b/media/capture/webm_muxer.cc
@@ -25,11 +25,14 @@ return frame_rate; } -WebmMuxer::WebmMuxer(const WriteDataCB& write_data_callback) - : track_index_(0), +WebmMuxer::WebmMuxer(VideoCodec codec, const WriteDataCB& write_data_callback) + : use_vp9_(codec == kCodecVP9), + track_index_(0), write_data_callback_(write_data_callback), position_(0) { DCHECK(!write_data_callback_.is_null()); + DCHECK(codec == kCodecVP8 || codec == kCodecVP9) + << " Only Vp8 and VP9 are supported in WebmMuxer"; // Creation is done on a different thread than main activities. thread_checker_.DetachFromThread(); } @@ -82,7 +85,8 @@ reinterpret_cast<mkvmuxer::VideoTrack*>( segment_.GetTrackByNumber(track_index_)); DCHECK(video_track); - video_track->set_codec_id(mkvmuxer::Tracks::kVp8CodecId); + video_track->set_codec_id(use_vp9_ ? mkvmuxer::Tracks::kVp9CodecId + : mkvmuxer::Tracks::kVp8CodecId); DCHECK_EQ(video_track->crop_right(), 0ull); DCHECK_EQ(video_track->crop_left(), 0ull); DCHECK_EQ(video_track->crop_top(), 0ull);
diff --git a/media/capture/webm_muxer.h b/media/capture/webm_muxer.h index 2d25c46..7196d1d4 100644 --- a/media/capture/webm_muxer.h +++ b/media/capture/webm_muxer.h
@@ -5,14 +5,13 @@ #ifndef MEDIA_FILTERS_LIBWEBM_MUXER_H_ #define MEDIA_FILTERS_LIBWEBM_MUXER_H_ -#include <set> - #include "base/callback.h" #include "base/numerics/safe_math.h" #include "base/strings/string_piece.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "media/base/media_export.h" +#include "media/base/video_codecs.h" #include "third_party/libwebm/source/mkvmuxer.hpp" namespace gfx { @@ -40,7 +39,9 @@ // either any file header or a SingleBlock. using WriteDataCB = base::Callback<void(base::StringPiece)>; - explicit WebmMuxer(const WriteDataCB& write_data_callback); + // |codec| can be VP8 or VP9 and should coincide with whatever is sent in + // OnEncodedVideo(). + WebmMuxer(VideoCodec codec, const WriteDataCB& write_data_callback); ~WebmMuxer() override; // Adds a |video_frame| with |encoded_data.data()| to WebM Segment. @@ -69,6 +70,9 @@ // Used to DCHECK that we are called on the correct thread. base::ThreadChecker thread_checker_; + // Video Codec configured: VP9 if true, otherwise VP8 is used by default. + const bool use_vp9_; + // A caller-side identifier to interact with |segment_|, initialised upon // first frame arrival by AddVideoTrack(). uint64_t track_index_;
diff --git a/media/capture/webm_muxer_unittest.cc b/media/capture/webm_muxer_unittest.cc index 7e162fa..eac8a62 100644 --- a/media/capture/webm_muxer_unittest.cc +++ b/media/capture/webm_muxer_unittest.cc
@@ -15,15 +15,18 @@ using ::testing::_; using ::testing::AtLeast; using ::testing::Mock; +using ::testing::TestWithParam; +using ::testing::Values; using ::testing::WithArgs; namespace media { -class WebmMuxerTest : public testing::Test { +class WebmMuxerTest : public TestWithParam<VideoCodec> { public: WebmMuxerTest() - : webm_muxer_(base::Bind(&WebmMuxerTest::WriteCallback, - base::Unretained(this))), + : webm_muxer_( + GetParam() /* codec */, + base::Bind(&WebmMuxerTest::WriteCallback, base::Unretained(this))), last_encoded_length_(0), accumulated_position_(0) { EXPECT_EQ(webm_muxer_.Position(), 0); @@ -62,7 +65,7 @@ // Checks that the WriteCallback is called with appropriate params when // WebmMuxer::Write() method is called. -TEST_F(WebmMuxerTest, Write) { +TEST_P(WebmMuxerTest, Write) { const base::StringPiece encoded_data("abcdefghijklmnopqrstuvwxyz"); EXPECT_CALL(*this, WriteCallback(encoded_data)); @@ -73,7 +76,7 @@ // This test sends two frames and checks that the WriteCallback is called with // appropriate params in both cases. -TEST_F(WebmMuxerTest, OnEncodedVideoTwoFrames) { +TEST_P(WebmMuxerTest, OnEncodedVideoTwoFrames) { const gfx::Size frame_size(160, 80); const scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateBlackFrame(frame_size); @@ -115,4 +118,6 @@ accumulated_position_); } +INSTANTIATE_TEST_CASE_P(, WebmMuxerTest, Values(kCodecVP8, kCodecVP9)); + } // namespace media
diff --git a/media/cast/net/udp_transport.h b/media/cast/net/udp_transport.h index 119aaef5..c845c5ac 100644 --- a/media/cast/net/udp_transport.h +++ b/media/cast/net/udp_transport.h
@@ -11,13 +11,12 @@ #include "media/cast/cast_environment.h" #include "media/cast/net/cast_transport_config.h" #include "media/cast/net/cast_transport_sender.h" +#include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" -#include "net/base/net_util.h" +#include "net/udp/diff_serv_code_point.h" #include "net/udp/udp_socket.h" namespace net { -class IOBuffer; -class IPEndPoint; class NetLog; } // namespace net
diff --git a/mojo/converters/surfaces/surfaces_type_converters.cc b/mojo/converters/surfaces/surfaces_type_converters.cc index 6e901df..381c6d2 100644 --- a/mojo/converters/surfaces/surfaces_type_converters.cc +++ b/mojo/converters/surfaces/surfaces_type_converters.cc
@@ -152,7 +152,7 @@ texture_quad->SetAll( sqs, input->rect.To<gfx::Rect>(), input->opaque_rect.To<gfx::Rect>(), input->visible_rect.To<gfx::Rect>(), input->needs_blending, - texture_quad_state->resource_id, gfx::Size(), false, + texture_quad_state->resource_id, gfx::Size(), texture_quad_state->premultiplied_alpha, texture_quad_state->uv_top_left.To<gfx::PointF>(), texture_quad_state->uv_bottom_right.To<gfx::PointF>(),
diff --git a/mojo/converters/surfaces/tests/surface_unittest.cc b/mojo/converters/surfaces/tests/surface_unittest.cc index 90aab3c58..30b1884 100644 --- a/mojo/converters/surfaces/tests/surface_unittest.cc +++ b/mojo/converters/surfaces/tests/surface_unittest.cc
@@ -112,12 +112,10 @@ float vertex_opacity[4] = {0.1f, 0.5f, 0.4f, 0.8f}; bool y_flipped = false; bool nearest_neighbor = false; - bool allow_overlay = false; texture_quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, - resource_id, gfx::Size(), allow_overlay, - premultiplied_alpha, uv_top_left, uv_bottom_right, - background_color, vertex_opacity, y_flipped, - nearest_neighbor); + resource_id, gfx::Size(), premultiplied_alpha, + uv_top_left, uv_bottom_right, background_color, + vertex_opacity, y_flipped, nearest_neighbor); QuadPtr mojo_quad = Quad::From<cc::DrawQuad>(*texture_quad); ASSERT_FALSE(mojo_quad.is_null()); @@ -266,12 +264,10 @@ float vertex_opacity[4] = {0.1f, 0.5f, 0.4f, 0.8f}; bool y_flipped = false; bool nearest_neighbor = false; - bool allow_overlay = false; texture_quad->SetAll(sqs, rect, opaque_rect, visible_rect, needs_blending, - resource_id, gfx::Size(), allow_overlay, - premultiplied_alpha, uv_top_left, uv_bottom_right, - background_color, vertex_opacity, y_flipped, - nearest_neighbor); + resource_id, gfx::Size(), premultiplied_alpha, + uv_top_left, uv_bottom_right, background_color, + vertex_opacity, y_flipped, nearest_neighbor); PassPtr mojo_pass = Pass::From(*pass); ASSERT_FALSE(mojo_pass.is_null());
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py index a97fd92..eabcc12 100755 --- a/native_client_sdk/src/tools/create_nmf.py +++ b/native_client_sdk/src/tools/create_nmf.py
@@ -367,36 +367,41 @@ needed = self.GetNeeded() - runnable = any(n.endswith(RUNNABLE_LD) for n in needed) - extra_files_kv = [(key, ArchFile(name=key, arch=arch, path=url, url=url)) for key, arch, url in self.extra_files] - for need, archinfo in needed.items() + extra_files_kv: + manifest_items = needed.items() + extra_files_kv + + # Add in runnable-ld.so entries to the program section. + for need, archinfo in manifest_items: + urlinfo = { URL_KEY: archinfo.url } + if need.endswith(RUNNABLE_LD): + manifest[PROGRAM_KEY][archinfo.arch] = urlinfo + + for need, archinfo in manifest_items: urlinfo = { URL_KEY: archinfo.url } name = archinfo.name + arch = archinfo.arch - # If starting with runnable-ld.so, make that the main executable. - if runnable: - if need.endswith(RUNNABLE_LD): - manifest[PROGRAM_KEY][archinfo.arch] = urlinfo - continue + if need.endswith(RUNNABLE_LD): + continue if need in self.main_files: if need.endswith(".nexe"): # Place it under program if we aren't using the runnable-ld.so. - if not runnable: - manifest[PROGRAM_KEY][archinfo.arch] = urlinfo + program = manifest[PROGRAM_KEY] + if arch not in program: + program[arch] = urlinfo continue # Otherwise, treat it like another another file named main.nexe. name = MAIN_NEXE name = self.remap.get(name, name) fileinfo = manifest[FILES_KEY].get(name, {}) - fileinfo[archinfo.arch] = urlinfo + fileinfo[arch] = urlinfo manifest[FILES_KEY][name] = fileinfo self.manifest = manifest
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java index 4008afad..2ed71e1 100644 --- a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java +++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
@@ -134,20 +134,15 @@ /** * Enables auto detection of the current network state based on notifications from the system. * Note that passing true here requires the embedding app have the platform ACCESS_NETWORK_STATE - * permission. + * permission. Also note that in this case the auto detection is enabled based on the status of + * the application (@see ApplicationStatus). * * @param shouldAutoDetect true if the NetworkChangeNotifier should listen for system changes in * network connectivity. */ public static void setAutoDetectConnectivityState(boolean shouldAutoDetect) { - getInstance().setAutoDetectConnectivityStateInternal(shouldAutoDetect, false); - } - - private void destroyAutoDetector() { - if (mAutoDetector != null) { - mAutoDetector.destroy(); - mAutoDetector = null; - } + getInstance().setAutoDetectConnectivityStateInternal( + shouldAutoDetect, new RegistrationPolicyApplicationStatus()); } /** @@ -159,42 +154,57 @@ * might perform expensive work depending on the network connectivity. */ public static void registerToReceiveNotificationsAlways() { - getInstance().setAutoDetectConnectivityStateInternal(true, true); + getInstance().setAutoDetectConnectivityStateInternal( + true, new RegistrationPolicyAlwaysRegister()); + } + + /** + * Registers to receive network change notification based on the provided registration policy. + */ + public static void setAutoDetectConnectivityState( + NetworkChangeNotifierAutoDetect.RegistrationPolicy policy) { + getInstance().setAutoDetectConnectivityStateInternal(true, policy); + } + + private void destroyAutoDetector() { + if (mAutoDetector != null) { + mAutoDetector.destroy(); + mAutoDetector = null; + } } private void setAutoDetectConnectivityStateInternal( - boolean shouldAutoDetect, boolean alwaysWatchForChanges) { + boolean shouldAutoDetect, NetworkChangeNotifierAutoDetect.RegistrationPolicy policy) { if (shouldAutoDetect) { if (mAutoDetector == null) { mAutoDetector = new NetworkChangeNotifierAutoDetect( - new NetworkChangeNotifierAutoDetect.Observer() { - @Override - public void onConnectionTypeChanged(int newConnectionType) { - updateCurrentConnectionType(newConnectionType); - } - @Override - public void onMaxBandwidthChanged(double maxBandwidthMbps) { - updateCurrentMaxBandwidth(maxBandwidthMbps); - } - @Override - public void onNetworkConnect(int netId, int connectionType) { - notifyObserversOfNetworkConnect(netId, connectionType); - } - @Override - public void onNetworkSoonToDisconnect(int netId) { - notifyObserversOfNetworkSoonToDisconnect(netId); - } - @Override - public void onNetworkDisconnect(int netId) { - notifyObserversOfNetworkDisconnect(netId); - } - @Override - public void updateActiveNetworkList(int[] activeNetIds) { - notifyObserversToUpdateActiveNetworkList(activeNetIds); - } - }, - mContext, - alwaysWatchForChanges); + new NetworkChangeNotifierAutoDetect.Observer() { + @Override + public void onConnectionTypeChanged(int newConnectionType) { + updateCurrentConnectionType(newConnectionType); + } + @Override + public void onMaxBandwidthChanged(double maxBandwidthMbps) { + updateCurrentMaxBandwidth(maxBandwidthMbps); + } + @Override + public void onNetworkConnect(int netId, int connectionType) { + notifyObserversOfNetworkConnect(netId, connectionType); + } + @Override + public void onNetworkSoonToDisconnect(int netId) { + notifyObserversOfNetworkSoonToDisconnect(netId); + } + @Override + public void onNetworkDisconnect(int netId) { + notifyObserversOfNetworkDisconnect(netId); + } + @Override + public void updateActiveNetworkList(int[] activeNetIds) { + notifyObserversToUpdateActiveNetworkList(activeNetIds); + } + }, + mContext, policy); final NetworkChangeNotifierAutoDetect.NetworkState networkState = mAutoDetector.getCurrentNetworkState(); updateCurrentConnectionType(mAutoDetector.getCurrentConnectionType(networkState));
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java index 839600a..06ff933f 100644 --- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java +++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -25,8 +25,6 @@ import android.telephony.TelephonyManager; import android.util.Log; -import org.chromium.base.ApplicationState; -import org.chromium.base.ApplicationStatus; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; @@ -35,9 +33,7 @@ * Note that use of this class requires that the app have the platform * ACCESS_NETWORK_STATE permission. */ -public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver - implements ApplicationStatus.ApplicationStateListener { - +public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver { static class NetworkState { private final boolean mConnected; private final int mType; @@ -300,13 +296,48 @@ } } + /** + * Abstract class for providing a policy regarding when the NetworkChangeNotifier + * should listen for network changes. + */ + public abstract static class RegistrationPolicy { + private NetworkChangeNotifierAutoDetect mNotifier; + + /** + * Start listening for network changes. + */ + protected final void register() { + assert mNotifier != null; + mNotifier.register(); + } + + /** + * Stop listening for network changes. + */ + protected final void unregister() { + assert mNotifier != null; + mNotifier.unregister(); + } + + /** + * Initializes the policy with the notifier, overriding subclasses should always + * call this method. + */ + protected void init(NetworkChangeNotifierAutoDetect notifier) { + mNotifier = notifier; + } + + protected abstract void destroy(); + } + private static final String TAG = "NetworkChangeNotifierAutoDetect"; private static final int UNKNOWN_LINK_SPEED = -1; + private final NetworkConnectivityIntentFilter mIntentFilter; - private final Observer mObserver; - private final Context mContext; + private final RegistrationPolicy mRegistrationPolicy; + // mConnectivityManagerDelegates and mWifiManagerDelegate are only non-final for testing. private ConnectivityManagerDelegate mConnectivityManagerDelegate; private WifiManagerDelegate mWifiManagerDelegate; @@ -314,7 +345,6 @@ private final NetworkCallback mNetworkCallback; private final NetworkRequest mNetworkRequest; private boolean mRegistered; - private final boolean mApplicationStateRegistered; private int mConnectionType; private String mWifiSSID; private double mMaxBandwidthMbps; @@ -369,7 +399,7 @@ */ @SuppressLint("NewApi") public NetworkChangeNotifierAutoDetect( - Observer observer, Context context, boolean alwaysWatchForChanges) { + Observer observer, Context context, RegistrationPolicy policy) { // Since BroadcastReceiver is always called back on UI thread, ensure // running on UI thread so notification logic can be single-threaded. ThreadUtils.assertOnUiThread(); @@ -391,15 +421,8 @@ mMaxBandwidthMbps = getCurrentMaxBandwidthInMbps(networkState); mIntentFilter = new NetworkConnectivityIntentFilter(mWifiManagerDelegate.getHasWifiPermission()); - - if (alwaysWatchForChanges) { - registerReceiver(); - mApplicationStateRegistered = false; - } else { - ApplicationStatus.registerApplicationStateListener(this); - onApplicationStateChange(getApplicationState()); - mApplicationStateRegistered = true; - } + mRegistrationPolicy = policy; + mRegistrationPolicy.init(this); } /** @@ -416,13 +439,9 @@ mWifiManagerDelegate = delegate; } - /** - * Returns the activity's status. - * @return an {@code int} that is one of {@code ApplicationState.HAS_*_ACTIVITIES}. - */ @VisibleForTesting - int getApplicationState() { - return ApplicationStatus.getStateForApplication(); + RegistrationPolicy getRegistrationPolicy() { + return mRegistrationPolicy; } /** @@ -434,46 +453,48 @@ } public void destroy() { - if (mApplicationStateRegistered) ApplicationStatus.unregisterApplicationStateListener(this); - unregisterReceiver(); + mRegistrationPolicy.destroy(); + unregister(); } /** * Registers a BroadcastReceiver in the given context. */ - private void registerReceiver() { - if (!mRegistered) { - mRegistered = true; - mContext.registerReceiver(this, mIntentFilter); - if (mNetworkCallback != null) { - mConnectivityManagerDelegate.registerNetworkCallback( - mNetworkRequest, mNetworkCallback); - // registerNetworkCallback() will rematch our NetworkRequest - // against active networks, so a cached list of active networks - // will be repopulated immediatly after this. However we need to - // purge any cached networks as they may have been disconnected - // while mNetworkCallback was unregistered. - final Network[] networks = mConnectivityManagerDelegate.getAllNetworks(); - // Convert Networks to NetIDs. - final int[] netIds = new int[networks.length]; - for (int i = 0; i < networks.length; i++) { - netIds[i] = networkToNetId(networks[i]); - } - mObserver.updateActiveNetworkList(netIds); + public void register() { + if (mRegistered) return; + + final NetworkState networkState = getCurrentNetworkState(); + connectionTypeChanged(networkState); + maxBandwidthChanged(networkState); + mContext.registerReceiver(this, mIntentFilter); + mRegistered = true; + + if (mNetworkCallback != null) { + mConnectivityManagerDelegate.registerNetworkCallback(mNetworkRequest, mNetworkCallback); + // registerNetworkCallback() will rematch our NetworkRequest + // against active networks, so a cached list of active networks + // will be repopulated immediatly after this. However we need to + // purge any cached networks as they may have been disconnected + // while mNetworkCallback was unregistered. + final Network[] networks = mConnectivityManagerDelegate.getAllNetworks(); + // Convert Networks to NetIDs. + final int[] netIds = new int[networks.length]; + for (int i = 0; i < networks.length; i++) { + netIds[i] = networkToNetId(networks[i]); } + mObserver.updateActiveNetworkList(netIds); } } /** - * Unregisters the BroadcastReceiver in the given context. + * Unregisters a BroadcastReceiver in the given context. */ - private void unregisterReceiver() { - if (mRegistered) { - mRegistered = false; - mContext.unregisterReceiver(this); - if (mNetworkCallback != null) { - mConnectivityManagerDelegate.unregisterNetworkCallback(mNetworkCallback); - } + public void unregister() { + if (!mRegistered) return; + mContext.unregisterReceiver(this); + mRegistered = false; + if (mNetworkCallback != null) { + mConnectivityManagerDelegate.unregisterNetworkCallback(mNetworkCallback); } } @@ -652,19 +673,6 @@ } } - // ApplicationStatus.ApplicationStateListener - @Override - public void onApplicationStateChange(int newState) { - final NetworkState networkState = getCurrentNetworkState(); - if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { - connectionTypeChanged(networkState); - maxBandwidthChanged(networkState); - registerReceiver(); - } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) { - unregisterReceiver(); - } - } - private void connectionTypeChanged(NetworkState networkState) { int newConnectionType = getCurrentConnectionType(networkState); String newWifiSSID = getCurrentWifiSSID(networkState);
diff --git a/net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java b/net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java new file mode 100644 index 0000000..9f840a2f --- /dev/null +++ b/net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java
@@ -0,0 +1,19 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +/** + * Registration policy which make sure that the listener is always registered. + */ +public class RegistrationPolicyAlwaysRegister + extends NetworkChangeNotifierAutoDetect.RegistrationPolicy { + @Override + protected void init(NetworkChangeNotifierAutoDetect notifier) { + super.init(notifier); + register(); + } + + protected void destroy() {} +}
diff --git a/net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java b/net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java new file mode 100644 index 0000000..516075f --- /dev/null +++ b/net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java
@@ -0,0 +1,50 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +import org.chromium.base.ApplicationState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.VisibleForTesting; + +/** + * Regsitration policy which depends on the ApplicationState. + */ +public class RegistrationPolicyApplicationStatus + extends NetworkChangeNotifierAutoDetect.RegistrationPolicy + implements ApplicationStatus.ApplicationStateListener { + private boolean mDestroyed = false; + + @Override + protected void init(NetworkChangeNotifierAutoDetect notifier) { + super.init(notifier); + ApplicationStatus.registerApplicationStateListener(this); + onApplicationStateChange(getApplicationState()); + } + + protected void destroy() { + if (mDestroyed) return; + ApplicationStatus.unregisterApplicationStateListener(this); + mDestroyed = true; + } + + // ApplicationStatus.ApplicationStateListener + @Override + public void onApplicationStateChange(int newState) { + if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { + register(); + } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) { + unregister(); + } + } + + /** + * Returns the activity's status. + * @return an {@code int} that is one of {@code ApplicationState.HAS_*_ACTIVITIES}. + */ + @VisibleForTesting + int getApplicationState() { + return ApplicationStatus.getStateForApplication(); + } +}
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java index b28f5ef..cfd748b0 100644 --- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java +++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -300,12 +300,12 @@ new TestNetworkChangeNotifierAutoDetectObserver(); NetworkChangeNotifierAutoDetect receiver = new NetworkChangeNotifierAutoDetect( - observer, context, false /* always watch for changes */) { - @Override - int getApplicationState() { - return ApplicationState.HAS_RUNNING_ACTIVITIES; - } - }; + observer, context, new RegistrationPolicyApplicationStatus() { + @Override + int getApplicationState() { + return ApplicationState.HAS_RUNNING_ACTIVITIES; + } + }); assertTrue(receiver.isReceiverRegisteredForTesting()); } @@ -318,13 +318,15 @@ @MediumTest @Feature({"Android-AppBase"}) public void testNetworkChangeNotifierRegistersForIntents() throws InterruptedException { - mReceiver.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); + RegistrationPolicyApplicationStatus policy = + (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy(); + policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); assertTrue(mReceiver.isReceiverRegisteredForTesting()); - mReceiver.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); + policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); assertFalse(mReceiver.isReceiverRegisteredForTesting()); - mReceiver.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); + policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); assertTrue(mReceiver.isReceiverRegisteredForTesting()); } @@ -460,14 +462,16 @@ observer.resetHasReceivedNotification(); // Pretend we got moved to the background. - mReceiver.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); + final RegistrationPolicyApplicationStatus policy = + (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy(); + policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); // Change the state. mConnectivityDelegate.setActiveNetworkExists(true); mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); // The NetworkChangeNotifierAutoDetect doesn't receive any notification while we are in the // background, but when we get back to the foreground the state changed should be detected // and a notification sent. - mReceiver.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); + policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); assertTrue(observer.hasReceivedNotification()); } @@ -527,8 +531,8 @@ public void testQueryableAPIsDoNotCrash() { NetworkChangeNotifierAutoDetect.Observer observer = new TestNetworkChangeNotifierAutoDetectObserver(); - NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect( - observer, getInstrumentation().getTargetContext(), true); + NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect(observer, + getInstrumentation().getTargetContext(), new RegistrationPolicyAlwaysRegister()); ncn.getNetworksAndTypes(); ncn.getDefaultNetId(); } @@ -551,17 +555,17 @@ new Callable<NetworkChangeNotifierAutoDetect>() { public NetworkChangeNotifierAutoDetect call() { return new NetworkChangeNotifierAutoDetect( - observer, context, false /* always watch for changes */) { - // This override prevents NetworkChangeNotifierAutoDetect from - // registering for events right off the bat. We'll delay this - // until our MockConnectivityManagerDelegate is first installed - // to prevent inadvertent communication with the real - // ConnectivityManager. - @Override - int getApplicationState() { - return ApplicationState.HAS_PAUSED_ACTIVITIES; - } - }; + observer, context, new RegistrationPolicyApplicationStatus() { + // This override prevents NetworkChangeNotifierAutoDetect from + // registering for events right off the bat. We'll delay this + // until our MockConnectivityManagerDelegate is first installed + // to prevent inadvertent communication with the real + // ConnectivityManager. + @Override + int getApplicationState() { + return ApplicationState.HAS_PAUSED_ACTIVITIES; + } + }); } }; FutureTask<NetworkChangeNotifierAutoDetect> task = @@ -575,7 +579,10 @@ // Now that mock ConnectivityDelegate is inserted, pretend app is foregrounded // so NetworkChangeNotifierAutoDetect will register its NetworkCallback. assertFalse(ncn.isReceiverRegisteredForTesting()); - ncn.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); + + RegistrationPolicyApplicationStatus policy = + (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy(); + policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); assertTrue(ncn.isReceiverRegisteredForTesting()); // Find NetworkChangeNotifierAutoDetect's NetworkCallback, which should have been registered @@ -600,9 +607,9 @@ // Simulate app backgrounding then foregrounding. assertTrue(ncn.isReceiverRegisteredForTesting()); - ncn.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); + policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES); assertFalse(ncn.isReceiverRegisteredForTesting()); - ncn.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); + policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES); assertTrue(ncn.isReceiverRegisteredForTesting()); // Verify network list purged. observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID);
diff --git a/net/base/net_util.h b/net/base/net_util.h index 7c9f3c8..c430019c 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h
@@ -231,36 +231,6 @@ IP_ADDRESS_ATTRIBUTE_DEPRECATED = 1 << 1, }; -// Differentiated Services Code Point. -// See http://tools.ietf.org/html/rfc2474 for details. -enum DiffServCodePoint { - DSCP_NO_CHANGE = -1, - DSCP_FIRST = DSCP_NO_CHANGE, - DSCP_DEFAULT = 0, // Same as DSCP_CS0 - DSCP_CS0 = 0, // The default - DSCP_CS1 = 8, // Bulk/background traffic - DSCP_AF11 = 10, - DSCP_AF12 = 12, - DSCP_AF13 = 14, - DSCP_CS2 = 16, - DSCP_AF21 = 18, - DSCP_AF22 = 20, - DSCP_AF23 = 22, - DSCP_CS3 = 24, - DSCP_AF31 = 26, - DSCP_AF32 = 28, - DSCP_AF33 = 30, - DSCP_CS4 = 32, - DSCP_AF41 = 34, // Video - DSCP_AF42 = 36, // Video - DSCP_AF43 = 38, // Video - DSCP_CS5 = 40, // Video - DSCP_EF = 46, // Voice - DSCP_CS6 = 48, // Voice - DSCP_CS7 = 56, // Control messages - DSCP_LAST = DSCP_CS7 -}; - } // namespace net #endif // NET_BASE_NET_UTIL_H_
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h index 2e50f5e..8e400cf0 100644 --- a/net/http/http_server_properties.h +++ b/net/http/http_server_properties.h
@@ -17,6 +17,7 @@ #include "net/base/net_export.h" #include "net/base/net_util.h" #include "net/quic/quic_bandwidth.h" +#include "net/quic/quic_server_id.h" #include "net/socket/next_proto.h" #include "net/spdy/spdy_framer.h" // TODO(willchan): Reconsider this. #include "net/spdy/spdy_protocol.h" @@ -213,6 +214,10 @@ AlternativeServiceMap; typedef base::MRUCache<HostPortPair, SettingsMap> SpdySettingsMap; typedef base::MRUCache<HostPortPair, ServerNetworkStats> ServerNetworkStatsMap; +typedef base::MRUCache<QuicServerId, std::string> QuicServerInfoMap; + +// Persist 5 QUIC Servers. This is mainly used by cronet. +const int kMaxQuicServersToPersist = 5; extern const char kAlternateProtocolHeader[]; extern const char kAlternativeServiceHeader[]; @@ -360,6 +365,18 @@ virtual const ServerNetworkStatsMap& server_network_stats_map() const = 0; + // Save QuicServerInfo (in std::string form) for the given |server_id|. + // Returns true if the value has changed otherwise it returns false. + virtual bool SetQuicServerInfo(const QuicServerId& server_id, + const std::string& server_info) = 0; + + // Get QuicServerInfo (in std::string form) for the given |server_id|. + virtual const std::string* GetQuicServerInfo( + const QuicServerId& server_id) = 0; + + // Returns all persistent QuicServerInfo objects. + virtual const QuicServerInfoMap& quic_server_info_map() const = 0; + private: DISALLOW_COPY_AND_ASSIGN(HttpServerProperties); };
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc index 6278f36..c83d9575 100644 --- a/net/http/http_server_properties_impl.cc +++ b/net/http/http_server_properties_impl.cc
@@ -31,6 +31,7 @@ spdy_settings_map_(SpdySettingsMap::NO_AUTO_EVICT), server_network_stats_map_(ServerNetworkStatsMap::NO_AUTO_EVICT), alternative_service_probability_threshold_(1.0), + quic_server_info_map_(kMaxQuicServersToPersist), weak_ptr_factory_(this) { canonical_suffixes_.push_back(".c.youtube.com"); canonical_suffixes_.push_back(".googlevideo.com"); @@ -151,6 +152,14 @@ } } +void HttpServerPropertiesImpl::InitializeQuicServerInfoMap( + QuicServerInfoMap* quic_server_info_map) { + for (const std::pair<QuicServerId, std::string>& entry : + *quic_server_info_map) { + quic_server_info_map_.Put(entry.first, entry.second); + } +} + void HttpServerPropertiesImpl::GetSpdyServerList( base::ListValue* spdy_server_list, size_t max_size) const { @@ -181,6 +190,7 @@ spdy_settings_map_.Clear(); last_quic_address_.clear(); server_network_stats_map_.Clear(); + quic_server_info_map_.Clear(); } bool HttpServerPropertiesImpl::SupportsRequestPriority( @@ -601,6 +611,29 @@ return server_network_stats_map_; } +bool HttpServerPropertiesImpl::SetQuicServerInfo( + const QuicServerId& server_id, + const std::string& server_info) { + QuicServerInfoMap::iterator it = quic_server_info_map_.Peek(server_id); + bool changed = + (it == quic_server_info_map_.end() || it->second != server_info); + quic_server_info_map_.Put(server_id, server_info); + return changed; +} + +const std::string* HttpServerPropertiesImpl::GetQuicServerInfo( + const QuicServerId& server_id) { + QuicServerInfoMap::iterator it = quic_server_info_map_.Get(server_id); + if (it == quic_server_info_map_.end()) + return nullptr; + return &it->second; +} + +const QuicServerInfoMap& HttpServerPropertiesImpl::quic_server_info_map() + const { + return quic_server_info_map_; +} + void HttpServerPropertiesImpl::SetAlternativeServiceProbabilityThreshold( double threshold) { alternative_service_probability_threshold_ = threshold;
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h index d6ee31a..093f5d20 100644 --- a/net/http/http_server_properties_impl.h +++ b/net/http/http_server_properties_impl.h
@@ -60,6 +60,8 @@ void InitializeServerNetworkStats( ServerNetworkStatsMap* server_network_stats_map); + void InitializeQuicServerInfoMap(QuicServerInfoMap* quic_server_info_map); + // Get the list of servers (host/port) that support SPDY. The max_size is the // number of MRU servers that support SPDY that are to be returned. void GetSpdyServerList(base::ListValue* spdy_server_list, @@ -125,6 +127,10 @@ const ServerNetworkStats* GetServerNetworkStats( const HostPortPair& host_port_pair) override; const ServerNetworkStatsMap& server_network_stats_map() const override; + bool SetQuicServerInfo(const QuicServerId& server_id, + const std::string& server_info) override; + const std::string* GetQuicServerInfo(const QuicServerId& server_id) override; + const QuicServerInfoMap& quic_server_info_map() const override; private: friend class HttpServerPropertiesImplPeer; @@ -177,6 +183,8 @@ double alternative_service_probability_threshold_; + QuicServerInfoMap quic_server_info_map_; + base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesImpl);
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc index e354b77..c5735fe 100644 --- a/net/http/http_server_properties_impl_unittest.cc +++ b/net/http/http_server_properties_impl_unittest.cc
@@ -1192,6 +1192,42 @@ EXPECT_EQ(NULL, stats3); } +typedef HttpServerPropertiesImplTest QuicServerInfoServerPropertiesTest; + +TEST_F(QuicServerInfoServerPropertiesTest, Initialize) { + HostPortPair google_server("www.google.com", 443); + QuicServerId quic_server_id(google_server, true, PRIVACY_MODE_ENABLED); + + // Check empty map. + QuicServerInfoMap quic_server_info_map(QuicServerInfoMap::NO_AUTO_EVICT); + impl_.InitializeQuicServerInfoMap(&quic_server_info_map); + EXPECT_EQ(0u, impl_.quic_server_info_map().size()); + + // Check by adding a QuicServerInfo into the map. + std::string quic_server_info1("quic_server_info1"); + quic_server_info_map.Put(quic_server_id, quic_server_info1); + impl_.InitializeQuicServerInfoMap(&quic_server_info_map); + + EXPECT_EQ(1u, impl_.quic_server_info_map().size()); + EXPECT_EQ(quic_server_info1, *impl_.GetQuicServerInfo(quic_server_id)); +} + +TEST_F(QuicServerInfoServerPropertiesTest, SetQuicServerInfo) { + HostPortPair foo_server("foo", 80); + QuicServerId quic_server_id(foo_server, true, PRIVACY_MODE_ENABLED); + EXPECT_EQ(0u, impl_.quic_server_info_map().size()); + + std::string quic_server_info1("quic_server_info1"); + impl_.SetQuicServerInfo(quic_server_id, quic_server_info1); + + EXPECT_EQ(1u, impl_.quic_server_info_map().size()); + EXPECT_EQ(quic_server_info1, *(impl_.GetQuicServerInfo(quic_server_id))); + + impl_.Clear(); + EXPECT_EQ(0u, impl_.quic_server_info_map().size()); + EXPECT_EQ(nullptr, impl_.GetQuicServerInfo(quic_server_id)); +} + } // namespace } // namespace net
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc index 2577f95..b8e3e0c 100644 --- a/net/http/http_server_properties_manager.cc +++ b/net/http/http_server_properties_manager.cc
@@ -56,6 +56,8 @@ const char kSupportsSpdyKey[] = "supports_spdy"; const char kSettingsKey[] = "settings"; const char kSupportsQuicKey[] = "supports_quic"; +const char kQuicServers[] = "quic_servers"; +const char kServerInfoKey[] = "server_info"; const char kUsedQuicKey[] = "used_quic"; const char kAddressKey[] = "address"; const char kAlternateProtocolKey[] = "alternate_protocol"; @@ -384,6 +386,29 @@ return http_server_properties_impl_->server_network_stats_map(); } +bool HttpServerPropertiesManager::SetQuicServerInfo( + const QuicServerId& server_id, + const std::string& server_info) { + DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); + bool changed = + http_server_properties_impl_->SetQuicServerInfo(server_id, server_info); + if (changed) + ScheduleUpdatePrefsOnNetworkThread(SET_QUIC_SERVER_INFO); + return changed; +} + +const std::string* HttpServerPropertiesManager::GetQuicServerInfo( + const QuicServerId& server_id) { + DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); + return http_server_properties_impl_->GetQuicServerInfo(server_id); +} + +const QuicServerInfoMap& HttpServerPropertiesManager::quic_server_info_map() + const { + DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); + return http_server_properties_impl_->quic_server_info_map(); +} + // // Update the HttpServerPropertiesImpl's cache with data from preferences. // @@ -443,6 +468,8 @@ new AlternativeServiceMap(kMaxAlternateProtocolHostsToPersist)); scoped_ptr<ServerNetworkStatsMap> server_network_stats_map( new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist)); + scoped_ptr<QuicServerInfoMap> quic_server_info_map( + new QuicServerInfoMap(kMaxQuicServersToPersist)); for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd(); it.Advance()) { @@ -478,6 +505,11 @@ } } + if (!AddToQuicServerInfoMap(http_server_properties_dict, + quic_server_info_map.get())) { + detected_corrupted_prefs = true; + } + network_task_runner_->PostTask( FROM_HERE, base::Bind( @@ -486,6 +518,7 @@ base::Owned(spdy_settings_map.release()), base::Owned(alternative_service_map.release()), base::Owned(addr), base::Owned(server_network_stats_map.release()), + base::Owned(quic_server_info_map.release()), detected_corrupted_prefs)); } @@ -713,12 +746,57 @@ return true; } +bool HttpServerPropertiesManager::AddToQuicServerInfoMap( + const base::DictionaryValue& http_server_properties_dict, + QuicServerInfoMap* quic_server_info_map) { + const base::DictionaryValue* quic_servers_dict = NULL; + if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion( + kQuicServers, &quic_servers_dict)) { + DVLOG(1) << "Malformed http_server_properties for quic_servers."; + return true; + } + + bool detected_corrupted_prefs = false; + for (base::DictionaryValue::Iterator it(*quic_servers_dict); !it.IsAtEnd(); + it.Advance()) { + // Get quic_server_id. + const std::string& quic_server_id_str = it.key(); + QuicServerId quic_server_id = QuicServerId::FromString(quic_server_id_str); + if (quic_server_id.host().empty()) { + DVLOG(1) << "Malformed http_server_properties for quic server: " + << quic_server_id_str; + detected_corrupted_prefs = true; + continue; + } + + const base::DictionaryValue* quic_server_pref_dict = NULL; + if (!it.value().GetAsDictionary(&quic_server_pref_dict)) { + DVLOG(1) << "Malformed http_server_properties quic server dict: " + << quic_server_id_str; + detected_corrupted_prefs = true; + continue; + } + + std::string quic_server_info; + if (!quic_server_pref_dict->GetStringWithoutPathExpansion( + kServerInfoKey, &quic_server_info)) { + DVLOG(1) << "Malformed http_server_properties quic server info: " + << quic_server_id_str; + detected_corrupted_prefs = true; + continue; + } + quic_server_info_map->Put(quic_server_id, quic_server_info); + } + return !detected_corrupted_prefs; +} + void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread( StringVector* spdy_servers, SpdySettingsMap* spdy_settings_map, AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, bool detected_corrupted_prefs) { // Preferences have the master data because admins might have pushed new // preferences. Update the cached data with new data from preferences. @@ -744,6 +822,9 @@ http_server_properties_impl_->InitializeServerNetworkStats( server_network_stats_map); + http_server_properties_impl_->InitializeQuicServerInfoMap( + quic_server_info_map); + // Update the prefs with what we have read (delete all corrupted prefs). if (detected_corrupted_prefs) ScheduleUpdatePrefsOnNetworkThread(DETECTED_CORRUPTED_PREFS); @@ -851,6 +932,17 @@ server_network_stats_map->Put(it->first, it->second); } + QuicServerInfoMap* quic_server_info_map = NULL; + const QuicServerInfoMap& main_quic_server_info_map = + http_server_properties_impl_->quic_server_info_map(); + if (main_quic_server_info_map.size() > 0) { + quic_server_info_map = new QuicServerInfoMap(kMaxQuicServersToPersist); + for (const std::pair<const QuicServerId, std::string>& entry : + main_quic_server_info_map) { + quic_server_info_map->Put(entry.first, entry.second); + } + } + IPAddressNumber* last_quic_addr = new IPAddressNumber; http_server_properties_impl_->GetSupportsQuic(last_quic_addr); // Update the preferences on the pref thread. @@ -860,7 +952,8 @@ &HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_, base::Owned(spdy_server_list), base::Owned(spdy_settings_map), base::Owned(alternative_service_map), base::Owned(last_quic_addr), - base::Owned(server_network_stats_map), completion)); + base::Owned(server_network_stats_map), + base::Owned(quic_server_info_map), completion)); } // A local or temporary data structure to hold |supports_spdy|, SpdySettings, @@ -897,6 +990,7 @@ AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, const base::Closure& completion) { typedef std::map<HostPortPair, ServerPref> ServerPrefMap; ServerPrefMap server_pref_map; @@ -966,6 +1060,9 @@ SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict); + SaveQuicServerInfoMapToServerPrefs(quic_server_info_map, + &http_server_properties_dict); + setting_prefs_ = true; pref_service_->Set(path_, http_server_properties_dict); setting_prefs_ = false; @@ -1060,6 +1157,26 @@ server_network_stats_dict); } +void HttpServerPropertiesManager::SaveQuicServerInfoMapToServerPrefs( + QuicServerInfoMap* quic_server_info_map, + base::DictionaryValue* http_server_properties_dict) { + if (!quic_server_info_map) + return; + + base::DictionaryValue* quic_servers_dict = new base::DictionaryValue; + for (const std::pair<QuicServerId, std::string>& entry : + *quic_server_info_map) { + const QuicServerId& server_id = entry.first; + base::DictionaryValue* quic_server_pref_dict = new base::DictionaryValue; + quic_server_pref_dict->SetStringWithoutPathExpansion(kServerInfoKey, + entry.second); + quic_servers_dict->SetWithoutPathExpansion(server_id.ToString(), + quic_server_pref_dict); + } + http_server_properties_dict->SetWithoutPathExpansion(kQuicServers, + quic_servers_dict); +} + void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() { DCHECK(pref_task_runner_->RunsTasksOnCurrentThread()); if (!setting_prefs_)
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h index 1e09ff7..ed695e3 100644 --- a/net/http/http_server_properties_manager.h +++ b/net/http/http_server_properties_manager.h
@@ -128,6 +128,10 @@ const ServerNetworkStats* GetServerNetworkStats( const HostPortPair& host_port_pair) override; const ServerNetworkStatsMap& server_network_stats_map() const override; + bool SetQuicServerInfo(const QuicServerId& server_id, + const std::string& server_info) override; + const std::string* GetQuicServerInfo(const QuicServerId& server_id) override; + const QuicServerInfoMap& quic_server_info_map() const override; protected: // The location where ScheduleUpdatePrefsOnNetworkThread was called. @@ -145,7 +149,8 @@ SET_SUPPORTS_QUIC = 10, SET_SERVER_NETWORK_STATS = 11, DETECTED_CORRUPTED_PREFS = 12, - NUM_LOCATIONS = 13, + SET_QUIC_SERVER_INFO = 13, + NUM_LOCATIONS = 14, }; // -------------------- @@ -174,6 +179,7 @@ AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, bool detected_corrupted_prefs); // These are used to delay updating the preferences when cached data in @@ -204,6 +210,7 @@ AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, const base::Closure& completion); private: @@ -229,6 +236,8 @@ bool AddToNetworkStatsMap(const HostPortPair& server, const base::DictionaryValue& server_dict, ServerNetworkStatsMap* network_stats_map); + bool AddToQuicServerInfoMap(const base::DictionaryValue& server_dict, + QuicServerInfoMap* quic_server_info_map); void SaveSpdySettingsToServerPrefs(const SettingsMap* spdy_settings_map, base::DictionaryValue* server_pref_dict); @@ -238,7 +247,9 @@ void SaveNetworkStatsToServerPrefs( const ServerNetworkStats* server_network_stats, base::DictionaryValue* server_pref_dict); - + void SaveQuicServerInfoMapToServerPrefs( + QuicServerInfoMap* quic_server_info_map, + base::DictionaryValue* http_server_properties_dict); void SaveSupportsQuicToPrefs( const IPAddressNumber* last_quic_address, base::DictionaryValue* http_server_properties_dict);
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc index 2164bb5..40b6211 100644 --- a/net/http/http_server_properties_manager_unittest.cc +++ b/net/http/http_server_properties_manager_unittest.cc
@@ -83,19 +83,22 @@ MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread, void()); MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread, void(const base::Closure&)); MOCK_METHOD1(ScheduleUpdatePrefsOnNetworkThread, void(Location location)); - MOCK_METHOD6(UpdateCacheFromPrefsOnNetworkThread, + MOCK_METHOD7(UpdateCacheFromPrefsOnNetworkThread, void(std::vector<std::string>* spdy_servers, SpdySettingsMap* spdy_settings_map, AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, bool detected_corrupted_prefs)); - MOCK_METHOD5(UpdatePrefsOnPref, + MOCK_METHOD7(UpdatePrefsOnPrefThread, void(base::ListValue* spdy_server_list, SpdySettingsMap* spdy_settings_map, AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, - ServerNetworkStatsMap* server_network_stats_map)); + ServerNetworkStatsMap* server_network_stats_map, + QuicServerInfoMap* quic_server_info_map, + const base::Closure& completion)); private: DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager); @@ -248,6 +251,27 @@ http_server_properties_dict->SetWithoutPathExpansion("supports_quic", supports_quic); + // Set quic_server_info for www.google.com:80 and mail.google.com:80. + base::DictionaryValue* quic_servers_dict = new base::DictionaryValue; + base::DictionaryValue* quic_server_pref_dict1 = new base::DictionaryValue; + std::string quic_server_info1("quic_server_info1"); + quic_server_pref_dict1->SetStringWithoutPathExpansion("server_info", + quic_server_info1); + base::DictionaryValue* quic_server_pref_dict2 = new base::DictionaryValue; + std::string quic_server_info2("quic_server_info2"); + quic_server_pref_dict2->SetStringWithoutPathExpansion("server_info", + quic_server_info2); + // Set the quic_server_info1 for www.google.com server. + QuicServerId google_quic_server_id("www.google.com", 80, false); + quic_servers_dict->SetWithoutPathExpansion(google_quic_server_id.ToString(), + quic_server_pref_dict1); + // Set the quic_server_info2 for mail.google.com server. + QuicServerId mail_quic_server_id("mail.google.com", 80, false); + quic_servers_dict->SetWithoutPathExpansion(mail_quic_server_id.ToString(), + quic_server_pref_dict2); + http_server_properties_dict->SetWithoutPathExpansion("quic_servers", + quic_servers_dict); + // Set the same value for kHttpServerProperties multiple times. pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict); @@ -298,6 +322,12 @@ const ServerNetworkStats* stats3 = http_server_props_manager_->GetServerNetworkStats(mail_server); EXPECT_EQ(20, stats3->srtt.ToInternalValue()); + + // Verify QuicServerInfo. + EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( + google_quic_server_id)); + EXPECT_EQ(quic_server_info2, *http_server_props_manager_->GetQuicServerInfo( + mail_quic_server_id)); } TEST_F(HttpServerPropertiesManagerTest, BadCachedHostPortPair) { @@ -330,10 +360,20 @@ servers_dict->SetWithoutPathExpansion("www.google.com:65536", server_pref_dict); + // Set quic_server_info for www.google.com:65536. + base::DictionaryValue* quic_servers_dict = new base::DictionaryValue; + base::DictionaryValue* quic_server_pref_dict1 = new base::DictionaryValue; + quic_server_pref_dict1->SetStringWithoutPathExpansion("server_info", + "quic_server_info1"); + quic_servers_dict->SetWithoutPathExpansion("http://mail.google.com:65536", + quic_server_pref_dict1); + base::DictionaryValue* http_server_properties_dict = new base::DictionaryValue; HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1); http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict); + http_server_properties_dict->SetWithoutPathExpansion("quic_servers", + quic_servers_dict); // Set up the pref. pref_service_.SetManagedPref(kTestHttpServerProperties, @@ -351,6 +391,7 @@ http_server_props_manager_->GetServerNetworkStats( HostPortPair::FromString("www.google.com:65536")); EXPECT_EQ(NULL, stats1); + EXPECT_EQ(0u, http_server_props_manager_->quic_server_info_map().size()); } TEST_F(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) { @@ -703,6 +744,28 @@ EXPECT_EQ(10, stats2->srtt.ToInternalValue()); } +TEST_F(HttpServerPropertiesManagerTest, QuicServerInfo) { + ExpectPrefsUpdate(); + ExpectScheduleUpdatePrefsOnNetworkThread(); + + QuicServerId mail_quic_server_id("mail.google.com", 80, false); + EXPECT_EQ(nullptr, + http_server_props_manager_->GetQuicServerInfo(mail_quic_server_id)); + std::string quic_server_info1("quic_server_info1"); + http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, + quic_server_info1); + // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. + http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, + quic_server_info1); + + // Run the task. + base::RunLoop().RunUntilIdle(); + Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); + + EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( + mail_quic_server_id)); +} + TEST_F(HttpServerPropertiesManagerTest, Clear) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(); @@ -719,11 +782,16 @@ stats.srtt = base::TimeDelta::FromMicroseconds(10); http_server_props_manager_->SetServerNetworkStats(spdy_server_mail, stats); + QuicServerId mail_quic_server_id("mail.google.com", 80, false); + std::string quic_server_info1("quic_server_info1"); + http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, + quic_server_info1); + const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH; const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST; const uint32 value1 = 31337; - http_server_props_manager_->SetSpdySetting( - spdy_server_mail, id1, flags1, value1); + http_server_props_manager_->SetSpdySetting(spdy_server_mail, id1, flags1, + value1); // Run the task. base::RunLoop().RunUntilIdle(); @@ -737,6 +805,8 @@ const ServerNetworkStats* stats1 = http_server_props_manager_->GetServerNetworkStats(spdy_server_mail); EXPECT_EQ(10, stats1->srtt.ToInternalValue()); + EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( + mail_quic_server_id)); // Check SPDY settings values. const SettingsMap& settings_map1_ret = @@ -763,6 +833,8 @@ const ServerNetworkStats* stats2 = http_server_props_manager_->GetServerNetworkStats(spdy_server_mail); EXPECT_EQ(NULL, stats2); + EXPECT_EQ(nullptr, + http_server_props_manager_->GetQuicServerInfo(mail_quic_server_id)); const SettingsMap& settings_map2_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); @@ -868,6 +940,12 @@ stats.srtt = base::TimeDelta::FromInternalValue(42); http_server_props_manager_->SetServerNetworkStats(server_mail, stats); + // Set quic_server_info string. + QuicServerId mail_quic_server_id("mail.google.com", 80, false); + std::string quic_server_info1("quic_server_info1"); + http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, + quic_server_info1); + // Set SupportsQuic. IPAddressNumber actual_address; CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address)); @@ -881,7 +959,9 @@ // Verify preferences. const char expected_json[] = - "{\"servers\":{\"mail.google.com:80\":{\"alternative_service\":[{" + "{\"quic_servers\":{\"http://" + "mail.google.com:80\":{\"server_info\":\"quic_server_info1\"}}," + "\"servers\":{\"mail.google.com:80\":{\"alternative_service\":[{" "\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\"," "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\"}]," "\"network_stats\":{\"srtt\":42}},\"www.google.com:80\":{"
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index 6fbfee8..b94b2b7c 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -1138,2346 +1138,2346 @@ 0xe6, 0x8e, 0xbc, 0x00, 0xe1, 0xd7, 0xfb, 0x39, 0xe1, 0x85, 0xe8, 0xeb, 0x6d, 0x9d, 0x48, 0x7b, 0xfd, 0x1b, 0xfc, 0xc6, 0xf9, 0xae, 0xed, 0x34, 0x5b, 0xf7, 0xb6, 0xdf, 0xc7, 0x5f, 0xdf, 0x7c, 0xed, 0x7e, 0x1d, 0x5c, - 0x3f, 0x95, 0x96, 0xfe, 0x3d, 0x7d, 0x82, 0x93, 0x1d, 0x7e, 0xf4, 0xb5, - 0xf7, 0x47, 0x5e, 0xd7, 0x42, 0x75, 0xfb, 0xef, 0x86, 0x3f, 0x3a, 0x96, - 0x78, 0xbb, 0x07, 0x2f, 0xfe, 0xf6, 0x93, 0x50, 0x39, 0xee, 0xa1, 0xd7, - 0x87, 0x3a, 0x75, 0x2c, 0xf6, 0xf6, 0x20, 0xdf, 0x83, 0x0a, 0xe0, 0x59, - 0xd7, 0xfc, 0xfa, 0x8c, 0x10, 0xf6, 0x0e, 0xbf, 0xfb, 0x17, 0xcc, 0xdf, - 0xa2, 0xea, 0xf3, 0x9d, 0x76, 0xb5, 0xc3, 0xfc, 0x13, 0x5a, 0x84, 0xdd, - 0xb1, 0xfd, 0x09, 0x1e, 0x14, 0xd7, 0xce, 0x83, 0xe3, 0xaf, 0x72, 0x3c, - 0x75, 0xfd, 0x33, 0x87, 0xa8, 0xb3, 0xaf, 0xef, 0x26, 0x06, 0x16, 0x75, - 0x78, 0xf6, 0x19, 0x2d, 0xbb, 0x42, 0x75, 0xfd, 0xbe, 0xa1, 0xb8, 0xb3, - 0xab, 0x88, 0xd8, 0x77, 0x3d, 0x11, 0x80, 0x56, 0xfb, 0xaa, 0x05, 0x67, - 0x5d, 0x92, 0x3a, 0xb0, 0xdc, 0x09, 0x1d, 0x2b, 0x6b, 0xbb, 0x91, 0x09, - 0xc9, 0x11, 0x85, 0xdf, 0x21, 0x50, 0x86, 0x1c, 0x20, 0xec, 0x7c, 0xbf, - 0x9f, 0x8c, 0x3d, 0xfc, 0xe9, 0x7f, 0x3e, 0xec, 0x2d, 0xfc, 0x75, 0x30, - 0x8e, 0x01, 0x85, 0x95, 0xfc, 0x16, 0x35, 0xed, 0x6e, 0x75, 0xca, 0xca, - 0xb6, 0x75, 0xe5, 0xbe, 0xe7, 0x5d, 0xb1, 0x0e, 0xbe, 0xe7, 0x33, 0xe9, - 0xd7, 0xed, 0x4f, 0x8c, 0xb0, 0xac, 0x1f, 0xb4, 0x10, 0x4c, 0x38, 0xe2, - 0xf5, 0x09, 0x83, 0x24, 0x29, 0xaf, 0xff, 0xff, 0x23, 0x5f, 0x8f, 0xd9, - 0x67, 0xb0, 0x3a, 0x75, 0xe7, 0x27, 0x8d, 0xce, 0xbf, 0x71, 0xae, 0xed, - 0x34, 0x52, 0x97, 0xff, 0xcf, 0xe1, 0xc9, 0xf9, 0x1d, 0x4e, 0xe7, 0x0e, - 0xbc, 0xf2, 0x62, 0x11, 0xed, 0x8e, 0xdf, 0x99, 0xdf, 0xf4, 0x98, 0xce, - 0x35, 0xdd, 0xa6, 0x89, 0x3a, 0xcc, 0x2d, 0x10, 0xce, 0x83, 0x51, 0x08, - 0xd0, 0x09, 0xe7, 0x05, 0x25, 0x1b, 0xd0, 0x6f, 0x8b, 0x93, 0x21, 0xdc, - 0xd8, 0xd1, 0xd2, 0x10, 0x4a, 0xf0, 0xa0, 0x98, 0x9f, 0x90, 0xb6, 0x5d, - 0x67, 0xa7, 0xd8, 0xcb, 0x1c, 0xa7, 0xf8, 0x64, 0x8c, 0x24, 0x75, 0x3d, - 0xbd, 0xe8, 0xcb, 0xb6, 0x47, 0x47, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x87, - 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x3b, 0x31, 0x87, - 0xfa, 0xb3, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x44, 0xf7, 0xf4, - 0xc9, 0xed, 0x01, 0x67, 0x5f, 0xfe, 0x55, 0x94, 0x65, 0x5e, 0x70, 0xaa, - 0xbe, 0x7c, 0xee, 0xd9, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0xc6, 0xff, - 0xfd, 0xfc, 0xa7, 0x55, 0xa1, 0x5b, 0x9d, 0xbc, 0xf9, 0xf3, 0xbb, 0x67, - 0x5f, 0x26, 0xf2, 0x56, 0xce, 0xb3, 0x10, 0x9a, 0xac, 0x8b, 0xb1, 0x8b, - 0xa6, 0x7e, 0x6b, 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, - 0x44, 0xf3, 0x7f, 0x31, 0xfc, 0x0c, 0xb4, 0x75, 0x42, 0xa9, 0x19, 0xca, - 0x25, 0x1c, 0xa7, 0x54, 0x3c, 0xaf, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x88, - 0x2f, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x4b, 0x31, 0x87, - 0xfa, 0xb3, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x45, 0x17, 0xf9, - 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x8c, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x13, - 0x2d, 0xfa, 0x59, 0xe7, 0x69, 0xd7, 0xe6, 0x16, 0xf2, 0x63, 0x0f, 0x67, - 0x73, 0x3b, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x49, 0x61, 0x3a, 0xdf, 0x4e, - 0xb3, 0x18, 0x7a, 0x8a, 0xe6, 0x60, 0x0f, 0xbf, 0xcc, 0x67, 0x1a, 0xee, - 0xd3, 0x45, 0x75, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0x16, 0xff, - 0xe5, 0xbc, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0xea, 0xff, 0x99, 0x61, - 0xe1, 0x36, 0xd3, 0x68, 0xeb, 0xff, 0xf4, 0xc3, 0x0b, 0x63, 0x34, 0x8c, - 0x85, 0xdd, 0x43, 0xae, 0xd7, 0x8e, 0xbf, 0x0b, 0xac, 0x60, 0xeb, 0xf8, - 0x1a, 0xeb, 0xc9, 0x85, 0x6c, 0xdd, 0x7d, 0x16, 0xbf, 0x67, 0xb4, 0x8b, - 0x3a, 0xff, 0xf4, 0x6f, 0xec, 0x99, 0x39, 0xed, 0x01, 0x5c, 0xeb, 0xcf, - 0xbb, 0x02, 0x7e, 0x9e, 0x26, 0xb7, 0xb1, 0x38, 0x4e, 0x42, 0x43, 0x50, - 0xc0, 0xa6, 0x15, 0x29, 0x42, 0x82, 0x47, 0x85, 0x7e, 0x4e, 0x8b, 0xcc, - 0x75, 0xfa, 0x58, 0x1f, 0x98, 0x75, 0x2a, 0x0f, 0x3a, 0x09, 0xaf, 0xd9, - 0xe4, 0x06, 0x8e, 0xb9, 0x58, 0x56, 0xa7, 0x52, 0xb5, 0x3c, 0x75, 0x58, - 0x9a, 0xfc, 0xab, 0x95, 0x8d, 0x73, 0xc7, 0x5f, 0xef, 0xa3, 0x9c, 0xe4, - 0x34, 0xea, 0x56, 0x0f, 0x99, 0x54, 0x67, 0x7d, 0xc5, 0xfb, 0x73, 0xaf, - 0xe5, 0x61, 0x59, 0x54, 0x44, 0x96, 0x75, 0xe6, 0xe7, 0x4a, 0xbc, 0xb8, - 0xd1, 0xd7, 0xbf, 0xe4, 0x1d, 0x7f, 0x67, 0xe9, 0x32, 0x32, 0x75, 0xff, - 0x9f, 0x5f, 0x35, 0xac, 0x94, 0xa0, 0xeb, 0xff, 0xf0, 0xba, 0x89, 0xc8, - 0x94, 0xb3, 0x5f, 0xff, 0x07, 0x50, 0x51, 0x84, 0xa1, 0x77, 0x4f, 0xef, - 0xff, 0xee, 0x26, 0xd3, 0xad, 0x88, 0xe7, 0x13, 0x69, 0xa0, 0x9c, 0xeb, - 0xe4, 0xef, 0xd5, 0x9d, 0x7f, 0xf9, 0x14, 0xf9, 0x82, 0xfb, 0xe9, 0x45, - 0x1c, 0xea, 0x69, 0xf8, 0x09, 0x1d, 0xff, 0xe7, 0xd0, 0xe7, 0xec, 0x75, - 0x1a, 0xfc, 0x3a, 0xfe, 0x0e, 0x29, 0xec, 0x69, 0xd7, 0xdd, 0x85, 0xb4, - 0xea, 0x73, 0xce, 0xf1, 0x6d, 0xf8, 0x29, 0x32, 0x32, 0x75, 0xff, 0xdf, - 0x22, 0x06, 0x17, 0xf3, 0xe7, 0x76, 0xce, 0xa8, 0x3f, 0x31, 0x28, 0xbf, - 0xf7, 0x72, 0x6e, 0xa7, 0x63, 0x90, 0x75, 0xcf, 0xb9, 0xd7, 0xf9, 0xf4, - 0xfd, 0x00, 0xce, 0x75, 0x09, 0xe4, 0x00, 0x5a, 0xa7, 0x5c, 0x0e, 0x90, - 0xda, 0x43, 0x7b, 0x86, 0x2b, 0x86, 0x97, 0x48, 0x46, 0x12, 0xfe, 0x84, - 0xa7, 0xd2, 0x0d, 0xa8, 0x42, 0xde, 0x17, 0xf1, 0xd7, 0x85, 0x34, 0x75, - 0x99, 0x54, 0x1b, 0x48, 0x1a, 0xbe, 0xe6, 0xc7, 0x59, 0xd7, 0xe5, 0x8b, - 0xfb, 0x47, 0x5e, 0x8c, 0xe1, 0xd7, 0xff, 0x9a, 0xfc, 0x7f, 0x26, 0xa0, - 0x63, 0xf3, 0xad, 0x2e, 0x9f, 0x0f, 0xd1, 0xaa, 0xdd, 0x16, 0x3c, 0x84, - 0x3d, 0x62, 0x65, 0x08, 0x56, 0x08, 0x6a, 0x5e, 0xd6, 0xd6, 0xd1, 0xd7, - 0xfd, 0xd7, 0xf4, 0x4d, 0xa4, 0x59, 0xd7, 0xfa, 0x24, 0x39, 0xbf, 0xb0, - 0xeb, 0xdd, 0x02, 0xce, 0xac, 0x45, 0x3a, 0x11, 0x70, 0xe0, 0x06, 0x37, - 0xf7, 0xb5, 0x34, 0x0c, 0xe7, 0x5f, 0x85, 0x44, 0xcd, 0x1d, 0x7e, 0x65, - 0xfc, 0xed, 0x3a, 0xff, 0xec, 0x65, 0xff, 0xc6, 0xf5, 0xff, 0xd1, 0xd7, - 0xfe, 0xd3, 0xef, 0x02, 0xe1, 0xc5, 0x0e, 0xa4, 0x46, 0x7f, 0x49, 0x84, - 0x9f, 0xc8, 0xb7, 0x47, 0x4e, 0xb0, 0x4e, 0xa5, 0x9a, 0x51, 0x15, 0xbe, - 0x10, 0xfc, 0x50, 0xeb, 0xfb, 0x34, 0xcb, 0x8c, 0xe7, 0x56, 0x1f, 0x8b, - 0x90, 0x09, 0x25, 0xf8, 0x0a, 0x68, 0x30, 0x75, 0xe5, 0xa6, 0x8e, 0xbf, - 0xa3, 0x79, 0x69, 0x04, 0xea, 0x85, 0x4d, 0x39, 0x0f, 0xd4, 0x86, 0x8f, - 0x4b, 0x1c, 0xa0, 0x46, 0xef, 0xff, 0x28, 0xf9, 0xbf, 0xbd, 0x19, 0xb1, - 0x1a, 0x75, 0xfe, 0x1c, 0xd7, 0x9d, 0xc4, 0xea, 0x50, 0xfe, 0xb6, 0x25, - 0xdf, 0xff, 0xf9, 0x39, 0xc8, 0xfb, 0xe4, 0x10, 0x4b, 0x34, 0x10, 0x3f, - 0x24, 0x75, 0xff, 0xfc, 0x38, 0xa6, 0x0f, 0xcd, 0x7b, 0xb8, 0xbf, 0xb1, - 0xf9, 0xd5, 0x08, 0xca, 0xc6, 0xcb, 0xfc, 0x07, 0xd2, 0x4c, 0x8c, 0x9d, - 0x48, 0x9a, 0x1f, 0x61, 0xde, 0x24, 0x37, 0xbb, 0x02, 0x75, 0xed, 0xfc, - 0xb3, 0xa9, 0xa6, 0xdd, 0xc6, 0xaf, 0xd3, 0x87, 0x88, 0xc9, 0xd7, 0xfb, - 0xeb, 0xec, 0x49, 0x91, 0x93, 0xaf, 0xfe, 0x41, 0xc0, 0x72, 0x75, 0xc6, - 0x78, 0xea, 0x83, 0xf9, 0x09, 0xbd, 0xfc, 0x17, 0xe7, 0xfb, 0x78, 0x75, - 0xee, 0xfd, 0xd8, 0x75, 0xff, 0x42, 0xc7, 0x1b, 0xc4, 0xfc, 0xea, 0x91, - 0xeb, 0xe8, 0x82, 0xff, 0xa2, 0x58, 0x9a, 0xd0, 0x20, 0xeb, 0xff, 0x7a, - 0x17, 0xbb, 0x53, 0x7c, 0xe1, 0xd7, 0xee, 0xe7, 0x13, 0x47, 0x5e, 0x14, - 0x96, 0xe7, 0xcb, 0xe3, 0xfb, 0xff, 0x3e, 0x7f, 0x02, 0xe1, 0xc5, 0x0e, - 0xa9, 0xd3, 0x0a, 0x94, 0x26, 0xff, 0x33, 0xbf, 0xcf, 0xbe, 0xbd, 0xec, - 0x57, 0x3a, 0xff, 0xf2, 0x73, 0xaf, 0x8d, 0x0e, 0x73, 0xf4, 0x3a, 0xfe, - 0x53, 0xd1, 0x82, 0xd3, 0xaf, 0xff, 0x46, 0x6f, 0xee, 0xc7, 0x86, 0x3f, - 0xd1, 0xd7, 0x47, 0xe7, 0x5d, 0xd5, 0x9d, 0x4d, 0x35, 0x9a, 0x16, 0xa4, - 0x46, 0x17, 0x8b, 0x00, 0xeb, 0x7a, 0x74, 0xe1, 0xd7, 0xf0, 0x35, 0xed, - 0x67, 0x8e, 0xbf, 0x80, 0xa9, 0x49, 0x91, 0x93, 0xae, 0xce, 0x9d, 0x79, - 0x96, 0x59, 0x2a, 0xff, 0xf7, 0x93, 0xda, 0xea, 0x6d, 0xfd, 0xe4, 0x48, - 0xa6, 0x0b, 0xfa, 0x51, 0x30, 0xd4, 0x1c, 0x72, 0xdf, 0x19, 0x00, 0xd2, - 0xff, 0xff, 0x93, 0xd2, 0x81, 0xcf, 0x75, 0x33, 0xd0, 0xb4, 0xe4, 0x8e, - 0xa9, 0x2f, 0x30, 0x85, 0xaf, 0x08, 0x1b, 0x0a, 0x24, 0x21, 0x9a, 0x10, - 0xfc, 0x8c, 0xb1, 0x67, 0x1d, 0x36, 0x18, 0xc2, 0xbd, 0x19, 0xe6, 0xc4, - 0xab, 0xfe, 0xde, 0x5a, 0xd6, 0x05, 0xfc, 0x75, 0xb0, 0xeb, 0xee, 0x0b, - 0xec, 0x3a, 0xa0, 0xfa, 0x94, 0x39, 0x40, 0xfb, 0x39, 0xd7, 0xa3, 0xba, - 0x3a, 0xb7, 0x35, 0x48, 0x1f, 0x7f, 0xff, 0x3f, 0x93, 0xae, 0xbf, 0x99, - 0xa8, 0xce, 0x60, 0x9d, 0x7f, 0xf9, 0x1b, 0xa8, 0xdb, 0xcf, 0x4a, 0x59, - 0xa3, 0xab, 0x88, 0xc4, 0x12, 0x1d, 0x8b, 0x17, 0xdc, 0xee, 0x09, 0xd4, - 0x87, 0xa2, 0xe6, 0x37, 0xde, 0x8d, 0xd9, 0x3a, 0xba, 0x78, 0x6c, 0x90, - 0x5c, 0xcf, 0x4e, 0xbf, 0xfd, 0x02, 0xdf, 0xbc, 0x7f, 0xd3, 0xdd, 0x83, - 0xaf, 0xf2, 0x33, 0xac, 0xc1, 0x9c, 0xeb, 0xe8, 0xd4, 0x6c, 0x3a, 0xff, - 0xe8, 0x17, 0xf4, 0xa1, 0x47, 0x67, 0xc7, 0x57, 0x4f, 0x94, 0x04, 0x57, - 0xbe, 0x3b, 0x4e, 0xa6, 0xa6, 0x6f, 0xf8, 0xbe, 0x92, 0xbd, 0x09, 0x7d, - 0xa2, 0x2b, 0xe5, 0xfd, 0x81, 0x3a, 0xf9, 0x03, 0x8b, 0x3a, 0xf9, 0xdc, - 0x7f, 0x3a, 0xcc, 0xc1, 0xe0, 0x28, 0x41, 0x70, 0x16, 0x75, 0xfe, 0x65, - 0xe6, 0xc9, 0x42, 0xb9, 0xd4, 0x87, 0xeb, 0xd2, 0x9d, 0x0b, 0x5f, 0xe8, - 0x7e, 0x75, 0x97, 0x09, 0x57, 0x32, 0xc9, 0x54, 0x13, 0xca, 0x64, 0xca, - 0xf7, 0x91, 0x5c, 0xa6, 0x0d, 0x1d, 0xfd, 0xbb, 0x53, 0x5d, 0x43, 0xaf, - 0x81, 0x20, 0x78, 0xea, 0x44, 0xfc, 0x26, 0x86, 0xbe, 0xa1, 0x37, 0xe2, - 0xfd, 0xb2, 0xdb, 0x99, 0xd1, 0xd6, 0xc3, 0xad, 0xbe, 0x1a, 0x6f, 0x0b, - 0xdf, 0x6f, 0x25, 0x46, 0xe7, 0x5f, 0xfd, 0xad, 0x04, 0x60, 0x3d, 0x8f, - 0x68, 0xea, 0x84, 0x49, 0x61, 0x38, 0x0a, 0x2f, 0xfd, 0xe4, 0xe3, 0xff, - 0xb5, 0xec, 0xe9, 0xd7, 0xfc, 0x8c, 0x8e, 0x79, 0x01, 0xf9, 0xd7, 0xf9, - 0xf9, 0xed, 0x0a, 0x28, 0x75, 0xff, 0xed, 0x62, 0x98, 0x0e, 0x38, 0x63, - 0xb0, 0x75, 0x49, 0x32, 0x14, 0x2e, 0x57, 0x41, 0x73, 0x8d, 0x19, 0x5e, - 0xc4, 0xe1, 0xd7, 0xfa, 0x48, 0xbe, 0xee, 0xea, 0xe7, 0x5f, 0x3f, 0x22, - 0x47, 0x5f, 0xf3, 0xef, 0xf3, 0x7d, 0x60, 0xa8, 0x75, 0x4e, 0x8a, 0xcd, - 0xc6, 0x96, 0x6d, 0xe2, 0x0b, 0xee, 0xab, 0xa2, 0xce, 0xbc, 0x31, 0xf9, - 0xd7, 0xa1, 0x79, 0xf0, 0xdf, 0xe8, 0x92, 0xff, 0xd1, 0xbf, 0x61, 0x6d, - 0xea, 0x4c, 0x75, 0x62, 0x3c, 0x11, 0xfb, 0x86, 0x77, 0xe6, 0xbc, 0xf8, - 0xc9, 0xd7, 0xe8, 0xe0, 0x70, 0x4e, 0xa1, 0x3c, 0xdf, 0x14, 0x5f, 0xfd, - 0x1f, 0xc7, 0x56, 0x2e, 0xa7, 0x50, 0xeb, 0x2a, 0x8e, 0xbf, 0xc1, 0xec, - 0x0b, 0x2f, 0xb9, 0xd7, 0xff, 0x20, 0x7b, 0x0d, 0x8f, 0xdc, 0x7f, 0x3a, - 0xff, 0xff, 0x96, 0xe3, 0xbc, 0x98, 0x67, 0x13, 0x66, 0x0e, 0x05, 0xe4, - 0x78, 0xbd, 0x6f, 0xca, 0x79, 0xdc, 0x4e, 0xbc, 0x20, 0x9c, 0xea, 0x73, - 0xc2, 0xf1, 0x35, 0x22, 0x35, 0xc6, 0x16, 0xd5, 0x09, 0xf5, 0xf0, 0x85, - 0x68, 0x6e, 0x29, 0xa3, 0x30, 0x46, 0x35, 0x72, 0xb0, 0xad, 0x9d, 0x79, - 0x23, 0x87, 0x52, 0xa8, 0xdd, 0x74, 0x82, 0xff, 0xee, 0x22, 0xe1, 0x5c, - 0x71, 0x7b, 0xc1, 0xd5, 0x23, 0xea, 0x98, 0x96, 0xf9, 0x05, 0xc2, 0x75, - 0xe9, 0xd6, 0x87, 0x50, 0x4d, 0xd8, 0x8f, 0xdf, 0xa5, 0x9b, 0x22, 0x47, - 0x5e, 0xce, 0x41, 0xd5, 0xba, 0x30, 0x11, 0x7b, 0x84, 0x1d, 0x28, 0xbf, - 0xfe, 0xcf, 0x6b, 0x26, 0xec, 0x6c, 0xce, 0xf6, 0x0e, 0xbf, 0xff, 0xff, - 0x26, 0x6f, 0xa4, 0xc6, 0x7e, 0x66, 0xf2, 0xd2, 0x7b, 0x49, 0xb8, 0x42, - 0x09, 0xce, 0xbf, 0xff, 0x20, 0x87, 0xe7, 0xdf, 0x26, 0x9d, 0x04, 0x12, - 0x3a, 0x85, 0x32, 0xef, 0x28, 0x6c, 0x84, 0x45, 0xe0, 0x72, 0x47, 0x5f, - 0xcf, 0xef, 0xfe, 0x8c, 0x8e, 0xaf, 0x87, 0x97, 0x38, 0xe5, 0xfe, 0x89, - 0x23, 0x0c, 0xb2, 0xc9, 0x57, 0x94, 0xc0, 0x9d, 0x7f, 0x75, 0xf8, 0xd8, - 0xf1, 0xd7, 0x38, 0x4e, 0xbf, 0xb8, 0xfa, 0xeb, 0xc8, 0xeb, 0x6e, 0x75, - 0xc8, 0xc9, 0xd7, 0x7d, 0xfc, 0xea, 0x98, 0xd7, 0xfe, 0x2d, 0x7a, 0x4e, - 0x13, 0xae, 0x65, 0x93, 0xaa, 0x48, 0xd7, 0xc1, 0x56, 0x96, 0x22, 0x06, - 0x88, 0xd9, 0x1b, 0xbd, 0xef, 0xbf, 0x94, 0xc1, 0xeb, 0x5f, 0xf2, 0x07, - 0x16, 0x93, 0x23, 0x27, 0x5f, 0xfe, 0x70, 0xe6, 0x0a, 0x9a, 0xd6, 0x0f, - 0xe7, 0x5f, 0x74, 0x0e, 0xa4, 0x22, 0x01, 0x67, 0x17, 0xff, 0xf4, 0x9f, - 0x5a, 0x8c, 0x9c, 0x12, 0x0f, 0x05, 0xd9, 0x3a, 0xef, 0x40, 0x51, 0x2a, - 0x87, 0x57, 0xed, 0x3c, 0xfa, 0xe9, 0xd5, 0x25, 0x62, 0x01, 0x1c, 0xde, - 0x35, 0x94, 0x8d, 0x1b, 0xc5, 0xb7, 0xed, 0x9f, 0x7a, 0x9e, 0x3a, 0xff, - 0xb3, 0xdd, 0x8e, 0x7b, 0x1a, 0x75, 0xe8, 0xe4, 0xc7, 0x54, 0x2f, 0x17, - 0x64, 0x6d, 0x69, 0x08, 0x2e, 0x92, 0xbc, 0xb4, 0x6f, 0xd6, 0x04, 0xaf, - 0x6c, 0xde, 0xf6, 0x9e, 0x63, 0xaf, 0xfe, 0x40, 0xbf, 0x93, 0x59, 0x2c, - 0xe9, 0xd7, 0x3e, 0xd1, 0xd6, 0xce, 0x9e, 0xcf, 0x90, 0x6b, 0x74, 0x4e, - 0x0b, 0xad, 0xf6, 0x6f, 0x3e, 0xc3, 0xaf, 0xf8, 0x43, 0x82, 0x09, 0x66, - 0x8e, 0xbf, 0xdf, 0x7c, 0x39, 0x3a, 0x70, 0xeb, 0xef, 0x26, 0x90, 0xea, - 0xe2, 0x2b, 0xdc, 0x94, 0x4d, 0x80, 0x69, 0x7f, 0xdd, 0x40, 0xa2, 0xa6, - 0x05, 0x0e, 0xbf, 0xcf, 0x2c, 0x0f, 0x35, 0xa3, 0xaf, 0xa3, 0x3e, 0x84, - 0xeb, 0xfc, 0xa2, 0x79, 0xfa, 0xca, 0xb9, 0xd7, 0xfd, 0xcc, 0x9b, 0xb9, - 0xa7, 0x13, 0xaf, 0xfb, 0xb9, 0x2c, 0x02, 0xa5, 0xc4, 0xeb, 0xff, 0xfc, - 0x83, 0x9b, 0xf9, 0x47, 0xf7, 0x63, 0xb9, 0xb1, 0xe4, 0x75, 0x05, 0x35, - 0xd6, 0x99, 0x21, 0x17, 0x0d, 0xfc, 0x6f, 0xb0, 0xea, 0xff, 0x82, 0x9c, - 0x8d, 0x9f, 0xea, 0x47, 0x5d, 0x0b, 0x3a, 0xde, 0x83, 0xd0, 0xe9, 0xdd, - 0xff, 0xa3, 0x4f, 0xd4, 0x0b, 0x52, 0x73, 0xaa, 0x15, 0x51, 0xe4, 0x72, - 0xcf, 0x0a, 0x90, 0x13, 0xde, 0x81, 0xf1, 0xd7, 0xf9, 0x3a, 0x9c, 0x94, - 0xd0, 0x75, 0xff, 0xf9, 0x00, 0xdf, 0xbb, 0xfe, 0xfa, 0x7e, 0x26, 0xff, - 0x9d, 0x7c, 0xfc, 0x89, 0x1d, 0x7f, 0xff, 0x20, 0xba, 0x0f, 0xfc, 0x8e, - 0xba, 0x7a, 0x3a, 0x75, 0x09, 0xfb, 0x78, 0x82, 0xfc, 0x9e, 0xd0, 0x27, - 0x3a, 0xff, 0xfa, 0x05, 0x3f, 0xf6, 0xed, 0x4e, 0x7d, 0x80, 0x9d, 0x41, - 0x4d, 0xa9, 0x21, 0xa0, 0xb2, 0x1f, 0x14, 0x5f, 0xb8, 0x06, 0xf6, 0x0e, - 0xbf, 0xb9, 0x34, 0x93, 0xda, 0x3a, 0xc3, 0x07, 0xab, 0x84, 0xf7, 0xfa, - 0x67, 0x99, 0xf7, 0x96, 0x8e, 0xbf, 0x9e, 0x74, 0x99, 0x19, 0x3a, 0xb0, - 0xf8, 0xdc, 0xd6, 0xfe, 0x9f, 0x06, 0x7c, 0x64, 0xeb, 0xfe, 0x89, 0xfe, - 0xcb, 0xa0, 0x79, 0xce, 0xac, 0x3e, 0xae, 0x17, 0x5f, 0xa3, 0x9c, 0xce, - 0x9d, 0x7f, 0x0b, 0xa9, 0x0b, 0x83, 0xaa, 0x47, 0xa2, 0x02, 0x6b, 0xe8, - 0x9d, 0x45, 0x0e, 0xbf, 0xff, 0x23, 0x61, 0x7a, 0x7e, 0x62, 0xc0, 0xd7, - 0x91, 0xd7, 0x26, 0xc3, 0xad, 0xd3, 0xaa, 0x47, 0xf4, 0xae, 0xa6, 0x01, - 0x7b, 0xc1, 0x85, 0x9d, 0x7f, 0xb3, 0xfc, 0x9a, 0x37, 0xd1, 0xd5, 0x07, - 0x9f, 0x83, 0x77, 0xf7, 0x5e, 0x51, 0xa9, 0x1d, 0x7f, 0xd9, 0xd4, 0xdf, - 0x5d, 0x06, 0x8e, 0xbb, 0x05, 0xa7, 0xcb, 0xf9, 0x65, 0xfc, 0x2f, 0xf8, - 0x70, 0x4e, 0xbf, 0x26, 0xde, 0x71, 0x43, 0xae, 0x52, 0x47, 0x5f, 0xba, - 0x9b, 0x11, 0xa7, 0x5d, 0x9d, 0x91, 0xbf, 0x68, 0xbd, 0x2d, 0x12, 0xbb, - 0x6d, 0x37, 0x99, 0x65, 0x92, 0xaf, 0xfd, 0xc1, 0x03, 0xfd, 0xc9, 0xa1, - 0x67, 0x30, 0x5f, 0xdf, 0xba, 0x93, 0x23, 0x27, 0x54, 0x1f, 0xbe, 0x27, - 0xdf, 0xe8, 0x0e, 0x4a, 0x05, 0xa7, 0x54, 0x2f, 0xc8, 0x48, 0x6b, 0x23, - 0x9c, 0x57, 0x84, 0xbc, 0xd0, 0x88, 0xe4, 0x22, 0x96, 0xe5, 0xd2, 0x27, - 0x84, 0xf0, 0xc2, 0x07, 0x50, 0x85, 0xf1, 0x68, 0x21, 0x80, 0xcc, 0x2f, - 0x3e, 0x90, 0x5f, 0x73, 0x99, 0xd3, 0xaf, 0xee, 0xa6, 0xd6, 0xd0, 0x14, - 0x3a, 0xa0, 0xf5, 0x5a, 0x43, 0x65, 0x49, 0xd6, 0x43, 0xaf, 0xfb, 0xd1, - 0xcd, 0x76, 0x07, 0xc7, 0x59, 0x52, 0x75, 0xff, 0x7a, 0x39, 0xae, 0xc0, - 0xf8, 0xeb, 0xb5, 0x07, 0x5e, 0x58, 0x60, 0xeb, 0xfc, 0x3e, 0x79, 0xb5, - 0x1e, 0x3a, 0x90, 0xf3, 0x5c, 0x6e, 0xf9, 0x1f, 0x1a, 0x75, 0xff, 0xb3, - 0x60, 0xe6, 0xa6, 0x18, 0x09, 0xd7, 0xcd, 0x0c, 0x4e, 0x75, 0xdf, 0xc1, - 0xd7, 0xb4, 0x9c, 0x3a, 0xb0, 0xf4, 0xff, 0x22, 0xf0, 0xb5, 0xfe, 0x96, - 0x0a, 0x07, 0x04, 0xeb, 0xde, 0xd3, 0x10, 0x9e, 0xde, 0x0a, 0x4c, 0x6f, - 0xd6, 0x2f, 0xc8, 0x04, 0x7f, 0x50, 0x91, 0xf1, 0x7d, 0xda, 0x83, 0xaf, - 0x2c, 0x30, 0x75, 0xfe, 0x1f, 0x3c, 0xda, 0x8f, 0x1d, 0x48, 0x79, 0xae, - 0x37, 0x7c, 0x8f, 0x8d, 0x3a, 0xff, 0xd9, 0xb0, 0x73, 0x53, 0x0c, 0x04, - 0xeb, 0xe6, 0x86, 0x27, 0x3a, 0xfe, 0x9b, 0xf4, 0x57, 0x79, 0x8e, 0xbb, - 0xf8, 0x3a, 0xf6, 0x93, 0x87, 0x56, 0x22, 0x15, 0xa4, 0x5f, 0x99, 0x78, - 0x5a, 0xff, 0x4b, 0x05, 0x03, 0x82, 0x75, 0xfc, 0x2e, 0x1c, 0x51, 0x88, - 0x5c, 0x8e, 0x08, 0xa6, 0x07, 0xb6, 0x50, 0x94, 0xd0, 0x89, 0xeb, 0x17, - 0xe4, 0x02, 0x3f, 0xa8, 0x61, 0xf8, 0xf6, 0xff, 0xee, 0x46, 0xfa, 0x18, - 0x5e, 0x6f, 0xe3, 0xaf, 0xff, 0xce, 0x1c, 0xc1, 0x53, 0xe8, 0xc0, 0xce, - 0x9c, 0x3a, 0xf3, 0xf2, 0x73, 0xc8, 0x25, 0x7d, 0x2c, 0xde, 0x47, 0x90, - 0x4a, 0xf6, 0x90, 0x27, 0x90, 0x4a, 0xe6, 0x59, 0x3c, 0x82, 0x54, 0xd4, - 0x52, 0xcc, 0x53, 0xe2, 0xf6, 0x4a, 0x2e, 0x7f, 0x16, 0x41, 0x23, 0x06, - 0xfe, 0xfe, 0xce, 0xe6, 0x0a, 0x87, 0x5e, 0x71, 0xff, 0xe2, 0xfa, 0x5c, - 0x4e, 0x57, 0xf2, 0x18, 0x2b, 0x44, 0x18, 0xce, 0x3c, 0x69, 0x7d, 0xb7, - 0x8f, 0xd3, 0xad, 0x8a, 0xe8, 0xa1, 0xfd, 0xfa, 0xd2, 0x3a, 0xff, 0x4d, - 0x20, 0x4f, 0xe4, 0x9c, 0xab, 0x41, 0xd7, 0xf9, 0x24, 0x07, 0xd7, 0x50, - 0xeb, 0xfb, 0x36, 0x3a, 0xf3, 0xa7, 0x5a, 0x45, 0x5e, 0x7e, 0x4e, 0x55, - 0x15, 0x50, 0x6d, 0x9a, 0x20, 0xb1, 0xcb, 0xd1, 0xfb, 0x4a, 0x60, 0xd6, - 0xd2, 0xd1, 0x7a, 0x30, 0x90, 0xa8, 0x4c, 0x57, 0x21, 0xdd, 0x7f, 0xfd, - 0xf4, 0x65, 0xae, 0x87, 0x39, 0xfa, 0xd3, 0x47, 0x5f, 0x01, 0xf9, 0x23, - 0xac, 0xb3, 0xae, 0xc9, 0x04, 0xd8, 0xcc, 0x43, 0x7e, 0x67, 0x26, 0x45, - 0x9d, 0x7f, 0x36, 0x26, 0x94, 0x7e, 0x55, 0x90, 0xeb, 0xfe, 0x9c, 0x12, - 0x0f, 0x40, 0xe2, 0x75, 0xfc, 0x90, 0xb9, 0xf1, 0x93, 0xaf, 0xd9, 0x3a, - 0xf1, 0x67, 0x5e, 0xd2, 0x70, 0xea, 0x13, 0xc2, 0xf1, 0x3d, 0xfc, 0x2f, - 0xff, 0xe0, 0xd1, 0xd7, 0xf2, 0x29, 0xf6, 0x16, 0xc0, 0x53, 0x06, 0xc0, - 0xfe, 0x1c, 0xe9, 0xbf, 0xc4, 0x35, 0x89, 0xe6, 0x21, 0x40, 0xc6, 0x69, - 0x7c, 0x39, 0x38, 0x0e, 0xbf, 0xec, 0xf7, 0xc1, 0xcf, 0xfe, 0xee, 0x75, - 0x49, 0x73, 0x2c, 0x25, 0x98, 0x21, 0xc3, 0x6e, 0xc6, 0x49, 0xf9, 0x38, - 0xc2, 0x0f, 0x51, 0xfc, 0xf8, 0xd3, 0x6c, 0x86, 0xff, 0xfd, 0x3f, 0x39, - 0x81, 0x75, 0xf5, 0xfc, 0x31, 0x31, 0xd7, 0xff, 0xff, 0x81, 0xc0, 0x4c, - 0x2f, 0xfe, 0xb5, 0x8a, 0x60, 0x38, 0xe1, 0x8e, 0xc1, 0xd7, 0xdb, 0x5d, - 0x07, 0xd3, 0xaf, 0x32, 0xcb, 0x25, 0x5d, 0x28, 0x29, 0x82, 0xfe, 0xa1, - 0x33, 0x89, 0xd5, 0x77, 0x78, 0xe2, 0x35, 0xfc, 0xa4, 0x73, 0x99, 0xd3, - 0xaf, 0xe9, 0xe6, 0x92, 0xab, 0x93, 0x9d, 0x7d, 0xd7, 0xdd, 0x93, 0xaf, - 0xd3, 0xf1, 0x21, 0x67, 0x5f, 0xff, 0x47, 0xdf, 0x0c, 0x7e, 0xfe, 0xff, - 0xe8, 0xc8, 0xea, 0x56, 0x51, 0xa4, 0x86, 0xae, 0x47, 0xe2, 0x7b, 0xff, - 0x3f, 0xb4, 0xce, 0x77, 0xf7, 0xf1, 0xd7, 0xff, 0xfe, 0xcf, 0x43, 0x47, - 0x30, 0x62, 0x5e, 0xeb, 0xac, 0x73, 0x61, 0xd4, 0x14, 0x53, 0xb2, 0x7f, - 0x7b, 0xe8, 0x66, 0x3a, 0xf4, 0x90, 0x4e, 0xbe, 0x9f, 0xee, 0xd3, 0x27, - 0x5f, 0xf4, 0x75, 0xd3, 0xd3, 0x23, 0x27, 0x5f, 0xfe, 0x52, 0x35, 0xc8, - 0xe8, 0xe7, 0xa1, 0x67, 0x5f, 0xf6, 0x87, 0x36, 0x24, 0xc8, 0xc9, 0xd7, - 0xff, 0xf0, 0x1e, 0x76, 0x82, 0x7f, 0x67, 0x47, 0x3d, 0xd4, 0x3a, 0xfd, - 0x13, 0x08, 0x34, 0x75, 0x62, 0x60, 0x88, 0x91, 0xd3, 0xaf, 0x2d, 0xdc, - 0x82, 0x75, 0xfc, 0xe3, 0xfe, 0x79, 0x43, 0xaa, 0x15, 0x1f, 0xce, 0x49, - 0x21, 0xf7, 0x1a, 0x12, 0x9f, 0x46, 0x79, 0xb0, 0xf3, 0x6c, 0x52, 0xfb, - 0xa0, 0x5c, 0x1d, 0x73, 0xe8, 0xeb, 0x80, 0xa9, 0x3a, 0x9c, 0xf4, 0x04, - 0x84, 0x02, 0xb7, 0x3b, 0x0a, 0x87, 0xca, 0x86, 0x56, 0xdb, 0x15, 0x50, - 0x93, 0x56, 0x85, 0x6a, 0xd4, 0x8d, 0x57, 0x1d, 0xc4, 0xe1, 0x4c, 0xf2, - 0x81, 0xe5, 0x0d, 0xb0, 0xca, 0xa4, 0xca, 0x43, 0xe2, 0x91, 0x97, 0x36, - 0x3b, 0x0d, 0xe3, 0x5a, 0x49, 0x48, 0x93, 0x4a, 0x31, 0xe4, 0x7d, 0x0b, - 0x94, 0xcd, 0xd9, 0xfe, 0xe7, 0x8c, 0x87, 0xf8, 0x69, 0x0c, 0xad, 0xed, - 0x4f, 0xeb, 0xfa, 0x9c, 0x18, 0x08, 0xf6, 0x59, 0x3f, 0xdb, 0x87, 0xff, - 0xd9, 0x64, 0xdb, 0x50, 0xcc, 0xbf, 0x2f, 0x11, 0xff, 0x3a, 0xf9, 0xae, - 0xed, 0x34, 0x51, 0x57, 0xff, 0xe7, 0xfe, 0x1b, 0xd4, 0xd7, 0x53, 0xdd, - 0xc1, 0x3a, 0xb8, 0x88, 0x01, 0x2d, 0xbf, 0x30, 0xb7, 0x93, 0x10, 0x8c, - 0x8c, 0x85, 0x35, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2e, 0x8b, 0xff, - 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x5d, 0xfb, 0x8d, 0x77, - 0x69, 0xa2, 0xf2, 0xb9, 0xf6, 0x1d, 0x66, 0x30, 0xf2, 0xb6, 0xcc, 0xea, - 0x1f, 0x50, 0x3a, 0x72, 0x89, 0x1f, 0xe4, 0x26, 0x1b, 0x09, 0x59, 0x8e, - 0x16, 0x7f, 0xd9, 0x52, 0x23, 0x79, 0x61, 0x7a, 0x96, 0x3b, 0xe4, 0x50, - 0x1f, 0xec, 0x84, 0xdd, 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, - 0x9a, 0x25, 0x9b, 0x81, 0xd3, 0xaf, 0xf2, 0x07, 0xb8, 0x82, 0xa1, 0xd7, - 0xdd, 0x7f, 0x00, 0xeb, 0xee, 0xc2, 0xba, 0xce, 0xbc, 0x06, 0xb9, 0xd5, - 0x24, 0x48, 0xa1, 0x8a, 0xb9, 0x0f, 0xd2, 0x4b, 0xf8, 0x3e, 0x03, 0xcb, - 0x47, 0x5e, 0xf3, 0xac, 0xeb, 0xff, 0x76, 0x3a, 0x8a, 0x7b, 0x4f, 0xf9, - 0xd7, 0xf0, 0xfb, 0x90, 0xed, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x46, 0x77, - 0xf2, 0x42, 0xe7, 0xc6, 0x4e, 0xb8, 0x64, 0x75, 0x96, 0x75, 0xf9, 0x39, - 0xd7, 0x63, 0x87, 0xa4, 0xb2, 0xdf, 0xa2, 0xb7, 0xf3, 0xc9, 0x38, 0xfc, - 0x3a, 0xff, 0xed, 0x20, 0x35, 0x82, 0x09, 0x66, 0x8e, 0xbd, 0xa8, 0xdc, - 0xea, 0x92, 0x78, 0x18, 0x7f, 0xc2, 0xb5, 0xbf, 0x8a, 0x76, 0x8a, 0xfc, - 0x85, 0x7f, 0xdc, 0x76, 0x7a, 0x91, 0xc8, 0x3a, 0xff, 0xa5, 0xac, 0x8f, - 0x91, 0xa5, 0x9d, 0x7d, 0xbf, 0x63, 0x47, 0x5f, 0x6a, 0x3d, 0xa3, 0xab, - 0x0f, 0x0f, 0x44, 0x57, 0xff, 0x79, 0x38, 0xff, 0xfc, 0xde, 0x50, 0xb3, - 0xaf, 0xc3, 0x12, 0xd3, 0x9d, 0x48, 0x7d, 0x9b, 0x11, 0xef, 0xff, 0xff, - 0xb3, 0xde, 0x45, 0xf1, 0x33, 0x71, 0x07, 0xa3, 0xbf, 0x36, 0x27, 0xa6, - 0x83, 0xaf, 0xf3, 0xcb, 0x5a, 0x71, 0x91, 0xd7, 0xe5, 0x3d, 0xe8, 0x59, - 0xd7, 0xff, 0xbd, 0x0d, 0x4f, 0x22, 0xe6, 0xd2, 0x09, 0xd6, 0x91, 0xd4, - 0x87, 0xb1, 0xf5, 0x22, 0xfd, 0xfc, 0x7a, 0x02, 0x75, 0x22, 0x32, 0x9e, - 0x10, 0x00, 0x23, 0xbf, 0xfe, 0x07, 0xb5, 0xbc, 0xa0, 0x7f, 0xd7, 0xc0, - 0x09, 0xd7, 0xa3, 0xd0, 0x75, 0x04, 0xfb, 0x76, 0x29, 0xde, 0xee, 0x09, - 0xd4, 0x86, 0xf8, 0x04, 0x97, 0x76, 0x63, 0xaf, 0xf6, 0xfa, 0x1c, 0xe0, - 0x60, 0xea, 0x43, 0xc9, 0x71, 0x7b, 0xef, 0x74, 0x1b, 0x67, 0x5f, 0xec, - 0x8e, 0x3c, 0x93, 0xa7, 0x5f, 0xe4, 0x67, 0x51, 0xd7, 0x57, 0x3a, 0xb8, - 0x7c, 0xbe, 0x30, 0xa4, 0x45, 0x62, 0xe1, 0x15, 0x7f, 0xf9, 0x3a, 0x05, - 0x70, 0xf4, 0x1a, 0xde, 0x4e, 0x75, 0x61, 0xfa, 0xb9, 0x3d, 0xef, 0xb8, - 0xaa, 0x3a, 0xff, 0xf0, 0x3f, 0x5a, 0x0e, 0x7e, 0x38, 0xf3, 0x1d, 0x7f, - 0xd0, 0x9d, 0x48, 0x19, 0x80, 0x75, 0xff, 0x80, 0x1e, 0x60, 0x3b, 0x0b, - 0xc3, 0xab, 0x11, 0xbb, 0xc2, 0x1e, 0xa4, 0xe8, 0xda, 0xff, 0xfb, 0x79, - 0x27, 0x03, 0xd0, 0x73, 0x1b, 0xdc, 0x3a, 0xe4, 0x64, 0xeb, 0xb6, 0xb0, - 0xea, 0xd1, 0xae, 0xf0, 0xb5, 0xfd, 0xa8, 0xf6, 0xba, 0x87, 0x5f, 0x87, - 0x17, 0xcc, 0x3a, 0xfb, 0x9b, 0x30, 0x27, 0x56, 0x1f, 0xa2, 0xcb, 0x00, - 0x4b, 0x7d, 0xfa, 0x6f, 0x23, 0xaf, 0xf4, 0x0f, 0x92, 0x71, 0x83, 0xaf, - 0xff, 0x27, 0x12, 0x78, 0x1c, 0xef, 0x01, 0xb0, 0xea, 0xfd, 0x13, 0xa2, - 0x47, 0xe3, 0x0b, 0x30, 0xad, 0xb3, 0x00, 0x22, 0x14, 0xf3, 0xa0, 0x84, - 0xb7, 0x23, 0xdb, 0x51, 0x8f, 0x73, 0x74, 0x7c, 0x9a, 0x11, 0xbc, 0x23, - 0x5c, 0x20, 0x3b, 0x0f, 0xb7, 0x86, 0xf7, 0xed, 0x23, 0x1a, 0x0e, 0xa1, - 0xfb, 0xe3, 0xcd, 0x8f, 0xdb, 0x70, 0x95, 0xfb, 0x0c, 0xbb, 0xff, 0xcc, - 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4d, 0x37, 0xff, 0x98, 0x5b, - 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9c, 0x6f, 0xff, 0x30, 0xb7, 0x93, - 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x40, 0xdf, 0xb8, 0xd7, 0x76, 0x9a, 0x2e, - 0x0b, 0xf8, 0x73, 0xcd, 0x4d, 0x1d, 0x74, 0x21, 0xd7, 0xf8, 0x65, 0x08, - 0x1c, 0x59, 0xd5, 0x88, 0xa2, 0x59, 0x9f, 0x4a, 0xc0, 0x29, 0x7e, 0x93, - 0x0a, 0x2a, 0x14, 0x3a, 0x98, 0x3e, 0xb8, 0x3c, 0xb9, 0xff, 0x3a, 0xfd, - 0x34, 0xa0, 0x64, 0x75, 0x1d, 0x58, 0x6c, 0x44, 0x9e, 0xfa, 0x3f, 0xc6, - 0x4e, 0xb9, 0x18, 0xe2, 0x22, 0x05, 0x1f, 0xe8, 0xfd, 0xff, 0x49, 0x8c, - 0xe3, 0x5d, 0xda, 0x68, 0x92, 0x6c, 0xc7, 0x51, 0x04, 0xe7, 0xb7, 0x33, - 0xf9, 0xd7, 0xf9, 0xfc, 0x39, 0x3b, 0x89, 0xd7, 0xf6, 0x0b, 0xef, 0x2d, - 0x1d, 0x7f, 0x42, 0xf9, 0x81, 0xf1, 0xd7, 0x3b, 0x01, 0x45, 0x02, 0x83, - 0x1c, 0x30, 0xd1, 0x65, 0x4e, 0xd9, 0x00, 0x4a, 0x98, 0xae, 0xd8, 0xd6, - 0x26, 0x57, 0xfd, 0x5f, 0x51, 0xb2, 0x7a, 0x32, 0xcd, 0x90, 0xc9, 0xbf, - 0xf2, 0x8e, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x5a, 0x97, 0xfe, 0x79, 0x31, - 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xad, 0xc8, 0xc9, 0xd4, 0x75, 0x98, 0x51, - 0x16, 0xab, 0x4b, 0xf2, 0x56, 0xd0, 0xb5, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, - 0x11, 0x4d, 0xff, 0xcb, 0x63, 0xc2, 0xff, 0xeb, 0xd8, 0xd3, 0xa9, 0x83, - 0xfd, 0x73, 0x8b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x46, 0x97, 0x03, - 0xa7, 0x5f, 0xf8, 0x38, 0xb4, 0xe6, 0x6a, 0x68, 0x3a, 0xff, 0xff, 0x9c, - 0x1a, 0xee, 0x07, 0xef, 0xdd, 0x27, 0xdf, 0x26, 0xa6, 0xfa, 0x75, 0xe4, - 0x76, 0x4e, 0xa4, 0x46, 0x3a, 0xb9, 0xea, 0xdb, 0xef, 0x9a, 0xee, 0xd3, - 0x45, 0x3f, 0x77, 0xa0, 0xea, 0xe1, 0xe1, 0x78, 0xb6, 0xff, 0xde, 0x9a, - 0x3d, 0xd7, 0x9b, 0xe6, 0x1d, 0x7f, 0xf9, 0x16, 0x20, 0xea, 0x73, 0x35, - 0x34, 0x1d, 0x7f, 0xf0, 0x3d, 0xc0, 0x4d, 0xa6, 0xbc, 0xda, 0x3a, 0xff, - 0xec, 0x98, 0x03, 0x3e, 0x9a, 0xf3, 0x68, 0xeb, 0x30, 0xad, 0xaa, 0x89, - 0x88, 0x6e, 0xe3, 0xa2, 0x11, 0x3a, 0x08, 0xa4, 0x79, 0x1e, 0xff, 0xf3, - 0x0b, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, 0x55, 0xfe, 0x63, 0x38, - 0xd7, 0x76, 0x9a, 0x2b, 0xbb, 0xe6, 0xbb, 0xb4, 0xd1, 0x5f, 0x5e, 0x65, - 0x96, 0x4a, 0xb0, 0x94, 0xc1, 0x7f, 0x5c, 0x3e, 0xb5, 0xa6, 0x5e, 0x94, - 0x6e, 0x75, 0xe9, 0xb3, 0xa7, 0x5f, 0xfb, 0x3a, 0xcb, 0xfb, 0x51, 0x93, - 0x9d, 0x6f, 0x1d, 0x7f, 0xc9, 0xcc, 0x9d, 0x25, 0x81, 0x3a, 0xb8, 0x78, - 0xee, 0x21, 0x7e, 0xdf, 0x6b, 0xa0, 0xfa, 0x75, 0xb8, 0x75, 0x1d, 0x6e, - 0xa1, 0x75, 0xc1, 0x0b, 0x31, 0x89, 0xb6, 0xcc, 0x44, 0xe3, 0x82, 0x39, - 0xa8, 0x42, 0x80, 0x87, 0x6d, 0x22, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, - 0x6b, 0xbb, 0x4d, 0x13, 0xdd, 0xfb, 0xb1, 0xb4, 0xfb, 0x9d, 0x7e, 0xe3, - 0x5d, 0xda, 0x68, 0xb8, 0x6c, 0xc4, 0x1e, 0xee, 0x15, 0x5f, 0xfc, 0xc3, - 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x93, 0xea, 0x19, 0x05, 0xb3, 0xc3, - 0x16, 0x44, 0x4a, 0x4a, 0xc8, 0x6b, 0x94, 0xca, 0xfc, 0x94, 0x2f, 0xd7, - 0x2d, 0x42, 0xd3, 0x61, 0x3d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x22, - 0xab, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x33, 0x7f, 0x27, 0x71, 0xf7, 0xfc, - 0xeb, 0x31, 0x87, 0xc1, 0xb6, 0x67, 0x7f, 0xf9, 0x85, 0xbc, 0x98, 0xce, - 0x35, 0xdd, 0xa6, 0x89, 0x9e, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, 0x6b, - 0xbb, 0x4d, 0x14, 0x6d, 0x4e, 0x9b, 0xc0, 0x61, 0x3e, 0xa1, 0x5f, 0x95, - 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x23, 0xab, 0xff, 0xb9, - 0x3b, 0x1a, 0x1c, 0xf6, 0xa1, 0x67, 0x53, 0x08, 0x8f, 0x84, 0xab, 0x81, - 0xd3, 0xaf, 0x9a, 0xd0, 0x34, 0xeb, 0xf6, 0x08, 0x72, 0x73, 0xaf, 0xf4, - 0x43, 0x73, 0x9c, 0xc3, 0xa9, 0x0f, 0x58, 0x49, 0xaf, 0xd9, 0xc6, 0x81, - 0x43, 0xaf, 0xfc, 0x38, 0xa3, 0xcd, 0xae, 0xc0, 0x4e, 0xbd, 0x33, 0xf8, - 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x4d, 0x5f, 0xb3, 0x76, 0x5f, 0xa7, 0x5f, - 0xfd, 0xac, 0x10, 0xc7, 0xc5, 0x5f, 0xb3, 0xf4, 0x3a, 0x82, 0x99, 0x22, - 0x14, 0x4c, 0x7d, 0xc1, 0xc1, 0x2d, 0xd1, 0x45, 0xff, 0xff, 0x60, 0xfb, - 0x48, 0xdc, 0x1d, 0x37, 0xa9, 0xd6, 0xfd, 0x9c, 0xeb, 0xfe, 0xd3, 0xef, - 0x93, 0x47, 0x74, 0x75, 0xdd, 0x41, 0x45, 0x07, 0x99, 0xef, 0xfe, 0x97, - 0x50, 0x67, 0xd0, 0x23, 0x93, 0x1d, 0x7f, 0xda, 0xd3, 0x53, 0x9c, 0x49, - 0xce, 0xbf, 0xf6, 0x32, 0xff, 0xbf, 0xbd, 0x9d, 0x3a, 0xff, 0xc2, 0x0f, - 0x77, 0x26, 0x94, 0x6e, 0x75, 0xa6, 0x3a, 0xfd, 0x9d, 0x71, 0x09, 0xd5, - 0x39, 0xb6, 0xfc, 0x46, 0xe8, 0x50, 0xeb, 0xf9, 0xff, 0xd2, 0xac, 0xab, - 0x2a, 0xc7, 0x5f, 0xc9, 0x0b, 0x9f, 0x19, 0x3a, 0xff, 0xfb, 0x3d, 0xdc, - 0x97, 0x1c, 0x7d, 0xd7, 0x91, 0xd7, 0x47, 0xe7, 0x5f, 0xe7, 0xde, 0x1a, - 0x8d, 0x63, 0x88, 0x90, 0x12, 0xdf, 0xa9, 0xb5, 0x89, 0xea, 0xa3, 0xaf, - 0x48, 0xc4, 0x5b, 0x50, 0xcd, 0xbf, 0x7b, 0xac, 0xbc, 0xe7, 0x59, 0x85, - 0x6d, 0x77, 0xf6, 0x05, 0x82, 0xf1, 0x91, 0xa2, 0x36, 0x1e, 0xfb, 0x96, - 0xf1, 0x14, 0x4e, 0x7d, 0x28, 0x4f, 0xea, 0x6d, 0xfb, 0x8d, 0x77, 0x69, - 0xa2, 0xaa, 0xbf, 0xf3, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9b, 0x6c, - 0xc6, 0x1f, 0xea, 0xcc, 0xef, 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x5f, - 0xdf, 0xb8, 0xd7, 0x76, 0x9a, 0x2c, 0x6b, 0xb6, 0xa4, 0x75, 0x98, 0xc3, - 0xcc, 0x98, 0xce, 0xfd, 0xa6, 0xf6, 0x14, 0x3a, 0xff, 0x08, 0x25, 0x9a, - 0x7f, 0x1d, 0x77, 0x3c, 0x75, 0xff, 0x67, 0xbd, 0x9c, 0x0e, 0x09, 0xd7, - 0x94, 0x96, 0x1d, 0x66, 0x31, 0x13, 0x2e, 0x62, 0x22, 0xda, 0x36, 0xb2, - 0x30, 0x98, 0x17, 0x21, 0x83, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb5, 0x6f, - 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0x2b, 0xf4, 0x33, 0xb7, - 0x9c, 0x3a, 0xcc, 0x62, 0x29, 0xd6, 0x67, 0xf5, 0x2a, 0xff, 0x40, 0xff, - 0x0a, 0xee, 0xb3, 0xae, 0xe4, 0x1d, 0x52, 0x3c, 0x9d, 0xa3, 0x4b, 0xe6, - 0xbb, 0xb4, 0xd1, 0x71, 0x5f, 0xc0, 0x7d, 0xc3, 0x9c, 0x3a, 0xb8, 0x7b, - 0x5a, 0x2d, 0xbd, 0xc8, 0x59, 0xd7, 0xcf, 0xb4, 0x93, 0x9d, 0x7e, 0xe8, - 0x14, 0xc1, 0x3a, 0xf6, 0xd2, 0x34, 0xea, 0x09, 0xe2, 0xed, 0x13, 0xdf, - 0xe5, 0xbc, 0xb4, 0x81, 0xc3, 0xaf, 0xf4, 0x2d, 0xf6, 0x47, 0x36, 0x8e, - 0xbf, 0xb3, 0x8f, 0xe0, 0x41, 0xd7, 0xff, 0xce, 0x30, 0x9b, 0x5a, 0x4d, - 0x67, 0x73, 0x6c, 0xea, 0x09, 0xfe, 0x6c, 0x2b, 0xbf, 0xf9, 0x04, 0x12, - 0xcd, 0x69, 0x03, 0x87, 0x54, 0xc7, 0xcb, 0xe2, 0x4b, 0x31, 0x0a, 0xad, - 0x71, 0xff, 0x84, 0x5d, 0x1b, 0x76, 0x9f, 0xc9, 0x7c, 0x63, 0xf6, 0x31, - 0x7b, 0xf2, 0xa9, 0x5a, 0x7e, 0xa4, 0x1d, 0x7f, 0xe4, 0xdd, 0x56, 0xd7, - 0x3e, 0x7c, 0xee, 0xd9, 0xd7, 0xdd, 0x8f, 0x34, 0xea, 0x56, 0xa7, 0xda, - 0x14, 0xcb, 0xff, 0xca, 0xb2, 0x8c, 0xab, 0xce, 0x15, 0x57, 0xcf, 0x9d, - 0xdb, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x74, 0xdf, 0xa0, 0x5c, 0x30, - 0x75, 0xe8, 0xf6, 0xd1, 0xd7, 0xd8, 0x1c, 0x09, 0xd7, 0xfc, 0xfb, 0x23, - 0xda, 0x03, 0x55, 0x27, 0x59, 0x85, 0x59, 0x3f, 0xd8, 0x85, 0x04, 0x8a, - 0x31, 0x89, 0x0c, 0xfa, 0x48, 0xe3, 0xc2, 0x41, 0x7f, 0xfd, 0x83, 0xe4, - 0x5f, 0x61, 0x05, 0xf8, 0xa1, 0xd7, 0xf4, 0xf1, 0xe7, 0x50, 0x07, 0x51, - 0xd7, 0xff, 0x47, 0x3f, 0xf9, 0xae, 0xc2, 0xdc, 0x4e, 0xbf, 0xd1, 0xcf, - 0xbd, 0xee, 0x7e, 0x75, 0x48, 0xfe, 0xba, 0x8b, 0x7f, 0x49, 0xe4, 0xe2, - 0xd3, 0xaf, 0xff, 0x67, 0xa1, 0x9f, 0xb3, 0xeb, 0x17, 0x0a, 0xe7, 0x59, - 0x85, 0x65, 0x32, 0x0c, 0x84, 0x24, 0xc4, 0x42, 0x57, 0x5c, 0x4e, 0x71, - 0x71, 0xa7, 0x5f, 0x63, 0x2a, 0xca, 0xce, 0xbf, 0xe4, 0xe0, 0xc6, 0xeb, - 0x7f, 0x1d, 0x7f, 0xff, 0xc0, 0xe4, 0xb5, 0xd7, 0x4e, 0x73, 0x80, 0xdd, - 0x38, 0xfa, 0x3a, 0xff, 0xc2, 0xec, 0xfb, 0x3a, 0xf3, 0x39, 0xd7, 0xff, - 0xf7, 0x44, 0x0e, 0xaf, 0x92, 0xee, 0x29, 0x81, 0x98, 0x07, 0x5c, 0xdc, - 0x3a, 0xa0, 0xfc, 0xd4, 0x5e, 0xbc, 0xa6, 0xa4, 0x75, 0xff, 0xa5, 0x9c, - 0xe3, 0xca, 0x7c, 0x64, 0xeb, 0xff, 0xb0, 0x31, 0x28, 0xe4, 0x7d, 0x71, - 0x3a, 0xff, 0xdb, 0x32, 0x4b, 0x0a, 0x6c, 0x80, 0x9d, 0x4b, 0x44, 0x1b, - 0xa1, 0x5c, 0xec, 0x4e, 0xa8, 0xea, 0x66, 0x7e, 0x42, 0xc3, 0x44, 0x5e, - 0x1d, 0xfb, 0x0c, 0x2a, 0xea, 0xae, 0x41, 0x94, 0xe3, 0x7f, 0xef, 0x23, - 0x50, 0x2e, 0x2a, 0x41, 0xd7, 0xfd, 0x1b, 0xf5, 0xf5, 0xe8, 0x64, 0xea, - 0x83, 0xf5, 0xe1, 0xe5, 0xc0, 0xe9, 0xd7, 0xe1, 0xce, 0xbf, 0x8e, 0xbf, - 0xa4, 0xf9, 0xb2, 0x02, 0x75, 0x2a, 0x0f, 0x49, 0x57, 0x92, 0xdf, 0x20, - 0x25, 0x07, 0x5f, 0x9e, 0x69, 0x27, 0x8e, 0xbf, 0xf4, 0x07, 0x91, 0x24, - 0xdf, 0xd8, 0x75, 0x49, 0x10, 0x9f, 0x90, 0x78, 0x9e, 0xff, 0xff, 0xa0, - 0x3d, 0xcd, 0xfc, 0x2f, 0xdf, 0xdf, 0x5a, 0x7e, 0x34, 0xeb, 0xfd, 0x99, - 0x8a, 0x28, 0xf2, 0x3a, 0x94, 0x44, 0xc7, 0x99, 0xaf, 0xdb, 0x13, 0x98, - 0x13, 0xaf, 0xff, 0xb5, 0xd4, 0xd7, 0xbb, 0x81, 0x4d, 0x60, 0x9d, 0x7b, - 0xb0, 0x38, 0x7e, 0xa0, 0x28, 0xbf, 0xd0, 0xbc, 0x45, 0xc2, 0xb9, 0xd7, - 0xfa, 0x4b, 0xd2, 0x0e, 0xf2, 0x3a, 0x9a, 0x7c, 0xd3, 0x19, 0xde, 0x77, - 0x69, 0xa2, 0x4c, 0xbd, 0xb4, 0x9a, 0x3a, 0x9a, 0x78, 0xbb, 0x44, 0xf7, - 0xe6, 0xaa, 0xca, 0xa5, 0x65, 0x50, 0x75, 0xfe, 0xcd, 0xfd, 0xe7, 0x96, - 0x8e, 0xa8, 0x3e, 0xde, 0x1d, 0x5f, 0xe1, 0x7f, 0x69, 0xa0, 0x13, 0xaf, - 0xff, 0xee, 0x67, 0xe9, 0xfb, 0x38, 0x9b, 0x07, 0x3d, 0xd4, 0x3a, 0xb1, - 0x11, 0xa8, 0x63, 0x52, 0x54, 0xc1, 0x90, 0x97, 0xe3, 0x42, 0xe1, 0x25, - 0xd8, 0x57, 0x5f, 0xc1, 0xfd, 0x51, 0xaf, 0xf6, 0xce, 0xbd, 0xa4, 0x09, - 0xd7, 0xf0, 0xc6, 0xeb, 0x7f, 0x1d, 0x7f, 0xd0, 0xdf, 0x03, 0xbc, 0x86, - 0x4e, 0xbf, 0xcd, 0x4e, 0x6a, 0x68, 0x73, 0xaf, 0xfe, 0x06, 0xba, 0xf2, - 0xeb, 0xca, 0x04, 0xea, 0xdc, 0xfd, 0x38, 0x65, 0x77, 0x52, 0x64, 0xc5, - 0xf8, 0x36, 0xb2, 0xcf, 0x42, 0xb6, 0xfb, 0xc8, 0xb7, 0x3a, 0xff, 0x27, - 0x75, 0x1e, 0x80, 0x9d, 0x58, 0x7a, 0x3e, 0x20, 0xbf, 0xe8, 0xef, 0x92, - 0x75, 0xc3, 0x4e, 0xbf, 0xff, 0x3b, 0x79, 0x1d, 0x1c, 0xf6, 0x30, 0xcb, - 0x2c, 0x95, 0x52, 0x45, 0x86, 0x88, 0x7c, 0x71, 0x7f, 0x35, 0xa0, 0x68, - 0xc1, 0xd7, 0xff, 0xb3, 0x79, 0x0c, 0x4b, 0x91, 0xe7, 0xf1, 0xd7, 0xfe, - 0x7f, 0x47, 0x35, 0xd8, 0x1f, 0x1d, 0x7e, 0xc9, 0x23, 0xec, 0x3a, 0x84, - 0xf8, 0xf4, 0x79, 0x52, 0x46, 0x60, 0x21, 0x57, 0x7f, 0xf8, 0x62, 0x5c, - 0xe0, 0x37, 0x4e, 0x3e, 0x8e, 0xbf, 0xfe, 0xd6, 0x28, 0x39, 0xed, 0x64, - 0x85, 0xd9, 0x3a, 0xed, 0x89, 0xd4, 0x4b, 0xf9, 0x26, 0xfb, 0x6a, 0x3b, - 0xa3, 0xaa, 0x0f, 0x53, 0x0c, 0x2f, 0xef, 0x08, 0x27, 0xdd, 0x5c, 0xeb, - 0xff, 0xd1, 0x38, 0xe6, 0x4f, 0xe5, 0x20, 0x64, 0x75, 0xff, 0x9c, 0x67, - 0xeb, 0xad, 0x34, 0x87, 0x53, 0xa2, 0xdc, 0x4c, 0x99, 0x49, 0xbc, 0xcb, - 0x2c, 0x95, 0x7d, 0x3a, 0xd3, 0x45, 0x30, 0x5f, 0xdd, 0x01, 0x3a, 0xdc, - 0x73, 0xc7, 0x13, 0x2b, 0xff, 0xff, 0x80, 0xe2, 0xde, 0x66, 0xc8, 0x1f, - 0x2e, 0x30, 0x43, 0x9b, 0xf8, 0xeb, 0xfd, 0x28, 0xe4, 0xf1, 0xc9, 0xce, - 0xbf, 0xb5, 0xa4, 0xc1, 0xfc, 0xeb, 0xdc, 0xc5, 0x73, 0xaf, 0xfd, 0x0c, - 0xfd, 0x9f, 0x58, 0xb8, 0x57, 0x3a, 0xb8, 0x88, 0xe5, 0x96, 0x78, 0x7a, - 0xa1, 0x1e, 0x59, 0x0c, 0x2b, 0xf2, 0x7a, 0x7c, 0x64, 0xeb, 0xfe, 0x86, - 0xf4, 0x41, 0xe8, 0xd1, 0xd7, 0xff, 0x26, 0xd4, 0x36, 0x17, 0x81, 0x75, - 0x9d, 0x7f, 0xfe, 0xf7, 0x72, 0x5f, 0x1b, 0xd4, 0xf6, 0xed, 0x4e, 0x1d, - 0x5c, 0x47, 0xda, 0xca, 0x3a, 0x6e, 0x28, 0x97, 0xfc, 0xb8, 0xe6, 0xcc, - 0xe4, 0x4c, 0x75, 0xff, 0xb8, 0xd5, 0xc6, 0xfa, 0xcd, 0x98, 0x75, 0xfe, - 0x1f, 0xf6, 0xf0, 0x38, 0xb3, 0xaf, 0xe1, 0xf9, 0xb7, 0x9c, 0x83, 0xaa, - 0x11, 0x4b, 0x88, 0x0e, 0x6b, 0x7f, 0xd8, 0xff, 0xfc, 0xc0, 0xbc, 0x8e, - 0xbf, 0xfc, 0xf3, 0xf5, 0x20, 0x72, 0x64, 0xe2, 0x1d, 0x58, 0x9e, 0x47, - 0xe7, 0x9a, 0x86, 0xff, 0x8b, 0x59, 0x39, 0xbf, 0x0e, 0x75, 0xfc, 0x75, - 0xff, 0xa5, 0x03, 0x3f, 0xde, 0x08, 0x24, 0x75, 0x2b, 0x9f, 0x2c, 0xc4, - 0xb7, 0xde, 0x9f, 0x02, 0x75, 0xff, 0x22, 0x9f, 0x79, 0xfa, 0xd3, 0x47, - 0x54, 0xc7, 0xbd, 0xb6, 0x45, 0x79, 0x96, 0x59, 0x3a, 0xff, 0xfd, 0x8b, - 0xf0, 0xc7, 0xf8, 0x1d, 0x62, 0xe1, 0xa5, 0x30, 0x5f, 0xdf, 0xec, 0x6f, - 0x52, 0x05, 0xa7, 0x5f, 0xee, 0x47, 0x91, 0xa8, 0x13, 0xaf, 0xd2, 0x9b, - 0x31, 0xa7, 0x5b, 0x87, 0x52, 0xb0, 0x7d, 0x10, 0x63, 0xf4, 0x9e, 0xb1, - 0x3f, 0x94, 0x84, 0x27, 0x51, 0x45, 0x8f, 0x50, 0x98, 0xbd, 0xe9, 0x74, - 0xeb, 0x21, 0xd7, 0xf7, 0x63, 0xe3, 0x52, 0x73, 0xaf, 0xee, 0x3f, 0x06, - 0x24, 0x75, 0xff, 0xf4, 0x29, 0xae, 0xba, 0x7a, 0x16, 0x2e, 0xa1, 0xd7, - 0xfe, 0xcd, 0x9d, 0x4f, 0x9a, 0xd2, 0x2c, 0xeb, 0x9f, 0xd2, 0x44, 0x7f, - 0x53, 0xaf, 0xfc, 0x92, 0x4e, 0x6f, 0x03, 0x1a, 0x3a, 0x95, 0xa2, 0x6c, - 0x41, 0x0f, 0xe1, 0x78, 0xc2, 0xeb, 0xc5, 0xd7, 0x49, 0x85, 0x6d, 0xb4, - 0xbe, 0x55, 0x34, 0x44, 0x2c, 0x25, 0x0c, 0x9c, 0x95, 0xf2, 0xa2, 0xd3, - 0x63, 0x4e, 0xde, 0x35, 0x04, 0x30, 0x9a, 0x1f, 0x1c, 0x8c, 0x4f, 0xb0, - 0xd7, 0x78, 0x4a, 0xfe, 0x4c, 0x31, 0xb1, 0x6a, 0x57, 0x4f, 0xa5, 0x57, - 0xed, 0xa9, 0x7d, 0x8d, 0xfa, 0xff, 0xf7, 0x31, 0x90, 0xf7, 0x26, 0x1c, - 0xe4, 0x8e, 0xbd, 0xcc, 0x57, 0x3a, 0xff, 0xd0, 0xcf, 0xd9, 0xf5, 0x8b, - 0x85, 0x73, 0xab, 0x88, 0xac, 0x5a, 0x57, 0x87, 0xaf, 0xff, 0x9d, 0x71, - 0xc6, 0xf0, 0x0a, 0x70, 0x0f, 0xa3, 0xab, 0x11, 0x00, 0x03, 0x0b, 0xfd, - 0xc6, 0x81, 0xc2, 0xb8, 0x3a, 0xff, 0xe8, 0xe7, 0xdf, 0x27, 0xbb, 0x81, - 0x43, 0xaf, 0xfd, 0xd1, 0x89, 0xfe, 0xf7, 0xae, 0xae, 0x75, 0x42, 0x2e, - 0x67, 0x32, 0xc4, 0x4b, 0xcf, 0xc9, 0xce, 0xb9, 0x96, 0x4e, 0xbc, 0xed, - 0x61, 0xa6, 0xd1, 0x91, 0xcb, 0xfa, 0x38, 0xf2, 0x4e, 0x9d, 0x7e, 0xc5, - 0xf5, 0xc2, 0x75, 0x98, 0x86, 0xfb, 0xdb, 0x23, 0xe8, 0x50, 0xa9, 0xb2, - 0xc2, 0xf9, 0x0a, 0x07, 0xad, 0x37, 0xc6, 0x54, 0xbe, 0xa1, 0xb7, 0xb1, - 0x8d, 0x93, 0x4d, 0xa2, 0xba, 0x93, 0xaf, 0xf3, 0x0c, 0xf1, 0x06, 0xf1, - 0x94, 0xf0, 0xa1, 0x70, 0x8b, 0xec, 0x65, 0x7f, 0xc3, 0x5b, 0x52, 0xcd, - 0xbd, 0x29, 0xf4, 0x15, 0xfb, 0xa5, 0xfd, 0xa8, 0x9a, 0x49, 0x31, 0xd7, - 0xff, 0xa2, 0x7c, 0xf4, 0x0a, 0x7f, 0x9b, 0xf8, 0xeb, 0x31, 0xa3, 0xf7, - 0xfa, 0x5d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x8d, 0x6f, 0x29, 0xbe, 0x8e, - 0xb3, 0x18, 0x7a, 0x3e, 0x33, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x54, 0xb7, - 0x3b, 0x4d, 0x10, 0xd5, 0x98, 0xc3, 0xd5, 0x73, 0x3b, 0xf7, 0x1a, 0xee, - 0xd3, 0x44, 0x7d, 0x7f, 0xfc, 0x2f, 0xe9, 0x42, 0x9f, 0x23, 0xda, 0x8f, - 0xce, 0xbc, 0xf2, 0x63, 0x11, 0x09, 0xf4, 0xce, 0xff, 0xcf, 0x3c, 0x75, - 0x38, 0x90, 0xb3, 0xaf, 0xf4, 0x73, 0x07, 0xd9, 0xd3, 0xaf, 0x2f, 0x18, - 0xdb, 0x3e, 0xcf, 0xa7, 0x94, 0xc2, 0x36, 0xe2, 0x14, 0x57, 0xff, 0xfd, - 0x20, 0x71, 0x47, 0xd6, 0x06, 0x37, 0xd7, 0xdf, 0x28, 0x8a, 0x1d, 0x7f, - 0x03, 0x7d, 0xe5, 0x9e, 0x3a, 0xff, 0xf2, 0xac, 0xa3, 0x2a, 0xf3, 0x85, - 0x55, 0xf3, 0xe7, 0x76, 0xce, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x58, 0xf7, - 0x3e, 0x8e, 0xbf, 0xa7, 0xfb, 0xce, 0x67, 0x0e, 0xa9, 0x1e, 0x2b, 0x8a, - 0xdf, 0xf0, 0xba, 0x9d, 0x48, 0x19, 0xce, 0xbf, 0xff, 0x7f, 0x29, 0xd5, - 0x68, 0x56, 0xe7, 0x6f, 0x3e, 0x7c, 0xee, 0xd9, 0xd7, 0xe4, 0xf7, 0x93, - 0xc7, 0x5f, 0x73, 0x99, 0xb6, 0x75, 0x61, 0xe5, 0x39, 0x35, 0xfb, 0x39, - 0x99, 0x31, 0xd6, 0x62, 0x15, 0x64, 0x4e, 0xd9, 0x22, 0xfc, 0x62, 0x47, - 0x89, 0x88, 0x7a, 0x6f, 0xa8, 0x5a, 0xfd, 0x20, 0xbc, 0xab, 0x2d, 0x43, - 0xaf, 0xe5, 0x40, 0xe7, 0x5f, 0xc7, 0x5f, 0xe7, 0xff, 0x4f, 0xef, 0x39, - 0xd7, 0x2d, 0xa7, 0x50, 0x9e, 0x47, 0x8c, 0xaf, 0xfd, 0x8c, 0xf3, 0x05, - 0xf7, 0x96, 0x8e, 0xbf, 0x66, 0xba, 0x8c, 0x9d, 0x7d, 0xfa, 0xd3, 0x87, - 0x5f, 0xff, 0xf4, 0x70, 0x70, 0x39, 0xde, 0xa3, 0x7a, 0x9e, 0xd3, 0xee, - 0x75, 0x22, 0x21, 0xba, 0x45, 0x7f, 0x47, 0x3f, 0xdb, 0x07, 0x8e, 0xbf, - 0xe8, 0x1f, 0x2a, 0x9f, 0xc0, 0x83, 0xaf, 0xff, 0x47, 0x61, 0x6d, 0xea, - 0x7b, 0x31, 0x67, 0x5f, 0x7f, 0xfa, 0x7d, 0x3a, 0xf3, 0xbb, 0x4d, 0x16, - 0x85, 0xff, 0x9d, 0x9d, 0xa6, 0xbf, 0x27, 0xc6, 0x4e, 0xbf, 0xbf, 0x81, - 0x8f, 0x68, 0xea, 0x6a, 0x25, 0xb8, 0x4f, 0xfa, 0x1d, 0xff, 0xff, 0xf2, - 0x73, 0xae, 0x29, 0x1e, 0x4e, 0xc6, 0xbb, 0x9a, 0xe6, 0x37, 0x3c, 0x75, - 0x49, 0x50, 0xb0, 0x4c, 0x5a, 0x74, 0x88, 0xfc, 0x85, 0xdf, 0x4c, 0x6e, - 0xc5, 0x9d, 0x7f, 0xf3, 0xef, 0xb3, 0xaa, 0xe9, 0xe1, 0x85, 0x9d, 0x5c, - 0x3d, 0xd7, 0x15, 0xbf, 0xff, 0x27, 0xb4, 0xfb, 0xeb, 0x59, 0xd4, 0xd0, - 0x27, 0x3a, 0xff, 0xf8, 0x13, 0xf1, 0x3d, 0x38, 0x39, 0x2d, 0x2b, 0xa1, - 0xd5, 0xd4, 0x55, 0x8a, 0xb5, 0xff, 0xf0, 0x39, 0xc8, 0x1c, 0x51, 0x3b, - 0xdc, 0xfa, 0x75, 0x95, 0x27, 0x57, 0x0f, 0x90, 0x0a, 0x17, 0xf9, 0x60, - 0x1f, 0x68, 0x1c, 0x3a, 0xb8, 0x7a, 0xbb, 0x64, 0x57, 0xf6, 0xc9, 0xbb, - 0x9f, 0xb9, 0xd7, 0xe1, 0x6b, 0xe9, 0x0e, 0xbf, 0xff, 0xb8, 0x31, 0x1b, - 0xfc, 0xd7, 0x86, 0x03, 0xd8, 0xf1, 0xd7, 0x27, 0x4e, 0xbe, 0x90, 0xbf, - 0xd3, 0xaf, 0xf0, 0x5f, 0xfe, 0x71, 0xff, 0x3a, 0xfd, 0x9c, 0x6a, 0xbb, - 0x27, 0x52, 0x1e, 0xf8, 0x9a, 0x54, 0x26, 0x6d, 0x84, 0xaa, 0xeb, 0x6e, - 0x2a, 0x08, 0x40, 0xde, 0x75, 0x74, 0x3a, 0xff, 0xdf, 0x7c, 0xa2, 0x29, - 0x18, 0x30, 0x75, 0xfb, 0xef, 0x86, 0x3f, 0x3a, 0xb7, 0x44, 0x2f, 0x07, - 0x76, 0x1f, 0xdf, 0xa3, 0xd9, 0xd8, 0x3a, 0xff, 0xff, 0xf7, 0x50, 0x38, - 0x93, 0xf6, 0x23, 0xe6, 0x6f, 0x2d, 0x27, 0x9c, 0x70, 0xeb, 0xff, 0x66, - 0xf2, 0xd4, 0xdc, 0x7f, 0x68, 0xeb, 0xff, 0xec, 0xf6, 0xb2, 0x6e, 0xc6, - 0xcc, 0xef, 0x60, 0xeb, 0xfe, 0x18, 0x89, 0xb3, 0x62, 0x70, 0xea, 0x9d, - 0x36, 0x36, 0x92, 0xfe, 0xec, 0x28, 0x1e, 0x50, 0xbf, 0x7c, 0x9a, 0x49, - 0x31, 0xd5, 0x0a, 0x83, 0x72, 0x39, 0x64, 0x4c, 0xbf, 0xfb, 0xa9, 0xf3, - 0x07, 0x13, 0x8f, 0xb0, 0xeb, 0xff, 0xfd, 0xd8, 0x1c, 0xff, 0x58, 0x1e, - 0xc4, 0xeb, 0x00, 0x84, 0xea, 0x51, 0x14, 0x9e, 0x44, 0xbf, 0xff, 0xa2, - 0x6c, 0x0f, 0x63, 0x67, 0x73, 0xc3, 0x10, 0xb3, 0xaf, 0xed, 0xf5, 0xf6, - 0x70, 0x09, 0xd7, 0xfd, 0x0d, 0xea, 0x4c, 0xef, 0x39, 0xd4, 0xb4, 0x61, - 0xba, 0xd7, 0xe6, 0x37, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xc8, - 0x01, 0x97, 0x23, 0x02, 0x75, 0xff, 0xff, 0x77, 0x24, 0xde, 0xa7, 0x63, - 0x39, 0x2f, 0x0c, 0x2f, 0x47, 0x56, 0x91, 0x35, 0xe3, 0x6a, 0x84, 0x78, - 0xe4, 0x33, 0xaf, 0xf7, 0x1b, 0x36, 0x27, 0x40, 0x75, 0xfe, 0x5c, 0x34, - 0x5f, 0x7f, 0x1d, 0x7f, 0x72, 0x3d, 0x3e, 0x32, 0x75, 0xff, 0xff, 0xf2, - 0x03, 0x9d, 0xc9, 0xa6, 0x7e, 0x4d, 0xee, 0x83, 0xfd, 0x62, 0x6c, 0x0c, - 0x1d, 0x7e, 0xf7, 0x5c, 0x54, 0x3a, 0xff, 0x84, 0x13, 0x87, 0xb8, 0x30, - 0x75, 0xb0, 0x28, 0xe0, 0xc8, 0x41, 0x34, 0x9e, 0xff, 0xf7, 0x3f, 0x6f, - 0xe3, 0x9e, 0xd3, 0xb8, 0x9d, 0x50, 0x9f, 0xae, 0x19, 0xa1, 0x90, 0xc6, - 0x1c, 0x03, 0x9b, 0xfd, 0x9d, 0x99, 0x3a, 0x8b, 0x3a, 0xff, 0x4b, 0x39, - 0xa1, 0x89, 0xce, 0xbd, 0xb7, 0x93, 0x9d, 0x7b, 0x3a, 0xe7, 0x5f, 0xa6, - 0x08, 0x00, 0x27, 0x50, 0x4f, 0x09, 0xc6, 0xaf, 0xf6, 0x33, 0x8d, 0x6e, - 0x32, 0x75, 0xff, 0x6e, 0xbc, 0xc1, 0xf6, 0xde, 0x1d, 0x79, 0x49, 0x00, - 0xeb, 0xf7, 0x63, 0x93, 0xac, 0xeb, 0xfc, 0x07, 0x1e, 0xe3, 0xcc, 0x75, - 0xb7, 0x98, 0xf6, 0x59, 0x28, 0xa4, 0x45, 0x0b, 0xbb, 0x56, 0x26, 0x5e, - 0xe6, 0x63, 0x0d, 0xba, 0xc5, 0x49, 0x1b, 0x99, 0x21, 0x93, 0xb0, 0xea, - 0x35, 0x0b, 0xbd, 0x07, 0x5c, 0xfe, 0x3a, 0xb8, 0x6a, 0xba, 0x2b, 0x7f, - 0xdc, 0xce, 0xe4, 0xff, 0x13, 0x47, 0x56, 0x1e, 0xd8, 0x08, 0x6f, 0xe4, - 0x10, 0x4b, 0x34, 0x75, 0xff, 0xb3, 0xd1, 0xbf, 0xef, 0xde, 0xa1, 0xd6, - 0x59, 0xd7, 0xf2, 0x08, 0x25, 0x9a, 0xf8, 0x79, 0xdb, 0x0f, 0xa9, 0x44, - 0x60, 0x79, 0xe6, 0xcc, 0x2b, 0x6d, 0xa0, 0xb2, 0xa8, 0x8a, 0x1d, 0xe7, - 0x21, 0x91, 0xf0, 0x61, 0x5b, 0x92, 0x8e, 0x14, 0x85, 0xd3, 0x61, 0x98, - 0x90, 0xdb, 0x98, 0x95, 0x71, 0xb3, 0x76, 0x57, 0x13, 0xc3, 0x67, 0xf8, - 0x73, 0x8c, 0x64, 0x3a, 0x94, 0x37, 0xe9, 0x52, 0xbb, 0x70, 0xd5, 0xfb, - 0x0e, 0x1b, 0xfb, 0x69, 0x02, 0x31, 0x31, 0xd7, 0xa1, 0xc4, 0xeb, 0xec, - 0xeb, 0xf8, 0xeb, 0x2a, 0x30, 0xfa, 0x3a, 0x5e, 0x23, 0x37, 0xff, 0xff, - 0xba, 0xe3, 0xed, 0x42, 0x4b, 0x36, 0x87, 0xd1, 0xd8, 0x50, 0x11, 0xb4, - 0x75, 0xf6, 0x6b, 0xf4, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x6b, 0x5f, - 0xe5, 0xa2, 0xde, 0x6c, 0xe9, 0xd7, 0xf6, 0x6d, 0x69, 0xc5, 0xa7, 0x5e, - 0xe4, 0x2c, 0xeb, 0xfb, 0xb9, 0xa8, 0x9f, 0x68, 0xeb, 0xfe, 0x93, 0x19, - 0xc6, 0xbb, 0xb4, 0xd1, 0x41, 0xd6, 0x1f, 0xab, 0x98, 0x5f, 0x64, 0xd1, - 0xe3, 0xaf, 0xfa, 0x25, 0x1c, 0x9e, 0x39, 0x39, 0xd7, 0xff, 0xef, 0x69, - 0x27, 0x7d, 0x38, 0xbf, 0xbb, 0x13, 0x1d, 0x66, 0x15, 0x4a, 0xb0, 0xe0, - 0xde, 0x4f, 0x58, 0x42, 0x86, 0x73, 0x19, 0x70, 0xb9, 0x70, 0x90, 0xe9, - 0x00, 0x90, 0xfd, 0x39, 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, - 0xd3, 0x45, 0x17, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0xaa, 0xa1, - 0xbf, 0xf2, 0x93, 0xe3, 0x5f, 0x52, 0x38, 0x65, 0xca, 0xf0, 0xed, 0x69, - 0x47, 0xfc, 0xe5, 0x0e, 0xa1, 0x53, 0xe5, 0x7b, 0xf7, 0x1a, 0xee, 0xd3, - 0x44, 0x43, 0x7b, 0xb8, 0x13, 0xaf, 0xb3, 0x62, 0x70, 0xeb, 0x31, 0x87, - 0xe1, 0xb9, 0x9a, 0xb8, 0xdd, 0xb6, 0xce, 0xbe, 0x8e, 0xc2, 0xce, 0xbe, - 0x6b, 0xbb, 0x4d, 0x11, 0xb5, 0x34, 0xf3, 0x78, 0x41, 0x66, 0x02, 0x88, - 0x2c, 0x60, 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x37, 0x7e, 0xe3, - 0x5d, 0xda, 0x68, 0xa8, 0x2f, 0x66, 0xec, 0x9d, 0x66, 0x30, 0xf4, 0x3a, - 0x67, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x9a, 0xfd, 0xc6, 0xbb, - 0xb4, 0xd1, 0x58, 0x5f, 0x91, 0x90, 0x83, 0x87, 0x5c, 0xbd, 0x1d, 0x7f, - 0x26, 0xdb, 0xc2, 0x6d, 0x9d, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x88, - 0xfe, 0xa0, 0xfb, 0xe4, 0x61, 0x7b, 0x22, 0x73, 0xaf, 0xf6, 0x6f, 0x27, - 0x92, 0x09, 0xd7, 0x3f, 0x8e, 0xb3, 0x18, 0x9b, 0x13, 0x4c, 0xd6, 0x50, - 0xf0, 0x85, 0x12, 0x1f, 0x0d, 0xed, 0x98, 0xdf, 0xfe, 0x61, 0x6f, 0x26, - 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x6f, 0xbf, 0xf9, 0x6f, 0x26, 0x33, 0x8d, - 0x77, 0x69, 0xa2, 0x7e, 0xbf, 0x9f, 0xb9, 0xe8, 0x09, 0xd7, 0x0b, 0x4e, - 0xbe, 0xd4, 0xcb, 0xd1, 0xd7, 0xf9, 0xbd, 0x4f, 0x66, 0x2c, 0xeb, 0xb6, - 0x34, 0xf1, 0x81, 0x54, 0x22, 0x39, 0x05, 0x74, 0x47, 0xe3, 0x1b, 0xfc, - 0xab, 0x95, 0x81, 0xc9, 0xe3, 0x73, 0xaf, 0xca, 0xca, 0xa3, 0x6f, 0x37, - 0x3a, 0xfe, 0x56, 0x1e, 0x7e, 0xa2, 0xb9, 0xd7, 0xe5, 0x6d, 0x45, 0x31, - 0x5c, 0xeb, 0xb6, 0x34, 0xf1, 0x80, 0xdb, 0xa7, 0x52, 0xb2, 0x98, 0x6a, - 0xb0, 0x7c, 0xa8, 0x34, 0x55, 0xc6, 0xbe, 0x31, 0x01, 0x2d, 0xf2, 0xb7, - 0xc7, 0xc3, 0xaf, 0x95, 0x53, 0xaf, 0x47, 0x5f, 0xff, 0xca, 0xd8, 0xbf, - 0xa0, 0x5a, 0x8b, 0x08, 0x1f, 0x92, 0x3a, 0xff, 0x9f, 0xa9, 0xb1, 0x86, - 0x59, 0x64, 0xab, 0xfd, 0xd7, 0xf7, 0x9d, 0xd9, 0x3a, 0x95, 0x48, 0xf4, - 0x55, 0xe4, 0xea, 0xd5, 0x75, 0x57, 0x1f, 0x5f, 0xff, 0xe5, 0x65, 0x51, - 0xae, 0x42, 0x7b, 0xb8, 0x14, 0xd6, 0x0f, 0xe7, 0x5f, 0xca, 0xf1, 0xc7, - 0x79, 0x1d, 0x7e, 0xea, 0x3f, 0xea, 0xb8, 0xea, 0x56, 0x11, 0x86, 0xab, - 0x34, 0x78, 0xba, 0xce, 0x75, 0xf9, 0x54, 0xad, 0x3f, 0x52, 0x0e, 0xbf, - 0xfe, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdf, 0x47, 0x5e, 0x4d, 0xf0, 0xeb, - 0xf7, 0x12, 0x77, 0x59, 0x57, 0x32, 0xc9, 0x55, 0x86, 0xfd, 0x92, 0x7b, - 0x00, 0xa6, 0x0d, 0x0d, 0x42, 0x39, 0x7f, 0x49, 0xd3, 0xdd, 0xf9, 0xdc, - 0x63, 0x68, 0xeb, 0xff, 0xc8, 0x38, 0xb8, 0xd6, 0xb2, 0x5b, 0x78, 0x75, - 0xff, 0xee, 0xc4, 0x9f, 0x02, 0x9b, 0x35, 0xfb, 0x4e, 0xbf, 0xdc, 0x00, - 0x83, 0xc0, 0xf1, 0xd7, 0xbb, 0x02, 0x75, 0xa1, 0x0f, 0x37, 0xc6, 0x75, - 0x08, 0xbe, 0xec, 0x26, 0x2f, 0x0a, 0x41, 0xd7, 0xe8, 0xfa, 0xbe, 0xa1, - 0xd5, 0xc3, 0xc1, 0x11, 0x9b, 0xfa, 0x5a, 0xf6, 0x0a, 0x87, 0x5e, 0x65, - 0xd9, 0x3a, 0xff, 0xf7, 0xb8, 0xf3, 0x87, 0xb1, 0xaf, 0x03, 0xa7, 0x5d, - 0x8b, 0xe9, 0xf4, 0x68, 0x76, 0xfc, 0xed, 0xea, 0x70, 0xeb, 0xff, 0xff, - 0xc2, 0xea, 0x27, 0x22, 0x5f, 0x3a, 0x8b, 0x0c, 0x7c, 0xdb, 0x07, 0x53, - 0x87, 0x5f, 0x3c, 0x93, 0x73, 0xaf, 0xfd, 0xd4, 0xf6, 0x73, 0x80, 0x9f, - 0x61, 0xd7, 0xfc, 0x9e, 0xce, 0x70, 0x13, 0xec, 0x3a, 0xf6, 0x80, 0x3f, - 0x0f, 0xf3, 0xa8, 0x34, 0x14, 0xe8, 0xb8, 0x5b, 0xd2, 0x61, 0x7d, 0xd4, - 0x27, 0x6d, 0x07, 0x5f, 0xff, 0x46, 0xf2, 0x71, 0xff, 0xe7, 0xe9, 0xc4, - 0x50, 0xea, 0xdb, 0x3e, 0x2d, 0xa0, 0xfb, 0xe9, 0xd6, 0x92, 0x3a, 0xfa, - 0x3f, 0xfa, 0xb3, 0xaf, 0x84, 0x0f, 0x23, 0xa9, 0xa7, 0x89, 0xa2, 0x4b, - 0xfd, 0xd8, 0x5b, 0x1f, 0xff, 0x07, 0x54, 0x22, 0xf7, 0x19, 0x90, 0x8a, - 0xfe, 0x99, 0x3b, 0xec, 0x69, 0xd5, 0xc3, 0xda, 0x72, 0xdb, 0xfe, 0xdc, - 0x3f, 0x61, 0x5f, 0xa0, 0xd1, 0xd7, 0xff, 0xe0, 0xf6, 0x38, 0x9f, 0xc7, - 0xd8, 0x98, 0x61, 0x67, 0x5f, 0xe5, 0x20, 0x7d, 0xa7, 0xe9, 0xd4, 0x88, - 0x88, 0x75, 0x6a, 0x84, 0x74, 0x0c, 0x31, 0xef, 0xf7, 0x62, 0x7e, 0x46, - 0x04, 0xeb, 0xff, 0xe1, 0xcd, 0x8d, 0x7e, 0x4e, 0xfe, 0x7d, 0xff, 0x3a, - 0xa1, 0x10, 0x8e, 0x65, 0x7f, 0x85, 0xe7, 0xde, 0x51, 0xb4, 0x75, 0xfe, - 0xd7, 0x5f, 0xef, 0x62, 0x47, 0x54, 0xe7, 0xd5, 0xb9, 0xb5, 0xec, 0xc9, - 0x8e, 0xbf, 0xe8, 0x90, 0xbf, 0xa4, 0x9b, 0x0e, 0xbd, 0xf6, 0x3f, 0x3a, - 0xba, 0x7a, 0xda, 0x38, 0xb2, 0xb9, 0xd7, 0xbd, 0x2c, 0x3a, 0xed, 0x61, - 0xd7, 0xff, 0x6a, 0x38, 0xdf, 0x0e, 0x4e, 0xe2, 0x75, 0x62, 0x29, 0xd0, - 0x89, 0xc4, 0xff, 0x1b, 0xf0, 0xad, 0xfc, 0x09, 0x81, 0xe8, 0xe9, 0xd7, - 0xff, 0x06, 0x3c, 0xfa, 0xce, 0xf5, 0x16, 0x75, 0xfe, 0x9c, 0x30, 0xfc, - 0xfc, 0x07, 0x5e, 0xf2, 0x4c, 0x75, 0x42, 0x24, 0xb1, 0x0b, 0x46, 0x97, - 0xe8, 0x57, 0x46, 0x5a, 0x75, 0x43, 0x2b, 0xa2, 0x73, 0x09, 0x13, 0x86, - 0x30, 0x7c, 0x68, 0xdc, 0x85, 0x25, 0x1b, 0xcd, 0x0b, 0x1e, 0x46, 0x7e, - 0xb8, 0xc2, 0x7b, 0x0a, 0xa7, 0x84, 0x5f, 0xe4, 0x83, 0x18, 0xc6, 0x92, - 0x3d, 0x0c, 0x0f, 0xa5, 0xd7, 0xff, 0xfc, 0xab, 0xd5, 0x51, 0x8a, 0xd7, - 0x8a, 0xa5, 0x5b, 0x62, 0xba, 0xae, 0x07, 0xcf, 0x9d, 0xdb, 0x3a, 0xf4, - 0xdf, 0x56, 0x75, 0xff, 0x67, 0xb5, 0x9e, 0xee, 0x7e, 0x75, 0x39, 0xeb, - 0x88, 0xfd, 0xce, 0x27, 0x57, 0x0d, 0xa2, 0xc8, 0x2f, 0xa3, 0xd8, 0xb3, - 0xaf, 0xde, 0x81, 0x4f, 0xce, 0xbf, 0xb1, 0x97, 0xfd, 0x78, 0x75, 0x7c, - 0x3f, 0x3c, 0x20, 0x12, 0x6b, 0xf7, 0x27, 0x8f, 0x68, 0xeb, 0xe7, 0xe3, - 0xc8, 0xeb, 0x73, 0x0f, 0x20, 0x4a, 0x2f, 0x32, 0xcb, 0x27, 0x5f, 0x4e, - 0x29, 0x05, 0x30, 0x5f, 0xdf, 0xf2, 0xbf, 0x5c, 0x64, 0x18, 0x9c, 0xeb, - 0xb7, 0x91, 0xd7, 0xf9, 0x48, 0xf6, 0xba, 0xe0, 0x3a, 0xfc, 0x93, 0xe6, - 0xfe, 0x3a, 0xe4, 0x69, 0xd5, 0x08, 0x87, 0x50, 0x5d, 0x66, 0x7e, 0x28, - 0xbf, 0x28, 0xfa, 0xd9, 0x23, 0xab, 0x73, 0xe7, 0xf1, 0xed, 0x2a, 0xca, - 0xfa, 0xa2, 0x31, 0xe0, 0xc2, 0x51, 0x1d, 0xfa, 0x8a, 0xe6, 0x00, 0x8c, - 0xa6, 0xff, 0xed, 0x8c, 0xe6, 0x85, 0x23, 0x99, 0x39, 0xd7, 0xff, 0xff, - 0xfe, 0x57, 0xf9, 0xdc, 0xde, 0x5d, 0x5f, 0xc6, 0xf4, 0x1e, 0xf6, 0x0f, - 0x73, 0xd0, 0x1f, 0x9f, 0x3b, 0xb6, 0x75, 0xff, 0x07, 0x00, 0xa9, 0x4e, - 0xba, 0xce, 0xbf, 0x42, 0xc7, 0x26, 0x3b, 0x0d, 0xdd, 0xed, 0x98, 0x13, - 0xaf, 0xf2, 0x9d, 0x48, 0x10, 0x41, 0xd5, 0xd3, 0xce, 0x71, 0xda, 0x0a, - 0x29, 0x35, 0x08, 0x3b, 0xfa, 0x25, 0xd8, 0xd8, 0x87, 0x5f, 0x9f, 0x80, - 0x7d, 0x1d, 0x74, 0xbc, 0x75, 0xf4, 0xd1, 0xe7, 0x3a, 0xf8, 0x1f, 0xe0, - 0xb4, 0xdb, 0x80, 0x5a, 0xd2, 0x3a, 0xa7, 0x3c, 0x8e, 0x9c, 0x5f, 0xfd, - 0x1d, 0xfa, 0x1f, 0x26, 0x4d, 0x0b, 0x3a, 0xfa, 0x3c, 0x05, 0x9d, 0x46, - 0x88, 0x3a, 0xfe, 0x79, 0xff, 0x71, 0x09, 0x2b, 0x06, 0xdb, 0x4d, 0x3d, - 0x2d, 0xb1, 0x7a, 0x5a, 0x27, 0xbc, 0xe7, 0x7f, 0xfe, 0x5e, 0x9e, 0x5d, - 0x4c, 0xf6, 0xb9, 0x81, 0xc3, 0xaf, 0xfa, 0x3c, 0x39, 0xb0, 0x73, 0x47, - 0x54, 0x22, 0xb7, 0x08, 0xf4, 0xa7, 0x7f, 0x3f, 0x61, 0x5c, 0x12, 0x3a, - 0xa4, 0xab, 0x89, 0xa5, 0xbc, 0x85, 0x2a, 0xc8, 0xfd, 0x1c, 0x86, 0xc2, - 0xeb, 0xfa, 0x43, 0x9b, 0xfb, 0x0e, 0xbf, 0xff, 0x7d, 0xff, 0xf8, 0xdf, - 0x27, 0x0b, 0xbb, 0x5c, 0x27, 0x54, 0x22, 0x17, 0x85, 0x97, 0xf9, 0xc7, - 0xd2, 0xce, 0x61, 0xd7, 0xf0, 0xa7, 0xfa, 0xea, 0x1d, 0x77, 0x02, 0x75, - 0xcc, 0xb2, 0x75, 0x48, 0xd7, 0x32, 0x2d, 0x7a, 0x13, 0x61, 0x4c, 0x1a, - 0x2a, 0x74, 0x54, 0xe9, 0xf2, 0xef, 0xf4, 0x75, 0xfc, 0x9d, 0x45, 0x14, - 0x83, 0xae, 0xd7, 0xd0, 0x9e, 0x27, 0x85, 0xe9, 0x11, 0x2d, 0xf5, 0x9a, - 0xf3, 0x2c, 0xb2, 0x55, 0x14, 0xc1, 0x7f, 0x7c, 0x8c, 0xa4, 0xc5, 0x53, - 0x4d, 0xe2, 0x0d, 0x5f, 0xb3, 0x91, 0xb3, 0x0e, 0xa8, 0x64, 0x0d, 0x4e, - 0x8b, 0x91, 0xc4, 0xa4, 0xb0, 0xae, 0x43, 0xad, 0x64, 0x5d, 0x8d, 0xbc, - 0x5f, 0xf4, 0x41, 0x7d, 0xc9, 0x03, 0x0e, 0xbf, 0xc3, 0xbf, 0xbe, 0xf5, - 0xff, 0x3a, 0xf0, 0xa6, 0x8e, 0xbe, 0x0b, 0x8f, 0xe7, 0x5f, 0xfd, 0x03, - 0xf8, 0xc6, 0xf3, 0x40, 0xfe, 0x75, 0x62, 0x2d, 0x50, 0xdb, 0xf1, 0xad, - 0x10, 0xd9, 0x0e, 0xbf, 0xe7, 0x51, 0xbd, 0x40, 0xbc, 0x8e, 0xbe, 0x9e, - 0x77, 0xdc, 0xeb, 0xbf, 0xd2, 0x1f, 0x58, 0x87, 0xfd, 0x38, 0xbf, 0x46, - 0x73, 0xa8, 0x75, 0xff, 0xe6, 0x7f, 0xee, 0x64, 0xe9, 0x9b, 0x23, 0x73, - 0xaf, 0xff, 0x7f, 0x0b, 0xe7, 0x22, 0x7f, 0x3b, 0xa8, 0x75, 0xfe, 0x96, - 0x77, 0x17, 0x0d, 0x3a, 0xf6, 0x2d, 0x5c, 0xeb, 0xfd, 0x9a, 0x1c, 0xf7, - 0x50, 0xea, 0x09, 0xe7, 0x08, 0xf5, 0x62, 0x73, 0x33, 0x1e, 0x74, 0x97, - 0xf4, 0xdf, 0x25, 0xec, 0x7f, 0xbf, 0xbd, 0x93, 0x0c, 0x2c, 0xf1, 0x01, - 0x5f, 0x9c, 0x43, 0xd8, 0x34, 0x40, 0x4c, 0x1b, 0x9b, 0xff, 0x93, 0x7d, - 0x07, 0x06, 0x04, 0x10, 0x75, 0xff, 0xc0, 0x6a, 0x9c, 0xcd, 0xf5, 0xfb, - 0xf8, 0xeb, 0xf4, 0x49, 0xf7, 0x64, 0xea, 0xc4, 0x58, 0x22, 0x0f, 0x11, - 0xed, 0x39, 0xd7, 0xef, 0x99, 0x32, 0x2c, 0xeb, 0xff, 0xc0, 0x8f, 0x9b, - 0x5e, 0x4d, 0x77, 0x77, 0x64, 0xea, 0x9c, 0xfe, 0x74, 0x53, 0x7f, 0xec, - 0x0f, 0x5d, 0x88, 0xec, 0x6e, 0x75, 0x2a, 0x11, 0xd7, 0xc8, 0x45, 0x2c, - 0x8e, 0xff, 0xc8, 0x2a, 0x70, 0x51, 0xa0, 0x13, 0xaf, 0xff, 0xcf, 0xbe, - 0xfa, 0x81, 0xf7, 0xd9, 0xba, 0x9e, 0xd1, 0xd5, 0x08, 0xce, 0xc3, 0x90, - 0x1e, 0x5f, 0x2e, 0x31, 0x67, 0x5f, 0xfb, 0x17, 0x0d, 0x4f, 0x70, 0x0b, - 0x3a, 0xf2, 0x6f, 0xa3, 0xad, 0x12, 0x3d, 0x9f, 0xcf, 0x6f, 0xf7, 0x26, - 0xd2, 0x0f, 0x90, 0xeb, 0xfd, 0xd4, 0xdf, 0xfe, 0x38, 0x4e, 0xbe, 0xdf, - 0xfe, 0x41, 0x57, 0x32, 0xc9, 0x55, 0x06, 0xed, 0x92, 0x3b, 0x85, 0x0a, - 0x60, 0xd0, 0xde, 0x7e, 0x4b, 0xe2, 0x2d, 0x65, 0x09, 0x0a, 0x56, 0xd9, - 0x0e, 0xb1, 0x0d, 0x6c, 0x94, 0x80, 0x90, 0x94, 0xe4, 0x3c, 0xfb, 0x1f, - 0x3b, 0x97, 0x0b, 0xcf, 0x8a, 0x01, 0x0e, 0x7b, 0xd3, 0xba, 0xce, 0xbd, - 0xe4, 0x64, 0xf1, 0x84, 0x5f, 0x78, 0x0f, 0xf4, 0xd1, 0x03, 0xee, 0x6a, - 0x69, 0xd1, 0x0c, 0x04, 0x5b, 0xca, 0xe9, 0xf9, 0xd7, 0x40, 0x0e, 0xbf, - 0x00, 0x7f, 0xfb, 0x23, 0xaf, 0xff, 0x87, 0x35, 0xf3, 0xef, 0x63, 0xf5, - 0xbc, 0xbe, 0x61, 0xbf, 0xd0, 0xad, 0x01, 0x19, 0x3b, 0x17, 0xaf, 0xfd, - 0xd0, 0x4f, 0x1f, 0x23, 0xd0, 0x13, 0xaf, 0x3f, 0x27, 0x3a, 0xe6, 0x59, - 0x3a, 0xff, 0x71, 0x33, 0x67, 0xd9, 0x30, 0xd3, 0x68, 0xc8, 0xe5, 0xff, - 0x91, 0x4f, 0x9a, 0x07, 0xeb, 0x89, 0x1d, 0x7f, 0xb5, 0x9e, 0x75, 0xe0, - 0x9d, 0x41, 0x4c, 0xd7, 0x8e, 0x9d, 0x4f, 0xf2, 0x15, 0xff, 0xc3, 0x8a, - 0x75, 0xe5, 0xf5, 0xf7, 0x83, 0xaa, 0x11, 0x07, 0x87, 0xd7, 0xff, 0x2d, - 0x6f, 0x2c, 0xe3, 0x5d, 0xda, 0x68, 0x86, 0x2f, 0xff, 0xff, 0x3e, 0xb0, - 0x71, 0xbd, 0x8d, 0xe5, 0xb7, 0x9d, 0x6a, 0x60, 0xba, 0x87, 0x56, 0x23, - 0x18, 0x09, 0xf4, 0x8a, 0xb9, 0xbb, 0x1e, 0xe8, 0xc3, 0x9e, 0xff, 0x2f, - 0xaf, 0x38, 0xc4, 0x8a, 0xbb, 0x40, 0x3a, 0xfe, 0x97, 0x5d, 0xc6, 0x0e, - 0xb4, 0x34, 0xf0, 0x37, 0x16, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x41, 0x57, - 0xbb, 0x0b, 0x3a, 0xff, 0xd1, 0x3b, 0xfb, 0x99, 0x2d, 0xbc, 0x3a, 0xb1, - 0x11, 0xc8, 0x66, 0x23, 0x77, 0xee, 0xc2, 0xc1, 0xb9, 0xd7, 0xde, 0xd4, - 0x7e, 0x55, 0xe7, 0xe4, 0xe5, 0x5f, 0x00, 0x5d, 0x42, 0xaf, 0xf2, 0x4f, - 0x9e, 0xd4, 0x7e, 0x55, 0x15, 0x7f, 0x63, 0x63, 0xb0, 0xb2, 0xae, 0x65, - 0x92, 0xaf, 0xe1, 0x81, 0x9d, 0x38, 0x55, 0x62, 0x61, 0x4d, 0x22, 0x58, - 0xe7, 0x48, 0x7f, 0x33, 0x10, 0xa6, 0x4a, 0xfe, 0x8c, 0x5c, 0x9c, 0x29, - 0x83, 0xf4, 0xa9, 0x27, 0xf5, 0x31, 0x6f, 0x63, 0xa6, 0xa8, 0x56, 0xb5, - 0xd7, 0x27, 0x95, 0x61, 0x7f, 0x60, 0xe9, 0x07, 0x0e, 0xbd, 0xd0, 0x2c, - 0xea, 0xe9, 0xe2, 0xed, 0x14, 0xdf, 0xe7, 0x1c, 0xd7, 0x23, 0x47, 0x5f, - 0xc1, 0xc1, 0x7f, 0x68, 0xeb, 0x44, 0x8f, 0x6f, 0x46, 0x17, 0xee, 0x6f, - 0x2c, 0xf1, 0xd7, 0xff, 0xfd, 0xd4, 0xe6, 0x05, 0xd7, 0x83, 0xe1, 0x86, - 0x73, 0xda, 0x3a, 0xd0, 0x75, 0xfb, 0xb1, 0xb0, 0x30, 0xd3, 0xf2, 0xfd, - 0x8e, 0xb8, 0x8d, 0xbf, 0x42, 0x6a, 0xff, 0x6f, 0x2d, 0xb8, 0x6e, 0x2c, - 0xeb, 0xff, 0xff, 0x73, 0x91, 0xbc, 0xb7, 0xd2, 0x71, 0xbd, 0xcf, 0xbc, - 0x48, 0x09, 0xd5, 0x08, 0xa5, 0xc3, 0x6b, 0xff, 0xf3, 0x54, 0x7d, 0x67, - 0x24, 0x9d, 0x71, 0xde, 0x47, 0x5f, 0xf9, 0xb1, 0xed, 0x67, 0x93, 0x76, - 0x4e, 0xb3, 0xe2, 0x25, 0x14, 0x55, 0xa8, 0x4e, 0xab, 0xb0, 0xcd, 0x18, - 0x5a, 0xde, 0xf3, 0xfe, 0x75, 0xff, 0xf9, 0xde, 0x4f, 0xdf, 0x99, 0x38, - 0x3c, 0x07, 0xfa, 0x68, 0xbe, 0xef, 0x7f, 0x01, 0x3a, 0xff, 0xda, 0x41, - 0xde, 0x5c, 0x04, 0x68, 0xea, 0x99, 0x17, 0xfc, 0x65, 0xf0, 0xe5, 0xfe, - 0x89, 0xfb, 0x93, 0x42, 0xb9, 0xd6, 0x69, 0xd7, 0xff, 0xfb, 0xf4, 0xe2, - 0x9d, 0x85, 0xcd, 0x24, 0x1e, 0xc7, 0x20, 0xeb, 0x7b, 0x0f, 0xc7, 0x42, - 0x17, 0xde, 0x1c, 0x91, 0xd5, 0x07, 0x8e, 0x84, 0xf7, 0xfe, 0x14, 0x97, - 0xbb, 0x9c, 0x4d, 0x1d, 0x7f, 0x44, 0x87, 0x32, 0x73, 0xaf, 0xf3, 0x86, - 0x3f, 0x86, 0x74, 0x75, 0x74, 0xf7, 0x9c, 0xae, 0xfe, 0xdb, 0x56, 0xbf, - 0x3e, 0x77, 0x6c, 0xf1, 0x00, 0xdf, 0xef, 0x7f, 0xf4, 0x65, 0xdc, 0x3c, - 0x40, 0x37, 0x9f, 0x92, 0x3c, 0x40, 0x35, 0x87, 0xd4, 0x04, 0x2b, 0x9e, - 0x47, 0x88, 0x06, 0xf9, 0xc7, 0x79, 0x1e, 0x20, 0x1b, 0xfc, 0x8d, 0xee, - 0x7f, 0xfc, 0x1e, 0x20, 0x1b, 0xc8, 0x21, 0x3c, 0x40, 0x34, 0x14, 0x5b, - 0xac, 0x8b, 0xa5, 0xdb, 0x10, 0x2c, 0xa1, 0xe2, 0x01, 0xbd, 0xc8, 0xf1, - 0xe2, 0x01, 0xa3, 0xc4, 0x03, 0x7b, 0x6d, 0x3f, 0x3c, 0x40, 0x37, 0x42, - 0xcf, 0x10, 0x0d, 0x04, 0xf9, 0x70, 0x5d, 0x0b, 0x2f, 0x91, 0x61, 0x83, - 0xc4, 0x03, 0x7b, 0xce, 0xd3, 0xc4, 0x03, 0x7f, 0xe1, 0x79, 0x31, 0xd4, - 0x6b, 0xf0, 0xf1, 0x00, 0xdf, 0xfc, 0xfe, 0x04, 0xe8, 0x3e, 0xeb, 0xc8, - 0xf1, 0x00, 0xdc, 0xe1, 0x3c, 0x40, 0x37, 0xf8, 0x5d, 0x9d, 0x6a, 0x3f, - 0x3c, 0x40, 0x37, 0xe4, 0x51, 0xc7, 0xf3, 0xc4, 0x03, 0x72, 0x68, 0xf1, - 0x00, 0xd7, 0x0f, 0x5b, 0xc6, 0x97, 0xff, 0xba, 0x9e, 0xf6, 0x6b, 0xe7, - 0x12, 0x16, 0x78, 0x80, 0x6f, 0xde, 0x18, 0xde, 0x46, 0x88, 0x06, 0xef, - 0xe0, 0xf1, 0x00, 0xb0, 0x6d, 0x2f, 0xc9, 0x0b, 0x70, 0x9e, 0x20, 0x1b, - 0xe0, 0x38, 0xb4, 0xf1, 0x00, 0xde, 0x8e, 0x34, 0xf1, 0x00, 0xdf, 0xfb, - 0x37, 0xd0, 0x63, 0x07, 0xfd, 0x1e, 0x20, 0x1b, 0xf0, 0x1e, 0x52, 0x83, - 0xc4, 0x03, 0x7e, 0x76, 0xf6, 0x37, 0x3c, 0x40, 0x35, 0x88, 0xb2, 0xea, - 0x58, 0x0c, 0xee, 0xe7, 0xe7, 0x88, 0x06, 0xa4, 0xac, 0x94, 0x24, 0x59, - 0x09, 0x66, 0x91, 0x24, 0x22, 0xfa, 0x69, 0xf9, 0x96, 0x8b, 0x7d, 0x0d, - 0xa0, 0x17, 0xdf, 0xb3, 0xda, 0x7d, 0xcf, 0x10, 0x0d, 0xfe, 0x0c, 0x36, - 0x6e, 0x47, 0x8f, 0x10, 0x08, 0x4d, 0xa5, 0xee, 0x43, 0x27, 0x88, 0x06, - 0x9a, 0x7f, 0x3c, 0x50, 0xbf, 0xc0, 0x79, 0x4a, 0x3e, 0xac, 0xf1, 0x00, - 0xdf, 0x20, 0xcb, 0x47, 0x88, 0x06, 0xfe, 0x79, 0xa5, 0x9b, 0xc8, 0xf1, - 0x00, 0xd6, 0x23, 0x2f, 0xa4, 0x5f, 0xa0, 0x80, 0xb6, 0xff, 0xbb, 0x1a, - 0x63, 0x40, 0xe7, 0xe7, 0x88, 0x06, 0xc8, 0x78, 0x80, 0x6e, 0x79, 0xc2, - 0x7c, 0x9d, 0x48, 0xbb, 0x9f, 0x9e, 0x20, 0x1b, 0xf3, 0xfb, 0x49, 0xb9, - 0xe2, 0x01, 0xbf, 0x90, 0x41, 0x2c, 0xd1, 0xe2, 0x01, 0xa8, 0x44, 0x80, - 0x92, 0x78, 0xd2, 0xa1, 0x94, 0xb0, 0x18, 0x5a, 0xe4, 0x36, 0x10, 0xfe, - 0x61, 0xee, 0x42, 0x37, 0xa5, 0xae, 0x5b, 0xf9, 0x40, 0xa5, 0x6a, 0x5b, - 0xaf, 0xa5, 0x09, 0xed, 0xc2, 0x87, 0xec, 0x2f, 0xaf, 0x79, 0x19, 0x3c, - 0x61, 0x37, 0x9d, 0xda, 0x68, 0x80, 0x58, 0x4c, 0x57, 0x78, 0x76, 0x5f, - 0x28, 0xad, 0x02, 0xb3, 0xae, 0xd9, 0x39, 0xd7, 0xed, 0x83, 0x01, 0xe9, - 0xd5, 0x07, 0x82, 0x83, 0x37, 0xff, 0x48, 0x71, 0xbd, 0x4f, 0xff, 0x04, - 0xc7, 0x5d, 0xfc, 0x15, 0x65, 0x0a, 0xbd, 0xd8, 0x9c, 0xeb, 0x99, 0x64, - 0xaa, 0x43, 0xdb, 0x57, 0x16, 0x98, 0x45, 0x91, 0xcb, 0xcb, 0x4d, 0x14, - 0xc1, 0xe0, 0x5e, 0x40, 0x78, 0xeb, 0xff, 0xde, 0xd6, 0x28, 0x9c, 0xfb, - 0xff, 0xf1, 0xb9, 0xd5, 0x3b, 0x3a, 0x62, 0x44, 0x01, 0x84, 0xd3, 0x69, - 0x71, 0xc8, 0x9d, 0xc6, 0xa7, 0x20, 0xfe, 0x1c, 0x3e, 0x2d, 0xfa, 0x37, - 0x7f, 0xf8, 0x7d, 0xb7, 0x93, 0x49, 0xf9, 0x38, 0x60, 0xeb, 0xfb, 0xdf, - 0x76, 0x6c, 0x8d, 0x1d, 0x7f, 0xb3, 0x7f, 0x79, 0xe5, 0xa3, 0xaf, 0x0e, - 0xf2, 0x3c, 0x60, 0x15, 0x88, 0xdc, 0x44, 0xde, 0x19, 0xb9, 0x9d, 0xfa, - 0x69, 0x47, 0x27, 0x3a, 0xfa, 0x14, 0x85, 0x9d, 0x5c, 0x3c, 0xa5, 0x94, - 0xdf, 0xfa, 0x5a, 0xf8, 0x38, 0xb8, 0xe2, 0x87, 0x5f, 0xd2, 0x8e, 0x7f, - 0xf5, 0x67, 0x5f, 0xfd, 0xb0, 0x73, 0x5e, 0xc1, 0x96, 0x68, 0xeb, 0xe5, - 0xc0, 0x3c, 0x75, 0x61, 0xf2, 0x3a, 0x1d, 0xdd, 0x7c, 0x45, 0xa0, 0xc2, - 0x52, 0xff, 0xa1, 0xb0, 0xb4, 0x5f, 0xe8, 0x75, 0x70, 0xfa, 0x36, 0x8c, - 0x6f, 0xef, 0xac, 0xf1, 0x33, 0xa5, 0x5f, 0xfd, 0xf8, 0xa6, 0x6f, 0xe9, - 0xa4, 0xfc, 0x3a, 0xfa, 0x6e, 0xbc, 0xc7, 0x5f, 0x35, 0xf9, 0x39, 0xd7, - 0xec, 0x9a, 0x51, 0xb9, 0xd7, 0xba, 0x93, 0x1d, 0x78, 0x62, 0x45, 0x5f, - 0xf8, 0x7f, 0x4d, 0xad, 0xa0, 0x4a, 0x15, 0xce, 0xac, 0x3e, 0x17, 0x1a, - 0xad, 0xd3, 0x4f, 0xe2, 0x2f, 0x48, 0xc4, 0x8b, 0xc5, 0x1b, 0x4f, 0xb5, - 0x0a, 0xdf, 0x30, 0x89, 0x23, 0x5c, 0xe9, 0x2b, 0xc6, 0xfd, 0x7f, 0x6f, - 0xae, 0x72, 0x3c, 0x75, 0xfd, 0x2d, 0x29, 0xc7, 0x69, 0xd7, 0x87, 0xda, - 0x3a, 0xfd, 0xa0, 0x08, 0x1a, 0x75, 0x41, 0xf8, 0x21, 0x70, 0x06, 0xef, - 0xfe, 0xeb, 0x31, 0xcd, 0x63, 0x2f, 0xc5, 0x0e, 0xbf, 0x60, 0x43, 0x8b, - 0x3a, 0xff, 0xf7, 0xb7, 0x6a, 0x77, 0x6e, 0x3d, 0xdf, 0xba, 0x3a, 0xe5, - 0x4e, 0x8e, 0xbe, 0x14, 0xde, 0x47, 0x5f, 0xf2, 0x6f, 0xdc, 0x0f, 0x1d, - 0xa7, 0x54, 0x1e, 0xcf, 0x08, 0x6f, 0xfb, 0xb1, 0xc8, 0x6a, 0x0b, 0x4e, - 0xbe, 0xf2, 0x8f, 0xae, 0x1e, 0xbe, 0xd1, 0x0d, 0x49, 0x3c, 0x3e, 0x23, - 0x2c, 0x98, 0x0a, 0x0c, 0xc3, 0x2a, 0xfd, 0xb4, 0x05, 0xe0, 0x4e, 0xbf, - 0xf7, 0x73, 0x69, 0xc5, 0x4c, 0xdf, 0xc7, 0x5f, 0xf6, 0x37, 0xa8, 0x1e, - 0x81, 0x43, 0xaf, 0x7b, 0x1a, 0x75, 0x2c, 0xf5, 0x34, 0x73, 0x7a, 0x4b, - 0xfc, 0xea, 0x51, 0x1a, 0x9f, 0xc2, 0x57, 0xc4, 0x57, 0xfc, 0xa3, 0xfc, - 0x85, 0x8a, 0x28, 0x75, 0xff, 0x9f, 0x4b, 0x84, 0xe7, 0x11, 0x93, 0xad, - 0xa5, 0x0f, 0xdf, 0xa7, 0x57, 0xfd, 0x9e, 0xf2, 0x29, 0xec, 0x69, 0xd7, - 0xf8, 0x31, 0xbe, 0xb3, 0x7f, 0x1d, 0x7f, 0xd1, 0xe4, 0x6a, 0x06, 0x3c, - 0x75, 0xb4, 0x14, 0x51, 0x61, 0xc7, 0x0d, 0x2b, 0x74, 0xc0, 0x3d, 0x0c, - 0xbb, 0xfe, 0xf2, 0x4f, 0x1b, 0xff, 0xc8, 0x3a, 0xf6, 0xbd, 0x87, 0x5d, - 0x9a, 0xf8, 0x7a, 0xbf, 0x4e, 0xaf, 0xfe, 0xcf, 0x26, 0xf2, 0x18, 0x55, - 0x2a, 0xfd, 0xb3, 0xaf, 0xd9, 0xef, 0xdf, 0xc7, 0x54, 0x8f, 0xdf, 0x6d, - 0x42, 0xff, 0xfd, 0x1d, 0x7c, 0x18, 0xe2, 0x81, 0x03, 0xf2, 0x47, 0x54, - 0x93, 0x20, 0xf4, 0x2a, 0x36, 0x89, 0x6a, 0x17, 0x35, 0x71, 0x45, 0x21, - 0xfc, 0xf1, 0xd7, 0x02, 0x39, 0xfb, 0xee, 0xa3, 0xc8, 0xeb, 0xfd, 0x83, - 0x2c, 0xd7, 0xd5, 0x9d, 0x7e, 0x5e, 0xbf, 0x77, 0x3a, 0xbc, 0x7b, 0x5f, - 0x4c, 0xef, 0xfb, 0x98, 0x3f, 0x3b, 0x9b, 0xb2, 0x75, 0xff, 0x48, 0x41, - 0xff, 0xc6, 0xaf, 0xf3, 0xaa, 0x74, 0xc5, 0xa4, 0xf5, 0x84, 0x9b, 0x9d, - 0xdf, 0xf0, 0xc6, 0x6f, 0xec, 0xe4, 0x1d, 0x50, 0x7e, 0xae, 0x7f, 0x7e, - 0x7d, 0x81, 0x0c, 0x1d, 0x76, 0xb4, 0x75, 0xe6, 0x59, 0x64, 0xeb, 0xbf, - 0x72, 0x98, 0x2f, 0xeb, 0x87, 0xb7, 0xa3, 0x5b, 0xff, 0x66, 0x85, 0xd4, - 0x98, 0x52, 0x63, 0xaf, 0xef, 0xe2, 0x5d, 0xfb, 0xa3, 0xaf, 0x3f, 0xf8, - 0x55, 0x49, 0x32, 0xe5, 0xc2, 0x0f, 0xa4, 0x5f, 0x9f, 0x6d, 0x98, 0x5f, - 0x40, 0x50, 0x27, 0x5f, 0x83, 0xc4, 0x04, 0xe7, 0x5f, 0xe6, 0x70, 0x73, - 0x62, 0x70, 0xeb, 0xf8, 0x73, 0x7f, 0xfe, 0xc8, 0xea, 0x99, 0x11, 0x62, - 0x51, 0xe3, 0x3b, 0x9d, 0x67, 0x5f, 0xec, 0xd9, 0x8c, 0x32, 0xcb, 0x25, - 0x5f, 0xa6, 0x8c, 0xee, 0x8e, 0xa1, 0x3d, 0xff, 0xa7, 0x17, 0xf9, 0x53, - 0x00, 0x6f, 0x53, 0x87, 0x5e, 0x5b, 0xf8, 0xea, 0x99, 0x1d, 0x1d, 0x74, - 0x01, 0x1e, 0xc3, 0x6b, 0xf8, 0x76, 0x3a, 0xd1, 0x67, 0x5f, 0xb2, 0x69, - 0x44, 0x8e, 0xbf, 0xa7, 0x0c, 0x60, 0x84, 0xea, 0x85, 0x5a, 0xf2, 0x54, - 0x48, 0x55, 0xbc, 0x63, 0x1a, 0x40, 0xf1, 0x6f, 0xd2, 0x7b, 0xcf, 0xfa, - 0x1d, 0x7f, 0xc1, 0x10, 0x6b, 0x27, 0xc9, 0xce, 0xbd, 0x1c, 0x13, 0xaf, - 0xf6, 0x04, 0x5f, 0x48, 0x13, 0xad, 0xd3, 0xaf, 0x01, 0xe7, 0x13, 0xc0, - 0xd1, 0x85, 0x93, 0x88, 0x8d, 0xf2, 0xd5, 0x2d, 0x30, 0x97, 0x1b, 0x54, - 0xc3, 0x1a, 0xff, 0xf6, 0x05, 0xd7, 0x9b, 0xcb, 0x3f, 0xc0, 0x9d, 0x77, - 0x5c, 0xeb, 0xa6, 0xd1, 0xd7, 0xec, 0xd8, 0x82, 0x1c, 0x35, 0x9f, 0x45, - 0x6f, 0xdd, 0xcd, 0xfd, 0x07, 0x5f, 0xb6, 0x9e, 0x7f, 0xb2, 0x3a, 0xbe, - 0x26, 0x10, 0xc3, 0xae, 0x1f, 0x80, 0x9e, 0xf8, 0x39, 0xd7, 0x3a, 0xff, - 0xe8, 0xc1, 0x97, 0x70, 0x46, 0x19, 0x3a, 0xb8, 0x8a, 0x01, 0x40, 0xf1, - 0x05, 0xfe, 0xe6, 0xbb, 0x82, 0x9a, 0x3a, 0x90, 0xf8, 0x1c, 0xbe, 0xff, - 0xb0, 0x38, 0x30, 0x20, 0x83, 0xae, 0x86, 0x4e, 0xa9, 0xdd, 0x99, 0xf4, - 0xa5, 0xe8, 0x86, 0x5c, 0xae, 0x3e, 0x29, 0x08, 0x06, 0xca, 0xac, 0xdc, - 0xe5, 0x21, 0xb7, 0x31, 0x8f, 0x29, 0xf0, 0xcb, 0x8e, 0x03, 0xb3, 0x80, - 0x0e, 0xa9, 0xfc, 0x27, 0x86, 0x7b, 0x17, 0x51, 0xf2, 0xfa, 0x70, 0x94, - 0x11, 0xbc, 0xec, 0x94, 0x83, 0xf4, 0x83, 0x68, 0xd2, 0xff, 0xb3, 0x83, - 0x1e, 0x96, 0x74, 0xeb, 0xf8, 0x7f, 0xc0, 0xbc, 0x8e, 0xbf, 0xff, 0x03, - 0xda, 0x6f, 0x50, 0x63, 0x7d, 0x22, 0xe0, 0xeb, 0xfc, 0xd1, 0xc9, 0x49, - 0xf4, 0x75, 0xfc, 0xec, 0xe7, 0xff, 0x7c, 0x75, 0xf9, 0xe5, 0xf0, 0x28, - 0x75, 0xe9, 0x47, 0xe7, 0x5f, 0xbe, 0xcd, 0x28, 0x57, 0x2a, 0xa1, 0x38, - 0x8c, 0x36, 0x50, 0xb1, 0x15, 0x38, 0x63, 0xd3, 0x0f, 0x14, 0x7d, 0x1c, - 0xb3, 0x4e, 0xbf, 0xf9, 0x41, 0x03, 0xfd, 0xcd, 0x24, 0x09, 0xd7, 0xb6, - 0xd0, 0x27, 0x57, 0x0f, 0x85, 0x68, 0x77, 0xff, 0x6f, 0xe0, 0x2f, 0xb0, - 0x82, 0xe1, 0x3a, 0xf9, 0x4e, 0x3b, 0x27, 0x5b, 0xe9, 0xa2, 0x05, 0xb7, - 0x8d, 0x40, 0xa5, 0x78, 0xde, 0x32, 0x3f, 0x58, 0x88, 0x14, 0x5f, 0xbf, - 0xf2, 0x6d, 0xf5, 0x3e, 0xb1, 0xff, 0xf0, 0x55, 0xff, 0x0f, 0xb4, 0x0d, - 0xfc, 0x8c, 0x9d, 0x7f, 0x80, 0xfa, 0xcc, 0x15, 0x0e, 0xa8, 0x3e, 0xbe, - 0x9d, 0x5f, 0xfe, 0x45, 0x3e, 0x0b, 0xa9, 0xf3, 0x5f, 0xff, 0x07, 0x5f, - 0xe7, 0xee, 0xfa, 0x81, 0xf1, 0xd5, 0xa4, 0x41, 0x79, 0x42, 0xff, 0x9b, - 0xd4, 0x9a, 0x50, 0x32, 0x3a, 0xfa, 0x5d, 0xc9, 0xce, 0xbf, 0xe8, 0xdd, - 0x6f, 0xec, 0xdf, 0xc7, 0x56, 0xe7, 0xb6, 0x24, 0x57, 0xfd, 0x0d, 0xf0, - 0x3b, 0xc8, 0x64, 0xeb, 0xb8, 0xe7, 0x5f, 0xff, 0xd1, 0xcf, 0xf3, 0x62, - 0x6b, 0x58, 0x2d, 0x71, 0xfc, 0xea, 0xe1, 0xf8, 0x74, 0x56, 0xff, 0xcf, - 0xbe, 0xb3, 0xc8, 0xb7, 0x91, 0xd6, 0xf1, 0xd5, 0xf9, 0xe6, 0xfd, 0x3d, - 0xbf, 0xff, 0xf8, 0x1a, 0xeb, 0xcb, 0x52, 0x4f, 0x7d, 0xe4, 0x76, 0x3d, - 0xa7, 0xdc, 0xeb, 0xf4, 0x60, 0xfb, 0x6c, 0xeb, 0xf9, 0x37, 0xff, 0x8e, - 0x13, 0xac, 0xb3, 0xa9, 0x67, 0xcd, 0xd2, 0x81, 0x2e, 0xbd, 0x20, 0x04, - 0xeb, 0x9f, 0x7f, 0x87, 0x94, 0xe5, 0xd5, 0xc4, 0xd4, 0xf5, 0x19, 0x25, - 0xff, 0xfd, 0x83, 0x3e, 0xb5, 0x1f, 0xe7, 0x53, 0x8e, 0xcf, 0x8e, 0xa0, - 0xae, 0x48, 0x6f, 0x0a, 0x39, 0x88, 0xf9, 0x09, 0x35, 0x91, 0x76, 0x15, - 0x3f, 0xb7, 0xfa, 0x37, 0x86, 0x4a, 0xaa, 0x17, 0x76, 0x92, 0x75, 0x02, - 0xff, 0xff, 0xb9, 0x3e, 0x24, 0xce, 0xf2, 0xd4, 0x2c, 0x3d, 0x81, 0x69, - 0xd7, 0xc1, 0xe8, 0x27, 0x3a, 0xff, 0x05, 0xe5, 0x93, 0x80, 0x4e, 0xb4, - 0xf0, 0x7a, 0xb8, 0x47, 0x72, 0xa7, 0x0e, 0xac, 0x3c, 0x07, 0x27, 0xbf, - 0xbd, 0xb6, 0x0e, 0xe3, 0x4e, 0xbf, 0xdc, 0x8f, 0x27, 0xf1, 0x23, 0xaf, - 0x4e, 0x32, 0x3a, 0x95, 0x0c, 0x91, 0x68, 0x71, 0x42, 0x25, 0xc3, 0x13, - 0xb3, 0xbf, 0x6e, 0x58, 0x30, 0xfa, 0xd1, 0x07, 0x8c, 0x00, 0x65, 0x7f, - 0xe5, 0x47, 0xd8, 0x5b, 0x7a, 0xfb, 0xfe, 0x75, 0xfe, 0x94, 0xd8, 0x2f, - 0xdc, 0x3a, 0xff, 0x6c, 0x79, 0x83, 0x03, 0x39, 0xd7, 0xd0, 0x05, 0x4a, - 0x1d, 0x7b, 0xde, 0x83, 0xaf, 0xf2, 0x72, 0x27, 0x7e, 0x34, 0xeb, 0x7b, - 0x87, 0xe2, 0xe4, 0x9e, 0x1b, 0xbf, 0xfd, 0xc6, 0x8e, 0x6c, 0x1c, 0x8e, - 0x46, 0x8e, 0xbf, 0xcf, 0x37, 0x71, 0x79, 0xa3, 0xab, 0x0f, 0xeb, 0x62, - 0x45, 0xfc, 0x8a, 0x7b, 0x31, 0x67, 0x5f, 0xb0, 0x29, 0xcd, 0x1d, 0x7b, - 0xde, 0xdc, 0xeb, 0xff, 0xb7, 0x6a, 0x77, 0xe6, 0xd6, 0x75, 0x16, 0x75, - 0x7e, 0x7c, 0xde, 0x1d, 0xb8, 0x1c, 0x3a, 0xb4, 0x6e, 0x76, 0xc8, 0xed, - 0x13, 0xa3, 0xa5, 0x98, 0x62, 0xd4, 0x2a, 0xbb, 0xc8, 0x53, 0x24, 0x2b, - 0xba, 0x47, 0xe8, 0xc5, 0x6f, 0xfc, 0x29, 0xf7, 0x7c, 0xd9, 0xbc, 0x7d, - 0x3a, 0xff, 0xf2, 0x67, 0x03, 0x0c, 0xe7, 0x63, 0x7d, 0x1d, 0x7d, 0xf6, - 0x39, 0xf9, 0xd7, 0x3f, 0x0e, 0xbf, 0xbc, 0x93, 0xae, 0x1a, 0x75, 0x04, - 0xf0, 0xba, 0x2b, 0x76, 0x6d, 0x1d, 0x7d, 0xff, 0xd1, 0x91, 0xd7, 0x7e, - 0xe2, 0x6f, 0x3c, 0x31, 0x50, 0x88, 0xa0, 0x2f, 0x5d, 0xbc, 0xc7, 0x5f, - 0xbe, 0xfb, 0xf5, 0xe1, 0xd4, 0xb3, 0xc2, 0xfc, 0x62, 0xf3, 0x63, 0x47, - 0x5f, 0xf4, 0x9f, 0x9e, 0x18, 0x5e, 0x8e, 0xbf, 0xd0, 0x18, 0xe0, 0x23, - 0xf3, 0xae, 0x5e, 0xa6, 0x3e, 0x95, 0x9b, 0xdf, 0xfa, 0x1c, 0x73, 0xde, - 0x46, 0x7c, 0x75, 0x42, 0x62, 0x58, 0x46, 0x90, 0x84, 0x01, 0x7d, 0x2a, - 0x97, 0xaf, 0xa1, 0x1a, 0x52, 0xbb, 0x31, 0x65, 0xa8, 0x93, 0x24, 0xea, - 0x1e, 0x1e, 0x8d, 0xda, 0xfe, 0x80, 0x6e, 0x9b, 0xed, 0x1d, 0x7e, 0xc6, - 0x73, 0x7f, 0x1d, 0x6e, 0x7c, 0x3d, 0x94, 0x31, 0xbf, 0xfd, 0xac, 0x10, - 0x37, 0xb8, 0xb9, 0x9d, 0xa7, 0x5f, 0xe1, 0x53, 0xb0, 0xb5, 0x89, 0xd7, - 0xf2, 0xba, 0x46, 0xd0, 0x3c, 0x75, 0xfa, 0x26, 0xcc, 0x69, 0xd5, 0x88, - 0x8a, 0x43, 0x2e, 0x99, 0x5f, 0xfb, 0xb9, 0x32, 0x4c, 0x0d, 0xa0, 0x68, - 0xeb, 0xc9, 0xc5, 0x0e, 0xa4, 0x3d, 0xf1, 0x43, 0xbf, 0x46, 0xd7, 0x62, - 0x63, 0xaa, 0x47, 0x95, 0xa2, 0x0b, 0xff, 0x81, 0x32, 0x76, 0x37, 0x94, - 0x4d, 0x07, 0x5f, 0x82, 0xe3, 0x1d, 0x3a, 0xfe, 0x94, 0x6f, 0xec, 0xe9, - 0xd7, 0xff, 0xbd, 0xa4, 0xfe, 0x25, 0xac, 0xcd, 0xfc, 0x75, 0x4c, 0x7e, - 0xfa, 0x2d, 0xb2, 0x75, 0x17, 0xec, 0xc2, 0x72, 0xff, 0xfd, 0xc0, 0x73, - 0x90, 0x38, 0xa2, 0x77, 0xb9, 0xf4, 0xeb, 0xf8, 0x5d, 0x03, 0x02, 0x75, - 0xf4, 0xf1, 0xb5, 0x07, 0x5e, 0xd8, 0x0e, 0x9d, 0x7f, 0xf2, 0x2d, 0x35, - 0xd8, 0x4e, 0x01, 0x5c, 0xea, 0x84, 0x43, 0xa1, 0x23, 0x8f, 0x5f, 0xc3, - 0xa4, 0xd9, 0x01, 0x3a, 0xf0, 0xa2, 0x87, 0x5f, 0xde, 0x4e, 0x27, 0x80, - 0x75, 0xa1, 0x67, 0x8f, 0xf4, 0x6e, 0xfe, 0x07, 0xde, 0xe6, 0xfa, 0x3a, - 0xff, 0xff, 0xfd, 0xc8, 0xf0, 0xbb, 0x53, 0x53, 0x27, 0x1b, 0x1a, 0xf4, - 0x6f, 0x1f, 0x73, 0x47, 0x5f, 0xee, 0xe6, 0xf1, 0xc4, 0x59, 0xd7, 0xff, - 0xff, 0xfe, 0xd6, 0xb3, 0xdd, 0x75, 0xeb, 0x9c, 0x4d, 0xfc, 0xee, 0xa6, - 0x64, 0xc0, 0xf4, 0x33, 0xbc, 0x1d, 0x50, 0x9a, 0x88, 0x61, 0x06, 0xe6, - 0x57, 0xdf, 0xbe, 0xfa, 0x3a, 0xe6, 0x59, 0x3a, 0xb4, 0x6e, 0xd9, 0x23, - 0xbf, 0x27, 0x5f, 0x3a, 0x53, 0x06, 0x8a, 0xff, 0x81, 0xe8, 0x16, 0xab, - 0x7f, 0xac, 0xeb, 0xdd, 0x8f, 0xce, 0xa4, 0x3d, 0xa7, 0x3e, 0xbf, 0xdd, - 0x8f, 0x01, 0x60, 0xf1, 0xd5, 0x0b, 0xfd, 0x92, 0x29, 0x0c, 0x34, 0xf7, - 0x86, 0xba, 0xb9, 0x14, 0xd1, 0x82, 0x70, 0xb9, 0x6a, 0xdd, 0x85, 0x83, - 0x96, 0xfe, 0xe8, 0xa9, 0x29, 0x18, 0xe0, 0x75, 0x09, 0x1f, 0x42, 0x43, - 0x68, 0x82, 0xfd, 0x34, 0x4d, 0xd8, 0x3a, 0xef, 0xb0, 0x75, 0xe6, 0x59, - 0x64, 0xab, 0xe9, 0x7b, 0x1a, 0x53, 0x05, 0xfd, 0xfb, 0x02, 0x9f, 0xe8, - 0xf7, 0x7f, 0x57, 0x0f, 0x94, 0x4c, 0x6a, 0x11, 0xc9, 0xc2, 0x87, 0x84, - 0xdd, 0xde, 0xd1, 0xd7, 0xfd, 0xf3, 0xdd, 0x8f, 0x6b, 0xa8, 0x75, 0xb4, - 0x75, 0xfe, 0xf6, 0xf2, 0xec, 0x0c, 0xe7, 0x5f, 0xfb, 0x37, 0x92, 0x60, - 0x8e, 0x04, 0xeb, 0xf4, 0xeb, 0x06, 0xfe, 0x3a, 0xa1, 0x1f, 0x3b, 0x8b, - 0x70, 0xe8, 0x44, 0x34, 0x69, 0xe3, 0xbb, 0xfe, 0x18, 0x67, 0x48, 0x3b, - 0xc8, 0xeb, 0xa1, 0xa7, 0x50, 0x9e, 0x6e, 0xc3, 0x8b, 0xe9, 0xfe, 0xc2, - 0xb9, 0xd7, 0xfb, 0x41, 0x18, 0x67, 0x04, 0xea, 0xe1, 0xec, 0x78, 0x9e, - 0xa1, 0x34, 0x04, 0x85, 0x1b, 0xbd, 0xdf, 0xc3, 0xbe, 0xa6, 0xcf, 0x1d, - 0x7f, 0x27, 0x85, 0xff, 0xd1, 0xd7, 0xff, 0xbd, 0x36, 0x73, 0x1d, 0x71, - 0xd4, 0x09, 0xd7, 0xf0, 0x17, 0x9d, 0xdd, 0xce, 0xa5, 0x11, 0x42, 0x25, - 0x9a, 0x48, 0xbf, 0xfc, 0x81, 0x17, 0xdc, 0x73, 0xd8, 0x9f, 0x9d, 0x7f, - 0x47, 0xbb, 0x2d, 0x00, 0xeb, 0xf7, 0x5f, 0x99, 0xc3, 0xae, 0x03, 0x9d, - 0x4d, 0x37, 0x62, 0x4d, 0x7f, 0x72, 0x12, 0x4f, 0xa3, 0xad, 0x13, 0x9e, - 0x58, 0x90, 0x5f, 0xa7, 0x57, 0x4c, 0xdc, 0xeb, 0xf2, 0x6a, 0x27, 0x59, - 0xec, 0xfd, 0xbf, 0x43, 0xf3, 0xf0, 0x1e, 0xcf, 0xdb, 0x9e, 0x47, 0xb3, - 0xf6, 0xf8, 0x12, 0xcd, 0x1e, 0xcf, 0xda, 0x09, 0xe8, 0x09, 0x15, 0xfa, - 0x33, 0x58, 0x27, 0xb3, 0xf6, 0x8f, 0x67, 0xed, 0xcf, 0xe3, 0xd9, 0xfa, - 0xb2, 0xde, 0xd2, 0x13, 0xf9, 0x02, 0x45, 0xf6, 0x6d, 0xa7, 0xe7, 0xb3, - 0xf6, 0x8f, 0x67, 0xed, 0xdf, 0xc1, 0xec, 0xfd, 0xbf, 0xec, 0xfd, 0xf9, - 0x9b, 0x30, 0x27, 0xb3, 0xf6, 0xfe, 0xce, 0xa6, 0x81, 0x39, 0xec, 0xfd, - 0xaf, 0xd1, 0x46, 0x24, 0x7a, 0x46, 0xbe, 0xe4, 0xf1, 0xe3, 0xd9, 0xfb, - 0x47, 0xb3, 0xf7, 0x0d, 0x7d, 0xcc, 0xb2, 0x7b, 0x3f, 0x6a, 0x4a, 0xc3, - 0x82, 0x69, 0x90, 0x84, 0xde, 0x13, 0x5c, 0x27, 0x59, 0x8e, 0xa1, 0x75, - 0xe5, 0xf6, 0x49, 0xaf, 0x4a, 0x14, 0x2d, 0x9f, 0xa6, 0x11, 0x21, 0x7f, - 0xb5, 0x92, 0x94, 0x7b, 0x73, 0xab, 0x0f, 0xc3, 0x47, 0xb7, 0xfe, 0xc6, - 0x87, 0x38, 0xcb, 0xf6, 0x63, 0xae, 0x94, 0xe5, 0x5f, 0x4c, 0xef, 0xc3, - 0xaa, 0x74, 0x4c, 0x6e, 0x42, 0x27, 0xfb, 0x42, 0xf5, 0xc5, 0xd1, 0x27, - 0x9c, 0xd1, 0xbf, 0xcb, 0xd0, 0xe7, 0xb3, 0xf3, 0xaf, 0xf9, 0xb1, 0xf8, - 0x40, 0xfc, 0x91, 0xd7, 0xfe, 0x77, 0x9f, 0x16, 0xe3, 0xbc, 0x8e, 0xbf, - 0x32, 0x2e, 0xa6, 0xb0, 0xfd, 0xa6, 0x39, 0xa8, 0x47, 0x43, 0xc2, 0xa2, - 0xfc, 0x3e, 0xee, 0x4e, 0x75, 0xc1, 0x64, 0xea, 0x83, 0x7d, 0x84, 0xf7, - 0xff, 0xe9, 0x72, 0x36, 0x3c, 0xd0, 0x1e, 0xc2, 0xde, 0x63, 0xaf, 0xf6, - 0xd3, 0xe9, 0x35, 0x36, 0x1d, 0x5b, 0xa2, 0x33, 0x8a, 0xf5, 0x0c, 0xc1, - 0x99, 0x4a, 0x6c, 0xc3, 0x34, 0x86, 0x7a, 0xb9, 0x87, 0x11, 0xfb, 0x0b, - 0x37, 0x9d, 0x39, 0x18, 0xc5, 0x74, 0xc8, 0x08, 0x55, 0xdf, 0xff, 0xf2, - 0x75, 0xfb, 0x12, 0x63, 0x3f, 0x89, 0x68, 0x3d, 0x8e, 0x1d, 0x7f, 0xe5, - 0x23, 0x71, 0x8e, 0xf4, 0x0d, 0x3a, 0xff, 0xf0, 0x79, 0x18, 0x39, 0x24, - 0xee, 0x6c, 0x3a, 0xfe, 0x17, 0x53, 0xaf, 0x23, 0xaf, 0x32, 0xcb, 0x25, - 0x5e, 0xfb, 0x1f, 0x94, 0xc1, 0x7f, 0x7f, 0xcf, 0x2f, 0xbc, 0xcd, 0x8f, - 0xc3, 0xaf, 0xff, 0xdd, 0xc9, 0x7d, 0x11, 0xc9, 0xe6, 0x94, 0x72, 0x73, - 0xa8, 0x51, 0x27, 0xe3, 0xbb, 0xfe, 0xf3, 0x8e, 0x6b, 0x91, 0xa3, 0xaf, - 0xa5, 0x1f, 0xee, 0x75, 0xfd, 0xfc, 0x0e, 0x6f, 0xe3, 0xae, 0x7f, 0xfe, - 0x1e, 0x87, 0xd2, 0x3a, 0x74, 0x5c, 0x0c, 0x21, 0xaf, 0x6c, 0x8e, 0x1d, - 0x52, 0x56, 0x2c, 0x16, 0x6c, 0x3f, 0x5a, 0x47, 0xe9, 0x63, 0x0c, 0x1f, - 0x43, 0x6b, 0x61, 0x35, 0xc9, 0x39, 0xd7, 0xf8, 0x5a, 0x14, 0xd9, 0x01, - 0x3a, 0x82, 0x79, 0x20, 0x16, 0xb7, 0xe7, 0x5f, 0xf6, 0x42, 0xbf, 0xce, - 0xbe, 0x70, 0xeb, 0xfd, 0xfe, 0xda, 0x2c, 0x21, 0xc3, 0xaf, 0xfb, 0xdd, - 0xcd, 0x7c, 0xf2, 0x4e, 0x75, 0x41, 0xf8, 0xa1, 0xb5, 0xff, 0x0a, 0x01, - 0x53, 0xad, 0xb8, 0xf1, 0xd5, 0x24, 0xc6, 0xe6, 0x11, 0xec, 0x2b, 0x04, - 0x82, 0xf3, 0x2c, 0xb2, 0x58, 0x84, 0x17, 0xcd, 0x77, 0x69, 0x62, 0x10, - 0x30, 0x6b, 0x6f, 0x9f, 0x98, 0xc9, 0xd5, 0xc3, 0xe0, 0xd8, 0x7f, 0x79, - 0x96, 0x59, 0x2c, 0x41, 0xea, 0x2c, 0x41, 0xe6, 0x0d, 0x6d, 0xe6, 0x59, - 0x64, 0xeb, 0xda, 0x85, 0x0a, 0x60, 0xbf, 0xb2, 0xf1, 0x18, 0xad, 0x51, - 0xf2, 0x45, 0xff, 0xdd, 0x89, 0x27, 0xb3, 0xad, 0x85, 0x9d, 0x50, 0x7e, - 0xfb, 0x0d, 0x6f, 0xff, 0x67, 0x53, 0x9d, 0x7c, 0xd2, 0x3c, 0xe7, 0x5f, - 0x47, 0xa1, 0x67, 0x52, 0xcf, 0x9f, 0xc8, 0xf7, 0xf3, 0x2e, 0x10, 0x3f, - 0xd3, 0xaf, 0x85, 0x21, 0x43, 0xaf, 0x7d, 0x8f, 0xce, 0xa9, 0xcd, 0xf2, - 0xc8, 0x2f, 0xcd, 0x8e, 0xc2, 0xca, 0xbf, 0x0b, 0x88, 0xe1, 0x57, 0x63, - 0x4a, 0xb9, 0x96, 0x4a, 0xac, 0x3f, 0x6d, 0x13, 0x78, 0x8d, 0x91, 0x5b, - 0xfc, 0x3f, 0x63, 0xfe, 0xe6, 0xd1, 0x4c, 0x1b, 0xcb, 0xff, 0xd3, 0x87, - 0x8e, 0xd1, 0xcd, 0x9c, 0x4d, 0x1d, 0x50, 0x9f, 0xb6, 0x11, 0x23, 0x6b, - 0xc3, 0x50, 0x09, 0x17, 0xff, 0x47, 0xfa, 0xcc, 0x0b, 0x8b, 0xa8, 0x75, - 0xff, 0xf4, 0xb4, 0xcc, 0x73, 0xb0, 0x9d, 0x81, 0x43, 0xaf, 0xff, 0xb4, - 0x39, 0xbf, 0xef, 0xa7, 0xe2, 0x6f, 0xf9, 0xd5, 0xba, 0x27, 0x99, 0x4d, - 0xae, 0xa6, 0x0a, 0xf0, 0xe0, 0xbf, 0xb5, 0xf4, 0x20, 0x19, 0x1d, 0x7f, - 0x23, 0x43, 0x8f, 0xf9, 0xd7, 0xff, 0xfe, 0x89, 0xd8, 0xd7, 0xb5, 0xbf, - 0xc0, 0xe0, 0x61, 0xf9, 0x83, 0xf9, 0xd7, 0xe5, 0xe9, 0x97, 0xdc, 0xeb, - 0x68, 0x28, 0x99, 0xfa, 0xe1, 0x7f, 0x64, 0xd2, 0x4e, 0x68, 0xea, 0x86, - 0x4a, 0xa8, 0x61, 0x8f, 0x91, 0x9e, 0xa4, 0xa0, 0xce, 0x4a, 0x80, 0x78, - 0xd4, 0x55, 0x25, 0x02, 0x5f, 0xa8, 0x62, 0xf8, 0xae, 0xf3, 0x2c, 0xb2, - 0x55, 0xf7, 0xee, 0x21, 0x29, 0x82, 0xfe, 0xfb, 0xa8, 0xf2, 0x3a, 0xfb, - 0x9c, 0x45, 0x9d, 0x7b, 0x51, 0xe3, 0xaf, 0x0f, 0xb4, 0x86, 0xf2, 0x62, - 0x1b, 0xdf, 0x14, 0xdb, 0x3a, 0xf7, 0x9c, 0x27, 0x57, 0x0d, 0xee, 0x88, - 0xaf, 0xe6, 0xc7, 0xe9, 0xc5, 0x0e, 0xbf, 0xbe, 0xe7, 0x33, 0x26, 0x3a, - 0xfc, 0xfd, 0xf8, 0x18, 0x3a, 0xa4, 0x9d, 0x08, 0x4c, 0x71, 0x71, 0x1b, - 0xc4, 0x87, 0x45, 0xde, 0x2e, 0xbf, 0x3f, 0x39, 0x9b, 0x9d, 0x7f, 0xfb, - 0xdd, 0x47, 0xff, 0x38, 0x18, 0x19, 0x1d, 0x7f, 0xfb, 0x7f, 0x9b, 0xff, - 0x02, 0xd7, 0x9c, 0x5c, 0xea, 0x84, 0x5e, 0x61, 0x38, 0xa4, 0x5f, 0xa3, - 0x5f, 0x46, 0x47, 0x5f, 0xff, 0xfc, 0xe9, 0xe4, 0xeb, 0x53, 0xe4, 0x93, - 0xae, 0x3e, 0x96, 0x73, 0x0e, 0xbd, 0xdc, 0xda, 0x3a, 0xfd, 0xed, 0x7d, - 0xd7, 0xce, 0xa2, 0x35, 0xdb, 0xef, 0xe6, 0x75, 0xd7, 0x6c, 0x1d, 0x7f, - 0xff, 0xf2, 0x29, 0xbc, 0xbd, 0x83, 0xed, 0x7c, 0xd6, 0xb3, 0x98, 0x2f, - 0x23, 0xaf, 0xfe, 0x60, 0x23, 0x00, 0x6e, 0x28, 0x9c, 0x3a, 0xec, 0x64, - 0xeb, 0x64, 0x1e, 0xd6, 0x91, 0x2f, 0xf0, 0x7b, 0x13, 0x3b, 0xee, 0x75, - 0xee, 0xff, 0xb0, 0xea, 0xe1, 0xe9, 0x6d, 0x19, 0xd4, 0x91, 0x3a, 0xef, - 0x17, 0xff, 0x67, 0x3f, 0x5a, 0x6b, 0xee, 0xa3, 0x0e, 0xbc, 0xea, 0xfa, - 0x3a, 0xa4, 0x7c, 0x6e, 0x8b, 0x78, 0x38, 0xb3, 0xaf, 0xbf, 0xf6, 0x7e, - 0x75, 0x21, 0xbe, 0xe0, 0xdd, 0xff, 0x37, 0xa3, 0x1b, 0xa4, 0x74, 0xea, - 0x85, 0xd1, 0x69, 0x46, 0x3c, 0x12, 0xdc, 0x85, 0xaa, 0x22, 0x70, 0xb5, - 0xe3, 0x6a, 0x18, 0x42, 0x81, 0x7f, 0xe9, 0x05, 0xff, 0x9d, 0x02, 0x0f, - 0x6a, 0x7c, 0x64, 0xeb, 0xf6, 0xb1, 0x48, 0xd1, 0xd7, 0xf2, 0xbe, 0x90, - 0x77, 0x91, 0xd7, 0xfe, 0x7e, 0x6d, 0xa7, 0x71, 0xf7, 0xfc, 0xeb, 0xff, - 0xf2, 0x7a, 0x17, 0x9b, 0xfa, 0x17, 0xf7, 0x8f, 0xf9, 0xd7, 0xc8, 0x2e, - 0x13, 0xaf, 0xfb, 0x51, 0xcf, 0x43, 0x01, 0x43, 0xaa, 0x48, 0xae, 0x0a, - 0xbe, 0x87, 0xef, 0xff, 0x69, 0x39, 0x12, 0xec, 0x4c, 0x20, 0x50, 0xeb, - 0x9b, 0xb6, 0x75, 0xfc, 0xa7, 0xa3, 0xb1, 0xa3, 0xaf, 0xee, 0xa6, 0xfa, - 0x7d, 0xce, 0xa9, 0x1f, 0xa2, 0x0c, 0xfe, 0x5b, 0x7f, 0xe1, 0x79, 0xba, - 0xfc, 0xe2, 0x04, 0xeb, 0xc1, 0x41, 0x3a, 0xfe, 0x8f, 0x2a, 0x1e, 0x37, - 0x3a, 0xbe, 0x1e, 0x52, 0x0d, 0x54, 0x95, 0x86, 0xe1, 0x3b, 0x4c, 0x12, - 0x1d, 0xf3, 0x18, 0x72, 0x17, 0xcb, 0x2f, 0x66, 0x10, 0xf7, 0xe4, 0x5a, - 0xac, 0xab, 0xd5, 0xb3, 0xaf, 0xbe, 0xc3, 0x3a, 0x3a, 0xef, 0xfc, 0x75, - 0xf7, 0x39, 0x9a, 0x3a, 0xec, 0x98, 0xeb, 0x4b, 0xe1, 0xf9, 0x4e, 0x48, - 0xe2, 0xff, 0x48, 0x6f, 0xc9, 0xe7, 0x1c, 0x3a, 0xfd, 0xc0, 0xe6, 0x09, - 0xd7, 0xff, 0x2b, 0xa6, 0x76, 0x36, 0x6b, 0xb1, 0xb9, 0xd7, 0xf6, 0xfc, - 0x06, 0xfe, 0x91, 0xd4, 0xe8, 0x9d, 0xd1, 0x28, 0x12, 0x2f, 0xfb, 0x07, - 0x99, 0xac, 0x4e, 0x9d, 0x7f, 0xfd, 0x2f, 0x0e, 0x3f, 0x87, 0x3d, 0xec, - 0x64, 0xeb, 0xd3, 0xe6, 0xc3, 0xaf, 0xff, 0x7b, 0x59, 0x37, 0x63, 0x66, - 0x77, 0xb0, 0x75, 0xfd, 0xd0, 0xa6, 0xc8, 0x09, 0xd5, 0x87, 0xf2, 0xe9, - 0x77, 0xd9, 0xe4, 0xd1, 0xd7, 0xf2, 0xb1, 0x30, 0xab, 0x73, 0x80, 0xea, - 0xd1, 0xec, 0xf8, 0x82, 0xa4, 0xaa, 0x90, 0x30, 0xc1, 0x69, 0x7e, 0xe6, - 0xbc, 0x4d, 0x18, 0x4b, 0xf9, 0xe6, 0xf3, 0x39, 0xd3, 0xaf, 0xf6, 0x91, - 0x4e, 0xb8, 0xa1, 0xd7, 0xc9, 0xac, 0x0b, 0x9e, 0x6f, 0x87, 0x2f, 0xfc, - 0xea, 0xff, 0x83, 0x48, 0x3b, 0xc8, 0xeb, 0xff, 0xfb, 0xd9, 0xd4, 0x8f, - 0x27, 0xf1, 0x26, 0x19, 0x65, 0x92, 0xaf, 0xf7, 0x40, 0xeb, 0x0b, 0xac, - 0xea, 0x14, 0x48, 0x79, 0x7a, 0xf8, 0x39, 0x8a, 0x15, 0x7c, 0xff, 0xbf, - 0x8e, 0xbf, 0xee, 0x3b, 0x7e, 0x76, 0x3e, 0x89, 0xd7, 0x81, 0x1c, 0x3a, - 0xef, 0x68, 0x27, 0xad, 0x31, 0xdd, 0xe9, 0x08, 0x0d, 0x10, 0xcd, 0xee, - 0xc4, 0xe7, 0x5e, 0x65, 0x96, 0x4a, 0xbd, 0x82, 0xd2, 0x98, 0x2f, 0xef, - 0xfd, 0x93, 0xe0, 0x5e, 0x43, 0x13, 0x9d, 0x5f, 0x9f, 0x38, 0x95, 0x5f, - 0x38, 0xab, 0x55, 0x51, 0xd7, 0x2b, 0x55, 0x6a, 0x75, 0xfb, 0x3d, 0xe0, - 0x4e, 0x75, 0xa4, 0xad, 0x4f, 0x28, 0x48, 0xaf, 0x3a, 0xbc, 0x1d, 0x7e, - 0xc0, 0xf5, 0xd5, 0xce, 0xbf, 0x0e, 0x06, 0x16, 0x75, 0x42, 0xae, 0x19, - 0xc8, 0x82, 0x43, 0x8e, 0xfb, 0x97, 0xcc, 0x51, 0xc8, 0x51, 0x74, 0x89, - 0xdd, 0x00, 0x5b, 0xb0, 0x75, 0x92, 0x9b, 0xfd, 0x0b, 0xc4, 0xe4, 0xd2, - 0x3a, 0xf7, 0x92, 0x0e, 0xbb, 0x04, 0xea, 0x43, 0x5c, 0x01, 0xab, 0xff, - 0xf7, 0x5f, 0x9a, 0xc4, 0x17, 0xf6, 0x99, 0x81, 0x3a, 0xfc, 0x14, 0xe4, - 0x78, 0xeb, 0xb7, 0xfc, 0xeb, 0xf9, 0x71, 0xaf, 0xd1, 0xa7, 0x5e, 0xd4, - 0x29, 0xf9, 0xe2, 0xe8, 0x62, 0xff, 0x03, 0x39, 0xff, 0xe8, 0x27, 0x5f, - 0xfb, 0x16, 0x81, 0xe6, 0x05, 0xd6, 0x75, 0xf6, 0x2f, 0xe8, 0x4e, 0xae, - 0x9e, 0xf8, 0x9e, 0x5f, 0xfe, 0x40, 0xf7, 0xee, 0xb3, 0x8d, 0x77, 0x69, - 0xa2, 0x0c, 0xbe, 0x07, 0x71, 0xa7, 0x54, 0x8f, 0xe3, 0x6d, 0x5e, 0xf7, - 0x40, 0xae, 0x75, 0xff, 0xee, 0x3e, 0xcc, 0x16, 0xf5, 0x3f, 0xfb, 0xe3, - 0xaa, 0x11, 0x22, 0xa9, 0x25, 0x00, 0xfd, 0x6e, 0xa8, 0x93, 0xa6, 0xba, - 0x84, 0x97, 0xa3, 0x2a, 0xbf, 0xdf, 0xa7, 0x7b, 0x9f, 0xb9, 0xd7, 0xff, - 0xfc, 0xbc, 0xf7, 0x9f, 0x83, 0x1b, 0xcb, 0xef, 0x3f, 0x5a, 0x68, 0xeb, - 0xfe, 0x5a, 0x33, 0x82, 0x1e, 0xc1, 0xd7, 0x74, 0x07, 0x5f, 0xff, 0xa4, - 0x82, 0x1e, 0xe6, 0xff, 0x5c, 0x7c, 0x21, 0x3a, 0xf2, 0x32, 0xae, 0x75, - 0xfe, 0xcd, 0x9a, 0xf7, 0xa1, 0x67, 0x57, 0x0f, 0x4f, 0xa3, 0xf5, 0x09, - 0xc0, 0x63, 0x4a, 0x1b, 0xcc, 0x2d, 0xa8, 0x54, 0x5f, 0xed, 0xbc, 0xd6, - 0xde, 0x72, 0x0e, 0xbf, 0xfe, 0x18, 0x6f, 0xce, 0x62, 0x01, 0x53, 0x9b, - 0x58, 0x75, 0x49, 0x77, 0x64, 0x24, 0x18, 0xa4, 0x92, 0xa3, 0xff, 0x4b, - 0xd4, 0x76, 0x7e, 0x4e, 0xda, 0x37, 0xbf, 0xda, 0xd6, 0x0f, 0xfb, 0x78, - 0x75, 0xf0, 0xa6, 0xd4, 0x1d, 0x69, 0x8e, 0xbf, 0xb5, 0x83, 0xfe, 0xde, - 0x1d, 0x6d, 0x9f, 0x11, 0x2f, 0x86, 0xbf, 0x91, 0x68, 0x46, 0xff, 0x81, - 0xef, 0xc0, 0xb8, 0xcf, 0x1d, 0x7f, 0xf8, 0x67, 0xf9, 0x32, 0x0e, 0x07, - 0x05, 0x43, 0xaf, 0xe4, 0xdf, 0x6b, 0xb1, 0xe3, 0xaf, 0x7d, 0xc8, 0x3a, - 0xa1, 0x12, 0xea, 0xe9, 0x6e, 0x61, 0x7f, 0xff, 0xe7, 0x0e, 0x0b, 0xfb, - 0x59, 0xcf, 0xff, 0x8c, 0xdf, 0xda, 0x43, 0xaf, 0x47, 0x26, 0x3a, 0xbe, - 0x36, 0xbb, 0x31, 0x2d, 0x32, 0x78, 0x41, 0x06, 0x15, 0x39, 0x2b, 0xa9, - 0xb0, 0xbd, 0xdc, 0xdd, 0x25, 0xd9, 0xf6, 0x15, 0xef, 0x3c, 0x73, 0xfc, - 0x63, 0x42, 0x8e, 0x08, 0x68, 0x32, 0x63, 0xb6, 0xd7, 0x7b, 0x79, 0xf6, - 0x1d, 0x7f, 0x7c, 0x6f, 0x63, 0x7d, 0xa3, 0xaf, 0x7c, 0xfd, 0x93, 0xab, - 0x73, 0xd3, 0xf1, 0x9d, 0xfd, 0x8c, 0xe6, 0x0a, 0x87, 0x5f, 0x2d, 0xf3, - 0x47, 0x52, 0x1e, 0x63, 0x96, 0x5f, 0xff, 0x36, 0x35, 0xa8, 0x5e, 0x79, - 0x35, 0xd7, 0x3a, 0xff, 0x08, 0xc4, 0x97, 0x08, 0x75, 0xfe, 0xf2, 0x6c, - 0x4f, 0x4a, 0x0a, 0xb2, 0xce, 0xbf, 0xb0, 0x54, 0xe4, 0x30, 0x87, 0x87, - 0xf4, 0xce, 0xb1, 0x30, 0x54, 0x4d, 0xd3, 0x95, 0xf7, 0x01, 0xbc, 0x8e, - 0xbf, 0xc3, 0x21, 0xc5, 0xc3, 0x4e, 0xbc, 0xb0, 0xe1, 0xd5, 0x07, 0xdd, - 0x84, 0x6e, 0x61, 0x7b, 0x6c, 0x1e, 0x3a, 0xff, 0xf7, 0xa1, 0x68, 0x1c, - 0x15, 0x3b, 0x0b, 0x3a, 0x9a, 0x7c, 0xfe, 0x1f, 0xbf, 0xfe, 0x4f, 0x76, - 0x35, 0x1d, 0x84, 0x9e, 0x14, 0x3a, 0xfd, 0xef, 0x69, 0xff, 0x3a, 0xfd, - 0x0b, 0xf6, 0x34, 0xeb, 0x92, 0x73, 0xaa, 0x11, 0x64, 0x89, 0xdd, 0x28, - 0xf1, 0x35, 0xf9, 0x94, 0x0e, 0xd2, 0x1d, 0x7f, 0xdd, 0x89, 0x20, 0xe2, - 0xe0, 0xeb, 0xfe, 0xcf, 0x77, 0x16, 0x2f, 0xe3, 0xaf, 0xed, 0x89, 0xcd, - 0xe1, 0x5c, 0xeb, 0x08, 0x4f, 0xa3, 0x0d, 0xaf, 0xcb, 0x86, 0xce, 0x13, - 0xaf, 0xa5, 0x0b, 0x73, 0xaf, 0xdc, 0xfd, 0x69, 0xa3, 0xae, 0xf6, 0xb0, - 0xfc, 0x1c, 0xa3, 0xe9, 0x05, 0x42, 0x34, 0x41, 0x09, 0x6b, 0x68, 0xeb, - 0xfa, 0x27, 0xc1, 0x45, 0x0e, 0xae, 0x1b, 0xcd, 0x08, 0x5f, 0xfd, 0x02, - 0xfd, 0x8f, 0xd8, 0xe6, 0xb4, 0x55, 0x4e, 0xa8, 0xd8, 0x31, 0xb7, 0x63, - 0x1a, 0xc8, 0x6f, 0xf3, 0x87, 0x5a, 0x8e, 0x48, 0xeb, 0x81, 0x39, 0xd7, - 0xfb, 0x79, 0x6f, 0xa4, 0xf4, 0x1d, 0x79, 0x37, 0xd1, 0xd5, 0x87, 0xa0, - 0x86, 0x94, 0x88, 0x87, 0xeb, 0x3d, 0xd8, 0xd3, 0xaf, 0x73, 0x34, 0x77, - 0x8b, 0x5b, 0xff, 0xe0, 0xfc, 0x74, 0xcd, 0x44, 0xf8, 0x28, 0xa1, 0xd7, - 0xfb, 0x8b, 0x8d, 0xfc, 0xed, 0x3a, 0xb1, 0x10, 0x48, 0x9f, 0x7c, 0x8b, - 0x89, 0x8e, 0xbe, 0xc9, 0xc1, 0x23, 0xaa, 0x63, 0xc3, 0x64, 0x86, 0xf8, - 0x01, 0x0c, 0x1d, 0x50, 0x78, 0xae, 0x49, 0x76, 0x32, 0x75, 0x15, 0x7f, - 0x6b, 0xec, 0x72, 0x16, 0x55, 0x15, 0x45, 0x51, 0x54, 0x55, 0x48, 0xf8, - 0x10, 0x2b, 0xf2, 0xe0, 0x05, 0x6d, 0x85, 0x6d, 0x05, 0x5d, 0xdc, 0x2a, - 0xfe, 0x77, 0xf4, 0xd0, 0xb2, 0xbe, 0x16, 0xb6, 0x54, 0x95, 0x45, 0x51, - 0x55, 0x22, 0xd1, 0x02, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, 0x2a, - 0xa7, 0x37, 0x81, 0x0a, 0x40, 0xaf, 0xc2, 0xb4, 0x15, 0xb0, 0x2a, 0x8a, - 0xa2, 0xaa, 0x45, 0xa6, 0x82, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x46, - 0xa3, 0xf0, 0xaf, 0x05, 0x6d, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, 0x54, - 0xe6, 0xa1, 0x40, 0xae, 0x05, 0x74, 0x2a, 0xca, 0x15, 0x45, 0x51, 0x54, - 0x55, 0x15, 0x41, 0x35, 0x1b, 0x85, 0x7e, 0x14, 0x00, 0xaa, 0x2a, 0x8a, - 0xa2, 0xaf, 0xdd, 0x8f, 0xf5, 0x85, 0x51, 0x55, 0x23, 0xcf, 0x68, 0x57, - 0x42, 0x9c, 0x2b, 0xf2, 0x7b, 0x34, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, - 0x91, 0xa8, 0xdc, 0x29, 0x02, 0xb6, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, - 0x54, 0x8d, 0x40, 0x42, 0xba, 0x14, 0x21, 0x56, 0xe9, 0x54, 0x55, 0x15, - 0x69, 0x15, 0x45, 0x6e, 0x58, 0x51, 0x54, 0x55, 0x15, 0x45, 0x54, 0xe7, - 0xcd, 0x20, 0xa5, 0x06, 0x9a, 0x35, 0x30, 0x57, 0xe1, 0x5e, 0x0a, 0xb6, - 0x15, 0x45, 0x51, 0x56, 0x91, 0x54, 0x56, 0xe5, 0x85, 0x15, 0x45, 0x54, - 0x1e, 0x94, 0x82, 0x90, 0x6b, 0x83, 0x4b, 0x0a, 0xa2, 0xa8, 0xaa, 0x2a, - 0x8a, 0xa2, 0xaa, 0x0d, 0x96, 0xe1, 0x5c, 0x0a, 0x58, 0x50, 0x85, 0x51, - 0x54, 0x55, 0x15, 0x5c, 0x2f, 0xb4, 0x15, 0xe0, 0xaa, 0x2a, 0x8a, 0xa2, - 0xa9, 0x65, 0xf0, 0x85, 0x78, 0x2a, 0xcb, 0x2a, 0x8a, 0xa2, 0xab, 0xf2, - 0xd0, 0x01, 0x54, 0x55, 0x15, 0x45, 0x51, 0x55, 0x06, 0xa2, 0x60, 0xae, - 0x85, 0x00, 0x2a, 0xa1, 0x7e, 0xa6, 0x77, 0x19, 0x1e, 0x84, 0xa3, 0x16, - 0xda, 0xd9, 0xba, 0x42, 0x33, 0xab, 0x9e, 0xcc, 0x73, 0xc8, 0x46, 0x2d, - 0x27, 0xa7, 0x0e, 0xcb, 0xf9, 0xd0, 0xbb, 0x69, 0x9f, 0xcc, 0x20, 0x79, - 0xd8, 0xca, 0xca, 0x5e, 0xd9, 0x67, 0xd2, 0x4d, 0xa4, 0x9b, 0xf4, 0x86, - 0x33, 0x45, 0x30, 0x9a, 0xb5, 0xe4, 0x85, 0x95, 0x7c, 0x8d, 0x7e, 0x1d, - 0x79, 0x03, 0x87, 0x59, 0x8d, 0xd1, 0x1b, 0xc3, 0x9e, 0x8d, 0x78, 0x82, - 0xd1, 0xb1, 0x94, 0x8f, 0xf6, 0x94, 0x05, 0x7f, 0xba, 0x8c, 0x87, 0x91, - 0x39, 0xd7, 0x93, 0x62, 0xa4, 0xea, 0xdd, 0x11, 0xd3, 0x1c, 0xf8, 0xd2, - 0xfd, 0x99, 0x33, 0xfd, 0x3a, 0xef, 0xe0, 0xeb, 0xfb, 0x8e, 0x3f, 0x63, - 0xf3, 0xae, 0x7e, 0x1d, 0x64, 0x39, 0xa5, 0xad, 0x9a, 0x75, 0x96, 0x75, - 0xdb, 0x6c, 0x22, 0x25, 0xf8, 0x2d, 0xd4, 0x37, 0x1e, 0xfa, 0x21, 0x7f, - 0xdd, 0x85, 0xe4, 0xd0, 0x33, 0x9d, 0x7f, 0xf7, 0xc7, 0x68, 0x7b, 0x1f, - 0xe0, 0xfe, 0x75, 0xdf, 0xc1, 0xd5, 0x87, 0xb9, 0xfa, 0x35, 0x62, 0x62, - 0x1f, 0xad, 0x02, 0x12, 0x97, 0xff, 0x08, 0xc4, 0xe3, 0x89, 0xb2, 0x36, - 0xce, 0xbd, 0x1b, 0xe8, 0xea, 0x73, 0xe1, 0xd2, 0x2d, 0xe7, 0xe4, 0x1d, - 0x7e, 0x4d, 0xb7, 0x1f, 0xce, 0xa9, 0x1e, 0x1a, 0xc6, 0xaf, 0xfb, 0xeb, - 0x87, 0x58, 0xb8, 0x57, 0x3a, 0xf6, 0x6e, 0xc9, 0xd7, 0xb7, 0xff, 0x38, - 0x7b, 0x22, 0x79, 0x7d, 0xb3, 0x39, 0x23, 0xaf, 0x05, 0xc4, 0xea, 0x43, - 0x7a, 0xe4, 0x77, 0xff, 0xd1, 0xf1, 0xf9, 0xc7, 0xfe, 0x18, 0x65, 0x96, - 0x4e, 0xa8, 0x4d, 0x81, 0xde, 0xf4, 0xe2, 0x01, 0xfa, 0x54, 0x37, 0x17, - 0xb0, 0xe7, 0x3b, 0x7c, 0xa3, 0x25, 0x0c, 0x27, 0x72, 0x12, 0x6d, 0x86, - 0xa6, 0xe7, 0x69, 0x29, 0x81, 0x5d, 0x16, 0x68, 0x5c, 0xf0, 0xdd, 0x70, - 0xac, 0xec, 0x2a, 0x5e, 0x95, 0xeb, 0xf9, 0x90, 0xc7, 0x9f, 0xa8, 0x4b, - 0xfa, 0x3c, 0x4b, 0xe4, 0x16, 0xc1, 0xd7, 0xf3, 0x2f, 0xce, 0x3e, 0xe7, - 0x5f, 0xff, 0xb5, 0xce, 0x24, 0xda, 0xe4, 0x79, 0x1a, 0x81, 0x3a, 0x96, - 0x8a, 0x21, 0x1f, 0x64, 0xba, 0xf9, 0x7e, 0x8d, 0x1d, 0x7f, 0xbd, 0x00, - 0x6f, 0x53, 0x87, 0x5f, 0xd8, 0xde, 0xc6, 0xf2, 0x3a, 0xfe, 0x5e, 0x91, - 0x4f, 0x32, 0x75, 0xfa, 0x37, 0xec, 0x48, 0xea, 0x14, 0x5a, 0xf8, 0xcb, - 0xe9, 0x6e, 0xd1, 0x7d, 0xdb, 0xf8, 0xeb, 0xf7, 0x9c, 0x41, 0x87, 0x5f, - 0xed, 0x62, 0xd3, 0xdd, 0x73, 0xad, 0x18, 0x7d, 0xa2, 0x2f, 0xe2, 0x5b, - 0xe9, 0x7c, 0x5a, 0x1d, 0x7b, 0x6b, 0x90, 0x75, 0xfe, 0xe2, 0x4c, 0x39, - 0xb1, 0xce, 0xbb, 0x7d, 0x7c, 0x3f, 0x48, 0x23, 0xe0, 0xf5, 0xff, 0x0c, - 0x3c, 0xfd, 0x8e, 0x7e, 0x75, 0xcf, 0xb0, 0xeb, 0xfa, 0x42, 0x92, 0xee, - 0x1d, 0x7e, 0x9d, 0x39, 0x12, 0x3a, 0xa6, 0x3e, 0x9e, 0x0b, 0x89, 0x5d, - 0xf6, 0x05, 0x14, 0x3a, 0xff, 0xf3, 0xa7, 0xa3, 0xda, 0xeb, 0xa7, 0x40, - 0x75, 0xf0, 0x88, 0x24, 0x75, 0xff, 0xbb, 0x1c, 0xfc, 0x71, 0x97, 0xfc, - 0xeb, 0xd9, 0x93, 0x1d, 0x6c, 0xe9, 0xed, 0x7e, 0x7f, 0x7f, 0x03, 0x80, - 0x5b, 0x89, 0xd7, 0xcb, 0x8c, 0x9c, 0xeb, 0xf6, 0x6c, 0x18, 0xdc, 0xea, - 0x43, 0xc9, 0xd1, 0x0d, 0xf4, 0x0f, 0x9a, 0x75, 0xa0, 0x2a, 0xa4, 0x32, - 0x14, 0x3c, 0x2f, 0xe9, 0x0b, 0xa3, 0x8b, 0xd6, 0x8a, 0x3c, 0xeb, 0xb6, - 0x43, 0x7f, 0x6b, 0x16, 0x9d, 0x83, 0xaf, 0x6f, 0x2d, 0x1d, 0x5b, 0x9e, - 0x47, 0x0a, 0xef, 0x6b, 0xf6, 0x4e, 0xa8, 0x3c, 0x1c, 0x23, 0xbe, 0x03, - 0xf2, 0x47, 0x5f, 0x40, 0x15, 0x3a, 0x2a, 0xfd, 0x26, 0x19, 0x65, 0x93, - 0xa8, 0x4f, 0x44, 0x04, 0xb7, 0xcf, 0xe5, 0xf8, 0xea, 0x0a, 0x2d, 0x31, - 0xcb, 0xf2, 0x1a, 0x85, 0xf3, 0xec, 0x30, 0x48, 0x6b, 0x2e, 0x15, 0xcf, - 0x0a, 0x6f, 0xe5, 0x66, 0x8c, 0x62, 0x60, 0x86, 0xa5, 0xe5, 0x65, 0x57, - 0xaa, 0x0e, 0xbd, 0x21, 0x73, 0xad, 0xba, 0xb2, 0x78, 0xb0, 0x57, 0x7f, - 0x47, 0x27, 0x8e, 0x4e, 0x75, 0xf8, 0x1f, 0xe0, 0xb4, 0xeb, 0xdc, 0x89, - 0x8e, 0xbe, 0x41, 0x79, 0x8e, 0xbf, 0xde, 0xcf, 0xb1, 0x32, 0x68, 0xea, - 0x92, 0x31, 0x78, 0x5c, 0xb2, 0x7e, 0x8e, 0x6c, 0x20, 0xbf, 0xe8, 0x4e, - 0xc2, 0xe7, 0xc6, 0x4e, 0xbf, 0xa3, 0xa9, 0x3b, 0x89, 0xd7, 0xfd, 0x38, - 0xe4, 0xbb, 0x9f, 0xe8, 0xeb, 0xff, 0x60, 0xef, 0x2d, 0x70, 0x11, 0xf9, - 0xd7, 0xec, 0xf6, 0xb1, 0x43, 0xa9, 0x0f, 0x99, 0x67, 0xf7, 0x83, 0x1b, - 0x0e, 0xbf, 0xfe, 0xc1, 0x18, 0x64, 0x23, 0x1b, 0xc9, 0x04, 0xeb, 0xff, - 0xcf, 0xf2, 0x69, 0x47, 0x27, 0xf8, 0xce, 0x74, 0xea, 0x0a, 0x2e, 0x7a, - 0x3a, 0x29, 0x97, 0xfc, 0xbe, 0xe7, 0xb0, 0x1c, 0x9c, 0xeb, 0xfe, 0x8f, - 0x67, 0x1a, 0xee, 0xd3, 0x45, 0xf1, 0x7e, 0xce, 0x46, 0xf2, 0x3a, 0xf7, - 0x61, 0x6d, 0x3e, 0xaf, 0x21, 0xdf, 0xff, 0x85, 0xbf, 0x3b, 0x09, 0xc4, - 0x5a, 0x6d, 0xc2, 0xce, 0xbc, 0xfc, 0x9c, 0xd1, 0x7f, 0xd4, 0x22, 0xcf, - 0x0c, 0xda, 0xaf, 0x7f, 0xff, 0xba, 0xfa, 0x48, 0xd7, 0xcf, 0x77, 0x17, - 0x8d, 0x7e, 0x1d, 0x74, 0x6d, 0x1d, 0x7d, 0xad, 0x3a, 0xce, 0xae, 0xa2, - 0x67, 0xf6, 0x0f, 0x0c, 0x5f, 0xff, 0xd2, 0x70, 0xb7, 0xa8, 0x39, 0xb1, - 0xe5, 0xa4, 0x09, 0xd7, 0xfd, 0x0b, 0xf8, 0x1c, 0xcf, 0xf4, 0x75, 0xff, - 0x26, 0x08, 0x54, 0x4c, 0xe1, 0xd4, 0x87, 0xe1, 0xb4, 0x75, 0x7f, 0x3f, - 0x37, 0x96, 0x78, 0xeb, 0xff, 0x7b, 0x49, 0xcf, 0x08, 0x1e, 0x47, 0x5f, - 0xfe, 0x5c, 0x6d, 0xe0, 0x07, 0x33, 0x64, 0x6e, 0x75, 0xff, 0xa3, 0x39, - 0x9c, 0xfd, 0x69, 0xa3, 0xaf, 0x3e, 0xfb, 0x47, 0x5f, 0xcf, 0xed, 0x46, - 0x4e, 0x75, 0x42, 0x67, 0xd8, 0x5a, 0x87, 0xa2, 0x99, 0xb0, 0xf5, 0x91, - 0xfb, 0xfe, 0x04, 0x2f, 0x58, 0xb8, 0x57, 0x3a, 0xff, 0xed, 0x60, 0xfb, - 0x5f, 0x76, 0x46, 0x6e, 0x75, 0xff, 0x33, 0xf6, 0x7d, 0x62, 0xe1, 0x5c, - 0xeb, 0xc9, 0xd4, 0x3a, 0xfa, 0x5c, 0x0c, 0x8e, 0xbe, 0x5f, 0x92, 0x73, - 0xab, 0x0f, 0x11, 0x08, 0xaf, 0xfe, 0xd9, 0xe5, 0x20, 0x65, 0x9d, 0x45, - 0x9d, 0x74, 0xfe, 0x3a, 0xff, 0x6c, 0xeb, 0xca, 0x30, 0x4e, 0xa8, 0x3c, - 0x9c, 0x17, 0xbf, 0xb1, 0x9f, 0xbd, 0x7f, 0x1d, 0x7f, 0xfe, 0xf7, 0xd9, - 0x46, 0xc4, 0x1f, 0xf8, 0x90, 0xbc, 0x2a, 0xfb, 0xbf, 0x77, 0xf1, 0xd7, - 0xec, 0x5e, 0x26, 0xc3, 0xaf, 0x4f, 0x32, 0xb9, 0xd5, 0x3a, 0x3c, 0xf0, - 0xbd, 0xaa, 0xe8, 0x4a, 0x02, 0x7b, 0xbd, 0x87, 0x5f, 0xb8, 0x93, 0xba, - 0xcd, 0x30, 0x9d, 0xf7, 0x81, 0x0e, 0x69, 0x84, 0xee, 0xfe, 0x0d, 0x40, - 0x9d, 0xfe, 0x17, 0x53, 0xd1, 0xcf, 0xcd, 0x40, 0x9d, 0xfe, 0xd6, 0x75, - 0x34, 0x09, 0xcd, 0x30, 0x9d, 0xd8, 0x13, 0x4c, 0x27, 0x73, 0x2c, 0x9e, - 0x61, 0x3a, 0xc4, 0xd2, 0xf7, 0x34, 0x42, 0xd5, 0x91, 0xe9, 0x03, 0x62, - 0x03, 0x24, 0x56, 0xf1, 0x66, 0x13, 0x30, 0x7c, 0xf6, 0x4d, 0xd3, 0xf7, - 0x66, 0x3c, 0x7a, 0x85, 0xcc, 0xf4, 0x3f, 0xea, 0xf3, 0x90, 0x0c, 0x23, - 0xb5, 0x18, 0x9f, 0xa5, 0x20, 0x5e, 0x1f, 0xd6, 0x75, 0xff, 0x40, 0x3c, - 0x29, 0xb3, 0xea, 0xce, 0xbc, 0x39, 0xac, 0x3d, 0x7e, 0x0e, 0x5e, 0x0f, - 0xf3, 0x1d, 0x50, 0xcc, 0xe4, 0x9e, 0x13, 0xe1, 0x86, 0xd6, 0x17, 0xb6, - 0x35, 0x64, 0x86, 0x3c, 0xc6, 0x3c, 0x86, 0x57, 0x63, 0x62, 0x15, 0x7d, - 0x1d, 0x7a, 0x74, 0x5b, 0x64, 0x33, 0x3e, 0x98, 0xdf, 0x83, 0x9c, 0x45, - 0x0e, 0xbf, 0xbb, 0x1f, 0x47, 0x7f, 0xce, 0xbf, 0x7b, 0x26, 0x45, 0x9d, - 0x7e, 0x8d, 0xff, 0xfe, 0x0e, 0xa8, 0x3d, 0x01, 0x27, 0xbf, 0x46, 0xc8, - 0x1f, 0x1d, 0x7e, 0x4d, 0x9e, 0x49, 0xce, 0xbf, 0x3c, 0xbd, 0x8d, 0x3a, - 0xfc, 0x39, 0xf7, 0x26, 0x3a, 0xff, 0xf6, 0x7f, 0xae, 0xa7, 0xcd, 0xe5, - 0x19, 0x39, 0xd7, 0xfd, 0xd7, 0x5f, 0x52, 0x37, 0x91, 0xd7, 0xf7, 0xd1, - 0x96, 0xdb, 0xce, 0x75, 0x49, 0x16, 0xe8, 0x9b, 0xf9, 0xc5, 0x4e, 0x9d, - 0x28, 0x48, 0x1a, 0x4f, 0xc2, 0x91, 0x26, 0xf4, 0x37, 0xef, 0xfd, 0x8f, - 0xd9, 0x90, 0x7b, 0x9b, 0x9d, 0x7f, 0x7f, 0x34, 0xa3, 0xda, 0x3a, 0xff, - 0xff, 0xfd, 0x9d, 0xc1, 0xff, 0x07, 0xdd, 0xce, 0xc6, 0x4c, 0x9c, 0x9b, - 0xa9, 0xbf, 0x8e, 0xbe, 0x18, 0xc6, 0x4e, 0xbe, 0x8d, 0xf4, 0xe7, 0x54, - 0x36, 0x4b, 0xb3, 0xa6, 0x04, 0xe3, 0x29, 0xa1, 0xe9, 0x0f, 0x25, 0x72, - 0x77, 0x94, 0x4a, 0x2b, 0xbe, 0x3d, 0x01, 0x7e, 0xc8, 0x41, 0x7d, 0x20, - 0xbf, 0xfe, 0x41, 0xc5, 0xc7, 0xd1, 0x04, 0x87, 0x16, 0x75, 0xff, 0x05, - 0x30, 0x41, 0x2c, 0xd1, 0xd7, 0xfd, 0xd4, 0x97, 0x5e, 0x48, 0xb3, 0xaf, - 0xfd, 0xa4, 0x1d, 0xe5, 0xe4, 0xd2, 0x1d, 0x58, 0x7e, 0x9e, 0x37, 0xbf, - 0x69, 0x70, 0x18, 0x3a, 0xa4, 0x99, 0xf6, 0x26, 0xae, 0x15, 0x5e, 0x21, - 0xbe, 0x18, 0xe4, 0x8e, 0xbf, 0xee, 0xc4, 0x90, 0x44, 0x1b, 0x9d, 0x7f, - 0xd1, 0x9e, 0xfb, 0xff, 0xf1, 0xb9, 0xd6, 0xe4, 0x22, 0x4f, 0x08, 0x16, - 0x6f, 0x7f, 0xff, 0xfb, 0xae, 0x9e, 0x90, 0x07, 0xda, 0xeb, 0xcb, 0xe8, - 0xc3, 0x79, 0x12, 0x3a, 0xff, 0xda, 0xfb, 0xe4, 0x10, 0x4b, 0x34, 0x75, - 0x2b, 0xa2, 0xdb, 0xae, 0xf7, 0xff, 0xf6, 0x6f, 0x9a, 0x71, 0xea, 0x47, - 0xba, 0x07, 0x59, 0xd5, 0x09, 0xb4, 0x3c, 0x3a, 0x84, 0x9a, 0xfe, 0x10, - 0x2d, 0x3b, 0x07, 0x5f, 0xff, 0x9c, 0x7c, 0xef, 0xd1, 0x8f, 0x69, 0x9c, - 0xe9, 0xd7, 0xfe, 0x9d, 0xc7, 0x5e, 0xea, 0x46, 0x8e, 0xbf, 0xe8, 0xff, - 0x41, 0x03, 0xf2, 0x47, 0x5e, 0xe6, 0xb4, 0x78, 0x80, 0xef, 0x9a, 0xee, - 0xd3, 0x44, 0x06, 0xc1, 0xa9, 0xbf, 0xb9, 0x1d, 0x8f, 0x99, 0x24, 0x50, - 0x71, 0x8a, 0x9d, 0x32, 0x3f, 0xb0, 0xdd, 0xaf, 0xd3, 0x9f, 0xf4, 0x6e, - 0xb7, 0xb6, 0x47, 0x4e, 0xac, 0x54, 0x24, 0x91, 0xe5, 0x7d, 0x2b, 0xbd, - 0xd7, 0x57, 0x3a, 0xfa, 0x3f, 0xdb, 0xc3, 0xab, 0xf3, 0xc2, 0xf0, 0xf5, - 0xf0, 0xfb, 0xf0, 0x1d, 0x7e, 0x5a, 0xb2, 0xac, 0xab, 0x2a, 0xc1, 0xd7, - 0xff, 0xf4, 0xb3, 0x49, 0xce, 0x22, 0xfe, 0xfb, 0xb8, 0xcf, 0x8e, 0xac, - 0x45, 0xda, 0x11, 0x39, 0xe5, 0xff, 0xe6, 0x70, 0x7d, 0x83, 0x2c, 0xd7, - 0xd5, 0x9d, 0x7f, 0xfa, 0x59, 0xbc, 0xbe, 0xc7, 0xec, 0x32, 0xcb, 0x25, - 0x5f, 0x96, 0xce, 0x26, 0xc3, 0xaf, 0x4b, 0x06, 0x63, 0xfb, 0xfa, 0xa5, - 0x50, 0x8f, 0xa7, 0x86, 0x2d, 0x42, 0xa2, 0xbe, 0xc3, 0x78, 0x63, 0x27, - 0xbf, 0xe4, 0x19, 0x69, 0x5a, 0xab, 0x0a, 0xca, 0xb0, 0x75, 0xf4, 0xda, - 0xc9, 0x8e, 0xbf, 0x7f, 0x1e, 0xc5, 0x73, 0xaf, 0xf4, 0x67, 0x1a, 0xee, - 0xd3, 0x44, 0x13, 0x7f, 0xd1, 0xec, 0xe3, 0x5d, 0xda, 0x68, 0xbe, 0x6f, - 0x0e, 0x68, 0x28, 0x80, 0x69, 0xed, 0x0a, 0x37, 0x76, 0x42, 0xaa, 0xff, - 0xe8, 0xea, 0x29, 0x9c, 0x9d, 0x60, 0xdc, 0xea, 0xc4, 0xdb, 0xd2, 0x30, - 0x0e, 0x94, 0xdf, 0xe0, 0x77, 0x6f, 0xa8, 0xde, 0x9d, 0x7f, 0xe9, 0xdf, - 0x7d, 0xbc, 0xf0, 0xbe, 0xc3, 0xaf, 0xff, 0xb3, 0xd0, 0x3e, 0xd6, 0x62, - 0x8a, 0x3c, 0x8e, 0xbf, 0xf6, 0x06, 0x25, 0x1d, 0xcf, 0xdc, 0xeb, 0xf9, - 0xe4, 0x09, 0x38, 0x4e, 0xbc, 0xcb, 0x2c, 0x95, 0x7e, 0xee, 0x35, 0xf8, - 0x53, 0x05, 0xfd, 0xff, 0xfe, 0x9b, 0x91, 0xb3, 0xe2, 0x8f, 0xf3, 0xec, - 0xda, 0xf9, 0x9b, 0xf8, 0xea, 0xf2, 0x29, 0x7e, 0x9b, 0x5f, 0xfe, 0x4e, - 0x27, 0x81, 0x9e, 0x75, 0xe0, 0x9d, 0x53, 0xaa, 0x28, 0x6a, 0x1a, 0xd3, - 0xbf, 0x3c, 0x18, 0x78, 0x78, 0x96, 0xff, 0xcb, 0x8d, 0xf4, 0x39, 0x3f, - 0xd9, 0x1d, 0x7f, 0xff, 0x93, 0xae, 0x3b, 0xcb, 0xec, 0xa0, 0x64, 0xeb, - 0xc0, 0x9d, 0x7f, 0xfb, 0x33, 0xa1, 0xec, 0x6b, 0x3a, 0x9f, 0x9d, 0x7f, - 0x94, 0xf9, 0x34, 0xa3, 0x9a, 0x3a, 0xa7, 0x4c, 0x82, 0x48, 0x21, 0x60, - 0x44, 0x8b, 0xf9, 0x5f, 0x25, 0xd8, 0xe1, 0xd7, 0xfb, 0xd0, 0x9d, 0x52, - 0x37, 0x3a, 0xff, 0xf6, 0xe3, 0xf1, 0xbd, 0x4f, 0xff, 0x8e, 0x48, 0xea, - 0x84, 0x58, 0x21, 0x7f, 0xd3, 0x3b, 0xe5, 0x7d, 0x4b, 0x61, 0xd7, 0xff, - 0xa2, 0x7f, 0xbd, 0x8d, 0xfd, 0x93, 0x88, 0x4e, 0xa7, 0x3f, 0x41, 0x27, - 0xbf, 0xd1, 0x83, 0xe5, 0x43, 0x2d, 0x3a, 0xff, 0x77, 0x36, 0x7c, 0xd4, - 0x9a, 0x75, 0x81, 0xa3, 0xed, 0xf1, 0xb5, 0xfe, 0x71, 0xf9, 0xf7, 0x9d, - 0x73, 0xaf, 0xd9, 0xc7, 0xdd, 0x93, 0xaf, 0xff, 0xf4, 0xf8, 0xc8, 0xe0, - 0x78, 0x80, 0x9c, 0x3d, 0x81, 0x9c, 0xea, 0x9d, 0x11, 0x5a, 0x28, 0xbc, - 0xcb, 0x2c, 0x95, 0x7f, 0xbe, 0xff, 0x03, 0x9b, 0xf8, 0xa6, 0x0b, 0xfb, - 0xff, 0xf9, 0x53, 0xf1, 0xbd, 0x40, 0x87, 0x19, 0xf9, 0xed, 0x64, 0xe7, - 0x57, 0x51, 0x54, 0x04, 0x5a, 0x44, 0xc4, 0x1e, 0x1d, 0xb5, 0x3b, 0x28, - 0x2e, 0x51, 0xde, 0x04, 0xd5, 0x25, 0x2f, 0x72, 0x37, 0xf5, 0xc3, 0xbb, - 0xb0, 0xa4, 0x18, 0x46, 0xe8, 0xa3, 0xd1, 0xe7, 0xdf, 0xfb, 0x10, 0x67, - 0x71, 0xf6, 0x2c, 0xeb, 0xff, 0x75, 0x19, 0x0f, 0x73, 0xdb, 0x78, 0x75, - 0xec, 0x1f, 0xce, 0xbe, 0xcf, 0x4d, 0x23, 0xaf, 0xfe, 0xda, 0x18, 0xda, - 0xd3, 0x8f, 0xdf, 0xf4, 0x75, 0x74, 0xfb, 0x5c, 0x8a, 0xff, 0xd9, 0xe8, - 0xe6, 0xbb, 0x03, 0xe3, 0xc4, 0x11, 0x7f, 0xa3, 0x38, 0xd7, 0x76, 0x9a, - 0x20, 0x86, 0x0f, 0x26, 0xfe, 0x7e, 0xf3, 0x88, 0xc9, 0xd7, 0xf2, 0xb8, - 0x59, 0x71, 0x91, 0xd4, 0x27, 0xba, 0x02, 0xdb, 0xff, 0xf4, 0x06, 0x69, - 0x20, 0xfa, 0x3f, 0x98, 0x52, 0x63, 0xa9, 0x45, 0x42, 0xbd, 0x84, 0x47, - 0xed, 0x43, 0x0a, 0xcd, 0x84, 0x37, 0xf7, 0x73, 0xde, 0x45, 0x9d, 0x7f, - 0x7b, 0xee, 0x75, 0xf7, 0x3a, 0xb7, 0x3d, 0xb1, 0x2c, 0xbf, 0xfd, 0xad, - 0x0b, 0xf9, 0xd7, 0xf6, 0x27, 0xc3, 0xaa, 0x0f, 0xb0, 0x04, 0x57, 0xf6, - 0x37, 0xee, 0xce, 0xe1, 0xd7, 0x42, 0x87, 0x5e, 0x0a, 0x09, 0xd7, 0x84, - 0x13, 0x9d, 0x7e, 0xeb, 0xcb, 0x04, 0xeb, 0xf9, 0x3c, 0x39, 0xd4, 0x3a, - 0xec, 0xef, 0xc3, 0xcf, 0x82, 0x5b, 0x9d, 0x9f, 0x88, 0xc9, 0xc1, 0x6e, - 0x8d, 0x79, 0xae, 0xa4, 0x9b, 0x26, 0x10, 0x8c, 0x3e, 0x6f, 0xff, 0xef, - 0x77, 0x35, 0xac, 0xc0, 0x72, 0x7c, 0x00, 0xf8, 0xeb, 0xfe, 0xec, 0x73, - 0xc3, 0x19, 0xb9, 0xd7, 0xff, 0xfc, 0x93, 0xc4, 0xb5, 0xce, 0x26, 0xf3, - 0x49, 0xf8, 0xbc, 0xdc, 0xeb, 0xdd, 0xc1, 0x0a, 0x28, 0x3a, 0x6f, 0x48, - 0x99, 0x6f, 0xa1, 0xf5, 0x7f, 0xe6, 0xf6, 0x33, 0x92, 0xd0, 0x16, 0x75, - 0xc9, 0xa3, 0xaf, 0xfb, 0x27, 0x7f, 0x7f, 0xf4, 0x64, 0x75, 0xfd, 0xf5, - 0x7a, 0x65, 0xf7, 0x3a, 0xa1, 0x1c, 0xf8, 0x50, 0xa1, 0xf7, 0x05, 0x7c, - 0x77, 0x7b, 0x99, 0xd3, 0xaf, 0x69, 0x16, 0x75, 0xa3, 0x86, 0xdb, 0xc3, - 0x77, 0xc9, 0x32, 0x32, 0x75, 0xff, 0xcb, 0x7d, 0xfe, 0xf9, 0x39, 0x00, - 0x54, 0x9d, 0x7f, 0xfe, 0x04, 0xe3, 0x19, 0xd6, 0x23, 0xd9, 0xd0, 0x70, - 0xeb, 0xef, 0x6b, 0xee, 0x82, 0x8c, 0x1c, 0x22, 0xfa, 0x95, 0x7e, 0xd2, - 0xf3, 0xda, 0x3a, 0xfc, 0xf2, 0x14, 0x83, 0xaf, 0xe8, 0x71, 0xf6, 0x09, - 0xd5, 0x24, 0xe9, 0xb2, 0x1c, 0xe8, 0x96, 0xb2, 0x71, 0x24, 0xbf, 0x9b, - 0xd4, 0xdb, 0x45, 0x0e, 0xbf, 0xfc, 0x9f, 0xc6, 0x97, 0x09, 0xce, 0x23, - 0x27, 0x5f, 0x2b, 0xf7, 0x27, 0x3a, 0xff, 0x40, 0x73, 0xc9, 0xd0, 0x1d, - 0x65, 0xc1, 0xeb, 0x04, 0x96, 0xff, 0xff, 0xcb, 0x71, 0xfe, 0x49, 0xa0, - 0x2f, 0xa9, 0x1e, 0xe8, 0x1d, 0x67, 0x5f, 0xff, 0x08, 0x3d, 0x24, 0xff, - 0xae, 0x9e, 0x75, 0x9d, 0x77, 0xc5, 0x73, 0xaf, 0xff, 0xce, 0x9e, 0x40, - 0xe0, 0x73, 0xc8, 0xb4, 0xe1, 0xd7, 0xb8, 0xfa, 0xc4, 0x5d, 0x71, 0x3b, - 0xa3, 0x77, 0x27, 0x9d, 0x36, 0x50, 0x46, 0x4b, 0x74, 0xa0, 0xeb, 0xff, - 0xd3, 0x87, 0xb1, 0xdc, 0xdf, 0xfc, 0xf6, 0x8e, 0xa7, 0x3e, 0x10, 0x0a, - 0xd0, 0x55, 0x88, 0xe1, 0x82, 0x42, 0x7d, 0xe3, 0x8c, 0x18, 0x4a, 0xdf, - 0xdc, 0x89, 0xd0, 0x7c, 0x75, 0xe0, 0xfd, 0x59, 0xd7, 0xe1, 0x80, 0xe4, - 0xc7, 0x5f, 0x68, 0x1c, 0x50, 0xeb, 0xf4, 0x77, 0xd1, 0x23, 0xaf, 0x82, - 0x0f, 0x6a, 0x0f, 0xbf, 0x72, 0x6f, 0xc8, 0xef, 0xdf, 0xe2, 0xe3, 0xa7, - 0x5e, 0x54, 0xf7, 0x0e, 0xa0, 0xa6, 0x8f, 0x85, 0x89, 0x08, 0xd1, 0x48, - 0x01, 0x3d, 0xee, 0x7d, 0xd1, 0xd7, 0x42, 0xb4, 0x3a, 0xff, 0xce, 0x2d, - 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x46, 0xe9, 0x4e, 0x75, 0x42, 0x26, 0x3f, - 0x1e, 0x00, 0xde, 0xc4, 0x8b, 0xff, 0xff, 0xdd, 0xc0, 0x71, 0x4e, 0xa6, - 0xf1, 0xe0, 0x74, 0x73, 0x7f, 0x01, 0xf4, 0x75, 0xff, 0xd9, 0xbf, 0xdf, - 0x20, 0x82, 0x59, 0xa3, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x33, - 0x8b, 0x86, 0x06, 0x78, 0xe0, 0x70, 0x73, 0xda, 0x46, 0xe0, 0xfd, 0x9f, - 0x39, 0x1a, 0x17, 0x53, 0x58, 0x9f, 0xfe, 0x0f, 0xc5, 0xc3, 0x03, 0x3c, - 0x70, 0xea, 0x84, 0xd3, 0xf1, 0x16, 0xff, 0xef, 0x38, 0xcf, 0xbc, 0x86, - 0x33, 0x47, 0x5f, 0xfb, 0xee, 0x75, 0xd6, 0xc3, 0x2c, 0xb2, 0x75, 0xff, - 0xfb, 0x1b, 0xd8, 0x10, 0x8a, 0x4f, 0x82, 0x8a, 0x1d, 0x73, 0xbc, 0xe8, - 0x96, 0x92, 0x25, 0xff, 0xfd, 0x30, 0xc7, 0xfa, 0x6f, 0x53, 0x93, 0x0c, - 0x7f, 0xa3, 0xaf, 0xfe, 0xf7, 0x53, 0x67, 0x5e, 0x5c, 0x85, 0x0e, 0xbf, - 0x81, 0xe4, 0x00, 0xa8, 0x75, 0xfd, 0x8c, 0xe0, 0x83, 0xf3, 0xaf, 0xd2, - 0xcf, 0x47, 0xe7, 0x5d, 0x0b, 0x9c, 0xf5, 0x37, 0x2d, 0xbf, 0xff, 0xfb, - 0xf5, 0xbc, 0xba, 0xe9, 0xe4, 0x0e, 0x07, 0x3c, 0x8b, 0x4e, 0x1d, 0x5a, - 0x44, 0xf0, 0x0b, 0xef, 0xd3, 0xae, 0x03, 0x07, 0x54, 0x97, 0x3f, 0x43, - 0x1e, 0x46, 0xe4, 0x53, 0x43, 0x67, 0x85, 0xdd, 0x5d, 0xd2, 0x37, 0xa3, - 0x1f, 0xfa, 0x47, 0x7f, 0xa3, 0x5a, 0x89, 0xf1, 0x93, 0xaf, 0xf7, 0x71, - 0x79, 0xd0, 0x09, 0xd4, 0x13, 0xe4, 0xf1, 0x9d, 0x62, 0x63, 0x8f, 0x0f, - 0xab, 0xcc, 0xb2, 0xc9, 0x57, 0xfd, 0x9f, 0xbf, 0x33, 0x66, 0x04, 0xa6, - 0x0b, 0xfb, 0x99, 0x64, 0xab, 0xcc, 0xb2, 0xc9, 0x57, 0xf3, 0xce, 0x1e, - 0xc6, 0x8a, 0x60, 0xbf, 0xa1, 0x45, 0xeb, 0x29, 0x3b, 0x66, 0xf7, 0xe6, - 0xa0, 0x7e, 0xac, 0xa6, 0x0d, 0x9d, 0xe6, 0x59, 0x64, 0xab, 0xda, 0x8e, - 0x14, 0xc1, 0x7f, 0x7c, 0xe3, 0xbf, 0x8e, 0xb7, 0xe8, 0x8a, 0x5f, 0x2c, - 0xb2, 0x57, 0x7f, 0x04, 0x62, 0x4e, 0xd3, 0xaf, 0xda, 0x04, 0xfb, 0x62, - 0x75, 0xf8, 0x29, 0xb2, 0x02, 0x75, 0xf6, 0x0e, 0x2b, 0x9d, 0x5c, 0x3c, - 0xa5, 0x94, 0x52, 0x22, 0x5f, 0xeb, 0xad, 0xff, 0xdd, 0x79, 0x0b, 0xa9, - 0x30, 0xa4, 0xc7, 0x5f, 0xfd, 0x9c, 0x9e, 0x37, 0xd2, 0x0e, 0x7e, 0x75, - 0xfd, 0xdc, 0xd9, 0x9e, 0xd1, 0xd4, 0xd4, 0x5b, 0x7e, 0x89, 0xe4, 0x4a, - 0xe2, 0x79, 0xbd, 0x86, 0x10, 0xc3, 0x6a, 0xe9, 0xfc, 0x75, 0x42, 0xa5, - 0x5c, 0x94, 0x08, 0x27, 0x57, 0xb7, 0x56, 0xaa, 0xc1, 0xd7, 0xff, 0xb1, - 0x5d, 0xc7, 0xfc, 0x6c, 0x76, 0x16, 0x75, 0xf6, 0xba, 0x93, 0x15, 0x7f, - 0xcf, 0xbf, 0xb2, 0x60, 0x71, 0x43, 0xac, 0xd4, 0x3d, 0xd0, 0x11, 0x5f, - 0xe1, 0xcd, 0xe5, 0xa4, 0x50, 0xeb, 0xe7, 0x7e, 0x28, 0x75, 0x7c, 0x3d, - 0x49, 0xcc, 0xef, 0xfb, 0x31, 0xbf, 0xc6, 0x6f, 0x23, 0xaf, 0xa1, 0xd7, - 0xb0, 0xab, 0xff, 0xba, 0x8f, 0xff, 0xf1, 0xfc, 0x77, 0x47, 0x5f, 0xdd, - 0xc5, 0xad, 0xe4, 0x75, 0xe6, 0x59, 0x64, 0xab, 0xfc, 0x3e, 0xea, 0x40, - 0xce, 0x53, 0x05, 0xfd, 0xe8, 0xff, 0x24, 0x88, 0xcc, 0x4b, 0xaf, 0x26, - 0x09, 0xf6, 0x1a, 0x36, 0xc6, 0xa6, 0xa2, 0xb8, 0xc9, 0xaf, 0xf4, 0x7d, - 0xe7, 0x13, 0xda, 0x3a, 0xa1, 0x5a, 0xdc, 0x8a, 0x37, 0x85, 0x3a, 0x3d, - 0xcc, 0x4b, 0xd8, 0xe2, 0x44, 0xbe, 0xfd, 0xfe, 0x27, 0x54, 0x3a, 0xff, - 0xfb, 0x1b, 0x02, 0xfe, 0xd0, 0x40, 0xfc, 0x91, 0xd5, 0xb9, 0xfa, 0xac, - 0xa2, 0xf3, 0x63, 0x47, 0x5f, 0xfd, 0xf6, 0x59, 0xd7, 0xea, 0x73, 0x90, - 0x75, 0x61, 0xef, 0xfe, 0x37, 0x7e, 0x8f, 0x6b, 0x66, 0x1d, 0x7e, 0x07, - 0x14, 0xea, 0x1d, 0x50, 0x8f, 0x41, 0x84, 0x17, 0x88, 0xb6, 0xca, 0x2f, - 0xff, 0x93, 0x66, 0x08, 0x45, 0xd9, 0xc1, 0x75, 0x0e, 0xbf, 0xff, 0xe0, - 0xf5, 0x19, 0xcd, 0xa4, 0x5b, 0xfb, 0x40, 0x96, 0x6f, 0xe3, 0xab, 0x11, - 0x70, 0xe9, 0xd7, 0xfd, 0x33, 0x7a, 0x8b, 0x8e, 0x28, 0x75, 0xfa, 0x7f, - 0x80, 0x89, 0x8e, 0xb4, 0x8e, 0xbd, 0xf4, 0x66, 0x3a, 0xa4, 0x6b, 0xbf, - 0x10, 0xac, 0x45, 0xab, 0x9d, 0x69, 0x66, 0xa1, 0xd9, 0xbc, 0x4f, 0x28, - 0xf6, 0x52, 0x91, 0x43, 0x2a, 0x97, 0x29, 0x48, 0xca, 0x42, 0xd9, 0xa7, - 0x69, 0x29, 0x5a, 0x69, 0x50, 0x9c, 0x94, 0x90, 0xb9, 0x44, 0xbd, 0x96, - 0xbc, 0xf1, 0xcf, 0xff, 0x0e, 0x51, 0x9e, 0x58, 0xd4, 0xe1, 0x87, 0xa5, - 0xc8, 0x82, 0x3d, 0x96, 0x61, 0xf7, 0xf6, 0x1a, 0xd7, 0xb6, 0x40, 0x9d, - 0x7f, 0xfd, 0x82, 0xc7, 0x94, 0x4d, 0xf5, 0xdc, 0xfd, 0xce, 0xa9, 0x1f, - 0x68, 0x47, 0x2f, 0xf3, 0x8b, 0x73, 0xdd, 0x43, 0xab, 0x73, 0xd2, 0x59, - 0x15, 0x95, 0xa1, 0xd7, 0xfe, 0x71, 0xff, 0xe0, 0x40, 0xfc, 0x91, 0xd7, - 0xc8, 0x33, 0xc1, 0xd4, 0xae, 0x7c, 0x1c, 0x40, 0xa5, 0x5e, 0x89, 0xbc, - 0x76, 0xbd, 0x03, 0x39, 0xd7, 0xc9, 0xd4, 0x59, 0xd6, 0xea, 0x1b, 0xb9, - 0x86, 0xef, 0xe8, 0x6c, 0x6b, 0xc8, 0x75, 0xff, 0x47, 0xba, 0xff, 0xbe, - 0xfa, 0x3a, 0x82, 0x7c, 0x82, 0x57, 0x7f, 0xee, 0x7f, 0xf3, 0xa8, 0xd0, - 0x73, 0xf3, 0xaf, 0x4c, 0x0e, 0x1d, 0x7f, 0xe7, 0x4e, 0x66, 0xec, 0x32, - 0xcb, 0x27, 0x54, 0x22, 0x89, 0xd0, 0xf4, 0x3b, 0x7f, 0xfc, 0x31, 0x2f, - 0x9f, 0x7c, 0x82, 0x09, 0x66, 0x8e, 0xac, 0x4f, 0x35, 0xb0, 0x8b, 0xec, - 0x30, 0xff, 0x2e, 0xbf, 0xd0, 0x32, 0x1c, 0xcf, 0xce, 0xbf, 0xb3, 0x9a, - 0x18, 0x9c, 0xeb, 0xf9, 0xfd, 0xd7, 0x1f, 0xce, 0xbf, 0xf3, 0xfb, 0x26, - 0x78, 0x18, 0x98, 0xeb, 0x27, 0x0f, 0xa3, 0xa5, 0x97, 0x35, 0xa6, 0x8c, - 0x12, 0xa4, 0x8d, 0xe6, 0xc2, 0x53, 0xf2, 0x7b, 0xb0, 0x4e, 0xbf, 0xfd, - 0xe8, 0x16, 0xe7, 0xba, 0x9c, 0xfd, 0xa7, 0x50, 0x4f, 0x77, 0x05, 0x2f, - 0xf4, 0x2f, 0x5a, 0x71, 0x9c, 0xeb, 0xed, 0x60, 0xf8, 0xeb, 0xdb, 0x51, - 0xc3, 0xa9, 0xcd, 0xf0, 0x08, 0x2f, 0x79, 0xd5, 0xce, 0xbf, 0xde, 0xea, - 0x31, 0xfb, 0xa1, 0xd4, 0x14, 0xc0, 0xba, 0x42, 0x2e, 0x1e, 0x20, 0x00, - 0xf5, 0xf7, 0x51, 0xe4, 0x75, 0xe0, 0xbc, 0x8e, 0xb8, 0x1f, 0xc1, 0xbb, - 0xc2, 0x0b, 0xfe, 0x6e, 0x7a, 0x36, 0x20, 0xfe, 0x75, 0xff, 0xfc, 0x08, - 0xf6, 0xb0, 0x7e, 0x72, 0x10, 0x22, 0xf2, 0x3a, 0xfc, 0xde, 0xee, 0xea, - 0xe7, 0x5f, 0xfc, 0x81, 0x10, 0x7b, 0x50, 0x31, 0xa3, 0xa9, 0x11, 0xfc, - 0x27, 0x20, 0x59, 0xd8, 0x57, 0x7f, 0xf7, 0xef, 0xcc, 0xd9, 0x81, 0xe0, - 0xb2, 0x75, 0xff, 0xfc, 0x39, 0xa0, 0x7c, 0xce, 0xb8, 0xe4, 0xd2, 0x8d, - 0xce, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x40, 0xd7, 0xf3, 0xcf, 0xfb, 0x88, - 0x49, 0x58, 0x3e, 0xf6, 0x68, 0x18, 0x7d, 0xdb, 0x66, 0x77, 0xba, 0xf2, - 0xf8, 0x8f, 0xe1, 0x86, 0x4d, 0x2d, 0x37, 0xef, 0x46, 0x89, 0x7f, 0xc3, - 0xff, 0x92, 0x75, 0xc3, 0x4e, 0xbf, 0x05, 0x5b, 0x70, 0xab, 0x67, 0x54, - 0x2a, 0x4f, 0xc8, 0xee, 0xd0, 0xa9, 0xce, 0x6f, 0xf6, 0x6f, 0xe0, 0xe6, - 0x28, 0x75, 0xfd, 0x9e, 0x81, 0x4f, 0xce, 0xbc, 0xfc, 0x9c, 0xd1, 0x82, - 0xdf, 0xf9, 0xf9, 0x83, 0xfe, 0xbd, 0xad, 0xce, 0xbf, 0xff, 0xff, 0xb3, - 0xdd, 0x71, 0x53, 0xe6, 0xb8, 0xef, 0xed, 0x98, 0x1f, 0x98, 0xb7, 0x1d, - 0xe4, 0x78, 0x82, 0xef, 0xfc, 0xee, 0xa3, 0x5c, 0x3f, 0x14, 0x64, 0xf1, - 0x05, 0xdf, 0xfd, 0xd4, 0xea, 0x40, 0xfb, 0xe2, 0x8c, 0x9e, 0x20, 0xbb, - 0xfd, 0x08, 0x3e, 0xf8, 0xa3, 0x27, 0x88, 0x2e, 0xfe, 0x5e, 0x07, 0xe2, - 0x8c, 0x9e, 0x20, 0xbb, 0xff, 0xfe, 0x71, 0x14, 0x5f, 0xcd, 0x37, 0xa9, - 0xc4, 0x52, 0x7c, 0x64, 0xf1, 0x05, 0xdd, 0xbf, 0xc0, 0xa7, 0x2e, 0xd4, - 0xfe, 0x29, 0xba, 0x10, 0x9f, 0x54, 0x2a, 0xc8, 0xe9, 0xf8, 0xca, 0x31, - 0xbf, 0xc9, 0x0a, 0x6b, 0xda, 0xdc, 0xeb, 0xe7, 0xe7, 0xee, 0x75, 0xff, - 0xdd, 0x4e, 0xa4, 0x0f, 0xbe, 0x28, 0xc9, 0xe2, 0x0b, 0xbf, 0xe9, 0xb4, - 0xd4, 0x9f, 0xe2, 0x8c, 0x9e, 0x20, 0xbb, 0xf7, 0xb5, 0x0b, 0xf8, 0xd4, - 0x4f, 0xfd, 0x53, 0xbf, 0xfd, 0xf1, 0xbd, 0x46, 0xc7, 0xb5, 0xf1, 0x46, - 0x4f, 0x10, 0x5d, 0xff, 0xff, 0xc2, 0x28, 0xbf, 0x80, 0xcf, 0x9a, 0x6f, - 0x53, 0x88, 0xa4, 0xf8, 0xc9, 0xe2, 0x0b, 0xac, 0x4c, 0x93, 0x74, 0x47, - 0x5d, 0xbf, 0xee, 0xa7, 0x11, 0x49, 0xf1, 0x93, 0xc4, 0x17, 0x7f, 0xfc, - 0xef, 0xbc, 0xb5, 0xd4, 0x08, 0x63, 0x90, 0x55, 0xff, 0xb2, 0x52, 0x06, - 0xb8, 0x33, 0xed, 0x9e, 0x20, 0xba, 0x6a, 0x39, 0x38, 0x8f, 0xa4, 0xeb, - 0xff, 0x35, 0x39, 0xe7, 0xff, 0x5f, 0x19, 0x3c, 0x41, 0x77, 0xf7, 0x53, - 0xbd, 0x4f, 0xcd, 0x00, 0x5d, 0xfb, 0x3f, 0xf8, 0xa3, 0x27, 0x88, 0x2e, - 0xec, 0xf3, 0x4f, 0xcf, 0xa7, 0x55, 0xba, 0x3b, 0xf5, 0x0c, 0x2b, 0xf9, - 0x78, 0x1f, 0x8a, 0x32, 0x78, 0x82, 0xef, 0xfc, 0xde, 0xa7, 0x11, 0x49, - 0xf1, 0x93, 0xc4, 0x17, 0x76, 0x7c, 0x74, 0x45, 0xe8, 0xfa, 0xff, 0x01, - 0x16, 0xe3, 0xbc, 0x8f, 0x10, 0x5d, 0xff, 0xb1, 0x36, 0x60, 0xe0, 0x5e, - 0x47, 0x88, 0x2d, 0x66, 0xfe, 0x82, 0xbb, 0xfb, 0xc3, 0x7f, 0xcd, 0x06, - 0x3e, 0x4d, 0x46, 0x29, 0xe8, 0xc7, 0xc1, 0x0b, 0x46, 0x5b, 0xae, 0xfe, - 0x0d, 0x10, 0x5b, 0x08, 0x8c, 0xb9, 0xda, 0x75, 0xb4, 0xd6, 0x4e, 0x2f, - 0xf4, 0x97, 0xaf, 0x1b, 0x5d, 0x2d, 0xa3, 0xaf, 0x44, 0xb6, 0x8e, 0xa8, - 0x36, 0xe2, 0x33, 0x53, 0xb2, 0xaf, 0x42, 0x67, 0xfd, 0x27, 0xc0, 0x5e, - 0xef, 0xfe, 0xc9, 0x0e, 0x7b, 0xa9, 0x9b, 0xf8, 0xeb, 0xf4, 0x7b, 0x5d, - 0x43, 0xaf, 0xfd, 0xa9, 0xa4, 0x00, 0xcd, 0x20, 0x04, 0xea, 0x91, 0xf4, - 0x78, 0x9a, 0xff, 0xe8, 0xde, 0x5f, 0x57, 0xaf, 0x46, 0xec, 0x9d, 0x7e, - 0x96, 0xd6, 0xd0, 0x27, 0x3a, 0xdd, 0x43, 0xf8, 0x74, 0x9b, 0xf7, 0x23, - 0x79, 0x68, 0xea, 0x91, 0xe7, 0x70, 0x9a, 0xff, 0xef, 0xc1, 0xad, 0xbc, - 0xe7, 0xeb, 0x4d, 0x1d, 0x7f, 0xbf, 0x07, 0x86, 0x3d, 0xa3, 0xab, 0xf3, - 0xfc, 0xd2, 0x4d, 0x42, 0x75, 0x39, 0x0e, 0x87, 0x84, 0xf5, 0xfc, 0xf2, - 0x8d, 0x8f, 0xd3, 0xaf, 0xb7, 0xd4, 0x6e, 0x75, 0xe5, 0xc4, 0x8e, 0xbf, - 0x60, 0x7a, 0x06, 0x4e, 0xaf, 0x87, 0xcc, 0xe4, 0x62, 0x37, 0x78, 0x2f, - 0xe3, 0xab, 0x87, 0x94, 0xe5, 0xf7, 0x93, 0x6f, 0x0e, 0xbc, 0xfc, 0xfc, - 0xeb, 0x6f, 0x06, 0xe7, 0xc3, 0xb7, 0xcc, 0xe7, 0x5c, 0xeb, 0xe5, 0x38, - 0x8c, 0x9d, 0x7e, 0x9d, 0xfb, 0x0a, 0xe7, 0x52, 0xb0, 0x79, 0xb8, 0x47, - 0x50, 0x9f, 0x92, 0x43, 0x75, 0xd6, 0xbf, 0x27, 0x16, 0xeb, 0xff, 0xc2, - 0x31, 0x3a, 0xfa, 0x9c, 0xe3, 0xc8, 0xeb, 0xfd, 0x3c, 0xf0, 0x3b, 0xe7, - 0x8e, 0xac, 0x3f, 0xc4, 0x48, 0xbf, 0xfb, 0x82, 0x0d, 0xfc, 0x39, 0x3b, - 0x89, 0xd7, 0x9f, 0x93, 0x9d, 0x77, 0xf0, 0x75, 0xf2, 0x42, 0xf0, 0xea, - 0x3a, 0xfe, 0x75, 0x3d, 0x1c, 0xfc, 0xea, 0x09, 0xb8, 0x10, 0xab, 0xff, - 0xfd, 0x08, 0x11, 0x80, 0x37, 0xd8, 0xd0, 0xc3, 0x7e, 0xac, 0xeb, 0xbf, - 0x83, 0xae, 0x85, 0x0e, 0xbf, 0xec, 0xf6, 0xa1, 0x7f, 0x72, 0x63, 0xaf, - 0xf6, 0xb3, 0xa9, 0xa0, 0x4e, 0x75, 0xcc, 0xb2, 0x55, 0xff, 0x0e, 0x6c, - 0x79, 0x69, 0x02, 0x75, 0x35, 0x3f, 0x24, 0x1c, 0xe0, 0xb2, 0xd5, 0xfa, - 0x41, 0xfb, 0x02, 0xa4, 0x58, 0x45, 0xb4, 0x74, 0xc9, 0x9f, 0xd1, 0x8b, - 0xcc, 0xb2, 0xc9, 0x56, 0x59, 0x4c, 0x17, 0xf7, 0xd3, 0x3b, 0xf0, 0xa6, - 0x11, 0xbd, 0xf6, 0x17, 0xd5, 0x3a, 0xb5, 0xb7, 0x96, 0x27, 0x7f, 0x7a, - 0x33, 0xb9, 0x39, 0xd7, 0x62, 0xce, 0xad, 0xcf, 0x07, 0x45, 0x95, 0x0d, - 0xf3, 0x8c, 0xa1, 0x7d, 0x92, 0x8c, 0x14, 0x48, 0xde, 0x30, 0xe4, 0x8e, - 0x57, 0x90, 0x85, 0xec, 0xb7, 0x97, 0xa5, 0x7f, 0x7e, 0x96, 0x32, 0x94, - 0xf5, 0x28, 0xab, 0xd0, 0xc9, 0x04, 0xb7, 0xbd, 0x8d, 0xb7, 0xf6, 0x7f, - 0xfa, 0x72, 0x47, 0x5c, 0xdc, 0x3a, 0x82, 0x78, 0x6e, 0x5d, 0x76, 0x32, - 0x75, 0xd1, 0xe3, 0xaa, 0x73, 0x56, 0xd1, 0x6b, 0x2c, 0xea, 0xc3, 0x65, - 0xe2, 0x2b, 0xfd, 0x24, 0x1c, 0x58, 0x3a, 0x75, 0xff, 0xb3, 0xda, 0xea, - 0x2d, 0xf3, 0x87, 0x54, 0x1f, 0x68, 0x98, 0xdf, 0x7c, 0xf4, 0x6c, 0x3a, - 0xfb, 0x17, 0x9e, 0x3a, 0xf7, 0x9d, 0x43, 0xaf, 0xff, 0xfe, 0x6b, 0xcc, - 0x09, 0x01, 0xbf, 0x3a, 0x9e, 0xf4, 0x6f, 0x13, 0xc6, 0x8e, 0xbf, 0xff, - 0xe5, 0x71, 0x77, 0xd9, 0x12, 0xec, 0x72, 0x78, 0xf6, 0x9e, 0x47, 0x5e, - 0x4d, 0xe6, 0x3a, 0xfd, 0x99, 0x38, 0x34, 0x75, 0xf7, 0x05, 0x3f, 0x3a, - 0xf9, 0x1a, 0xfc, 0x3a, 0xe8, 0xfc, 0xeb, 0xe0, 0x4e, 0x06, 0x3a, 0x6d, - 0xbe, 0x90, 0x52, 0x22, 0x53, 0xaa, 0xf7, 0xfd, 0xd7, 0xd7, 0x52, 0x77, - 0x13, 0xaf, 0x9e, 0x7f, 0xb2, 0x3a, 0x95, 0x4a, 0xf0, 0x21, 0xfa, 0x50, - 0x8d, 0xc2, 0x0d, 0xc9, 0x50, 0x83, 0x83, 0x8e, 0xed, 0xfb, 0x4e, 0x87, - 0x7d, 0x0b, 0xbf, 0xa4, 0x5b, 0x46, 0xf7, 0xf0, 0x80, 0x2b, 0x79, 0x1d, - 0x79, 0x27, 0x01, 0xd7, 0xe8, 0xfd, 0x37, 0xc3, 0xae, 0x5e, 0xc3, 0xac, - 0x18, 0x37, 0xe2, 0x4f, 0x7f, 0xfa, 0x43, 0x1f, 0x16, 0x30, 0xa7, 0x92, - 0x73, 0xaf, 0xce, 0xbc, 0xea, 0xce, 0xad, 0xcf, 0xc7, 0xc9, 0x77, 0xbd, - 0xc8, 0x3a, 0xff, 0x6b, 0xdb, 0x30, 0x70, 0x27, 0x54, 0x27, 0x1d, 0x22, - 0xcc, 0x5b, 0x48, 0x4b, 0x2c, 0x8d, 0xc6, 0xef, 0x3f, 0xcf, 0xa7, 0x5f, - 0x2d, 0x70, 0xb3, 0xaf, 0xff, 0x86, 0x5f, 0x30, 0x29, 0xad, 0xfc, 0x07, - 0xd1, 0xd7, 0xfb, 0xe8, 0xbf, 0xa5, 0x0a, 0x1d, 0x7d, 0x99, 0xbc, 0x8e, - 0xbd, 0xa4, 0x98, 0xeb, 0x28, 0x26, 0xf7, 0x44, 0x37, 0xff, 0x3c, 0xe3, - 0x1b, 0xa0, 0x46, 0x27, 0x3a, 0xb8, 0x7d, 0x42, 0x4f, 0x7e, 0xf9, 0xd8, - 0xe4, 0x8e, 0xaf, 0x89, 0xdb, 0x40, 0xfe, 0x10, 0xb5, 0x45, 0xe1, 0xb6, - 0xc9, 0x0d, 0xe5, 0xea, 0x0e, 0xbf, 0xa7, 0x9a, 0x4a, 0xae, 0x4e, 0x75, - 0xf2, 0xf1, 0xfa, 0x75, 0xd2, 0x9c, 0xeb, 0xdd, 0x0a, 0x1d, 0x7e, 0xee, - 0x24, 0xb4, 0x75, 0xff, 0xf7, 0x63, 0xeb, 0x1e, 0x17, 0xff, 0x5a, 0x8f, - 0xca, 0xbf, 0x71, 0xae, 0xed, 0x3c, 0x40, 0x97, 0xb5, 0x1b, 0x9d, 0x6f, - 0xf0, 0xf3, 0xf7, 0x33, 0xbd, 0xe4, 0x9c, 0xeb, 0xd3, 0xb8, 0x9d, 0x52, - 0x4c, 0xa0, 0x24, 0xdc, 0x85, 0x12, 0xca, 0x7c, 0x39, 0x7f, 0x0b, 0x5d, - 0x4e, 0xa1, 0xd7, 0x6d, 0x48, 0xeb, 0xef, 0x4e, 0xe2, 0x75, 0xe1, 0x75, - 0x0e, 0xbc, 0xa2, 0x78, 0xeb, 0xda, 0x7f, 0x1d, 0x4a, 0x1b, 0x7d, 0xc7, - 0x2e, 0xf9, 0xd3, 0xaf, 0xe5, 0xf9, 0x02, 0x08, 0x3a, 0xf2, 0xfc, 0xd3, - 0xad, 0xe8, 0x3c, 0x8c, 0x2c, 0xa9, 0xd3, 0x35, 0xc1, 0x96, 0x90, 0xf5, - 0x4b, 0xf2, 0x31, 0x60, 0xbb, 0x80, 0x3a, 0xff, 0x0b, 0xb3, 0xad, 0x47, - 0xe7, 0x5e, 0xdb, 0x75, 0x0e, 0xbf, 0xe8, 0x5c, 0xb2, 0x7c, 0x02, 0xa4, - 0xeb, 0xe7, 0xf2, 0xa6, 0x73, 0xab, 0x11, 0x02, 0x83, 0xee, 0x79, 0x79, - 0x96, 0x59, 0x3d, 0x5f, 0x57, 0x9c, 0x42, 0x5a, 0xbe, 0xac, 0x1a, 0xcb, - 0xf6, 0x48, 0x10, 0xa1, 0xd5, 0x09, 0xc1, 0x84, 0x5b, 0x90, 0xb4, 0xfd, - 0x67, 0xc7, 0x37, 0xff, 0xec, 0x14, 0x51, 0x8d, 0x7b, 0xa0, 0x79, 0x4a, - 0x0e, 0xa9, 0xd1, 0x4a, 0xa2, 0x85, 0xf6, 0x05, 0xe4, 0x75, 0xf9, 0xc4, - 0x51, 0x67, 0x5f, 0xf7, 0x53, 0x98, 0x8b, 0x85, 0x73, 0xaf, 0xc8, 0xb7, - 0x1c, 0x3a, 0xbe, 0x2f, 0x60, 0xab, 0x23, 0x70, 0x6b, 0x22, 0x00, 0x8b, - 0xe4, 0x68, 0x6a, 0x28, 0x24, 0x6c, 0x2f, 0x2a, 0x03, 0xf2, 0x51, 0x20, - 0x01, 0x26, 0xd9, 0xcd, 0xf9, 0x3d, 0x1e, 0xd1, 0x57, 0xcd, 0x8f, 0x68, - 0xab, 0x99, 0x64, 0xaa, 0x91, 0xef, 0xe1, 0x33, 0x24, 0x37, 0x63, 0x25, - 0x30, 0x6b, 0xef, 0xff, 0xbd, 0x0d, 0xcc, 0x1f, 0x75, 0x20, 0x67, 0x3a, - 0x8e, 0xac, 0x3d, 0x6d, 0x26, 0x57, 0xe8, 0x9e, 0x65, 0xf6, 0xff, 0xff, - 0x46, 0xc4, 0x1f, 0xfe, 0x7b, 0x58, 0xde, 0xb8, 0xfb, 0x47, 0x5f, 0xa5, - 0xd0, 0x47, 0x0e, 0xbf, 0xf9, 0xd7, 0xc8, 0xd8, 0x9b, 0x04, 0x1a, 0x3a, - 0xb7, 0x3e, 0xde, 0x93, 0xdf, 0xb0, 0x0b, 0x8d, 0x1d, 0x47, 0x5d, 0x93, - 0x70, 0xd8, 0x68, 0x9a, 0xff, 0x90, 0x0a, 0x9e, 0xc7, 0xd1, 0x9c, 0xeb, - 0xfe, 0x89, 0xe3, 0x7f, 0x0e, 0x4e, 0x75, 0x62, 0x29, 0x1a, 0x5a, 0x87, - 0xd7, 0xe7, 0x58, 0xc6, 0xe7, 0x54, 0xc9, 0xa5, 0xf2, 0x1e, 0xfd, 0x2e, - 0xbe, 0xce, 0xe4, 0xe7, 0x5e, 0x93, 0xf0, 0xeb, 0xf4, 0xb3, 0xd8, 0x12, - 0xaf, 0xa0, 0x46, 0x0e, 0xa9, 0x8f, 0x7f, 0xc3, 0x7f, 0x49, 0xaf, 0xbf, - 0xd2, 0xf8, 0x75, 0x28, 0x8d, 0x54, 0x84, 0x07, 0x8c, 0xaf, 0xf8, 0x73, - 0xb9, 0xf3, 0xb9, 0x39, 0xd7, 0xf0, 0x15, 0x29, 0xce, 0x61, 0xd7, 0xde, - 0x53, 0x3a, 0x75, 0xb4, 0x75, 0xc9, 0xf9, 0xd7, 0x75, 0x0e, 0xb8, 0x1a, - 0xf8, 0x6a, 0xe6, 0x16, 0xa7, 0x3e, 0xbf, 0xce, 0xee, 0xfe, 0x0e, 0xbb, - 0xf8, 0x3a, 0xfc, 0x09, 0x60, 0xb0, 0x86, 0xb3, 0xf1, 0x6a, 0x84, 0xc6, - 0x7f, 0x84, 0x68, 0xa7, 0x5f, 0xff, 0x60, 0xbe, 0xfa, 0x51, 0x47, 0xf8, - 0xd5, 0xfe, 0x75, 0xff, 0xde, 0xee, 0x2f, 0xec, 0x7f, 0x9b, 0xf8, 0xeb, - 0xfd, 0xbb, 0x53, 0x9f, 0x60, 0x27, 0x5f, 0x7e, 0xb7, 0x97, 0xc4, 0x68, - 0x69, 0x53, 0xc8, 0xf7, 0xf7, 0xeb, 0xfb, 0xaf, 0xb3, 0x9d, 0x76, 0x6e, - 0x75, 0x6e, 0x79, 0x5b, 0x66, 0x97, 0xdf, 0xf1, 0x38, 0x75, 0x42, 0x37, - 0x1e, 0x12, 0x8c, 0x93, 0x5f, 0x68, 0x1b, 0xf8, 0xeb, 0xb1, 0x93, 0xaf, - 0xfa, 0x37, 0xcf, 0xe3, 0x66, 0x4e, 0x75, 0x70, 0xf4, 0x7f, 0x16, 0xbf, - 0xf4, 0xd1, 0x3e, 0xb9, 0x8d, 0x89, 0xce, 0xbf, 0xb1, 0x78, 0x14, 0x64, - 0xeb, 0x97, 0x07, 0x52, 0xcf, 0x05, 0xcb, 0x2f, 0xe1, 0xc9, 0xba, 0x9e, - 0x3a, 0xfb, 0x33, 0xba, 0x3a, 0xb1, 0x1d, 0xcf, 0x08, 0x1f, 0x10, 0xed, - 0x16, 0x5e, 0x65, 0x96, 0x4a, 0xbf, 0x62, 0x82, 0x0d, 0x14, 0xc1, 0x7f, - 0x7e, 0xc6, 0x19, 0x65, 0x93, 0xaa, 0x0f, 0x8b, 0xc6, 0xf7, 0xfd, 0xae, - 0x40, 0x3c, 0x29, 0xb0, 0xeb, 0xff, 0x0e, 0x69, 0xbd, 0x46, 0xc0, 0x9d, - 0x7f, 0xff, 0x94, 0x65, 0xf8, 0xa3, 0x1a, 0xc9, 0x08, 0x1f, 0x58, 0x27, - 0x54, 0x23, 0x5b, 0x0e, 0x50, 0xee, 0xf9, 0x97, 0x19, 0x1d, 0x7f, 0xde, - 0x8d, 0xff, 0x7e, 0xf5, 0x0e, 0xb7, 0x4e, 0xac, 0x3c, 0x96, 0x9c, 0xde, - 0x65, 0x96, 0x4a, 0xbf, 0x91, 0xd4, 0xea, 0x78, 0xa6, 0x0b, 0xfb, 0xef, - 0x69, 0xf8, 0x75, 0xee, 0xc0, 0x4e, 0xa4, 0x37, 0x8e, 0x43, 0x7e, 0xcf, - 0xf3, 0x26, 0x3a, 0xda, 0xf8, 0x8f, 0xee, 0x20, 0x75, 0xe0, 0x47, 0xee, - 0x04, 0x82, 0x9d, 0x66, 0x46, 0xd1, 0x7e, 0x54, 0xf6, 0x27, 0x01, 0xd5, - 0xd5, 0x47, 0x43, 0x1e, 0xc8, 0x0d, 0x6f, 0x46, 0xc8, 0x3a, 0x90, 0xf4, - 0xc4, 0xde, 0xf0, 0xc6, 0xc3, 0xae, 0x54, 0xa1, 0xd7, 0x27, 0x4e, 0xb3, - 0xce, 0x6b, 0xb8, 0x33, 0x7d, 0xed, 0x01, 0x5c, 0xeb, 0xfd, 0x03, 0x21, - 0x48, 0xdc, 0xea, 0x86, 0x6e, 0x5c, 0x89, 0x72, 0x50, 0xda, 0x91, 0x86, - 0x34, 0xd5, 0x0e, 0x79, 0x1a, 0x4f, 0x63, 0xe1, 0x73, 0x4f, 0xdd, 0x06, - 0x31, 0x1d, 0x43, 0x13, 0xd2, 0xe1, 0x36, 0x10, 0x6d, 0xa5, 0x7d, 0x27, - 0xda, 0x25, 0xb9, 0x58, 0x43, 0xaf, 0xfd, 0x13, 0x7b, 0x6b, 0x51, 0x30, - 0x38, 0x75, 0xff, 0xd8, 0x9d, 0x80, 0xf4, 0x11, 0xbe, 0x8e, 0xbc, 0x15, - 0x3f, 0x3a, 0xfc, 0xbe, 0x71, 0xfc, 0x75, 0x7c, 0x3c, 0x58, 0x1e, 0xbf, - 0xfc, 0xd9, 0x9d, 0xbd, 0x89, 0x78, 0x71, 0x67, 0x5f, 0xff, 0x22, 0xf7, - 0x96, 0xbe, 0x60, 0x8e, 0x27, 0xe7, 0x5e, 0x4e, 0x80, 0xea, 0x56, 0x53, - 0xbc, 0x90, 0xd7, 0x10, 0xfb, 0x08, 0x87, 0x23, 0xf2, 0x4e, 0xc5, 0x0b, - 0x30, 0xac, 0x46, 0xc5, 0xf8, 0xa8, 0x85, 0xca, 0xb7, 0x1a, 0x42, 0xa9, - 0xb1, 0x5a, 0x46, 0x32, 0xab, 0xe3, 0x16, 0x56, 0xa7, 0x4a, 0xb0, 0x7c, - 0x53, 0x00, 0x27, 0x9d, 0x08, 0x95, 0x22, 0x4c, 0x34, 0x90, 0xcc, 0xb6, - 0x8e, 0x8a, 0x4b, 0x0e, 0x6d, 0x26, 0x23, 0x79, 0xf5, 0xf4, 0xa4, 0x67, - 0x4d, 0x4e, 0x08, 0xe5, 0x34, 0xa5, 0x73, 0xf1, 0x1d, 0xad, 0x9e, 0x9e, - 0xb9, 0xce, 0xfe, 0x92, 0x60, 0xa9, 0x86, 0xb0, 0xd6, 0x69, 0xfa, 0xb6, - 0xaf, 0xbe, 0xb4, 0x17, 0xa0, 0x9d, 0x1b, 0xd9, 0x29, 0x4d, 0x99, 0x41, - 0xfb, 0x73, 0xe3, 0xdf, 0x69, 0xf8, 0xdb, 0x52, 0xb6, 0x29, 0x88, 0xd9, - 0x8e, 0xa5, 0x9b, 0x1a, 0x65, 0xf9, 0x8f, 0xd7, 0x9e, 0x3a, 0xff, 0x31, - 0x9c, 0x6b, 0xbb, 0x4d, 0x17, 0x1d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, - 0x2e, 0xbb, 0xff, 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x8d, - 0x44, 0x6d, 0x6e, 0x32, 0x85, 0xd8, 0x4a, 0x54, 0x84, 0x7b, 0x4a, 0x12, - 0x3a, 0x15, 0x77, 0x17, 0xcd, 0x9a, 0x47, 0xf3, 0xbd, 0x14, 0xf8, 0xff, - 0x68, 0xfe, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, - 0xd5, 0xff, 0x2a, 0xee, 0xa2, 0xbb, 0xc6, 0xfb, 0x47, 0x5f, 0xb8, 0xd7, - 0x76, 0x9a, 0x23, 0x7b, 0xff, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, - 0x7e, 0xfe, 0x8f, 0x7d, 0xeb, 0xf8, 0xeb, 0xfd, 0x9f, 0x78, 0xa7, 0x41, - 0xa3, 0xac, 0xc2, 0xb5, 0x4c, 0x97, 0x11, 0x16, 0x67, 0xd4, 0xa1, 0x2e, - 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x57, 0x72, 0x6d, 0x1d, 0x7c, - 0x8b, 0x7d, 0x87, 0x52, 0x86, 0xeb, 0xc3, 0x17, 0x87, 0x69, 0x93, 0xaf, - 0xe7, 0xec, 0xc3, 0x01, 0x3a, 0xff, 0xef, 0x76, 0x34, 0x2e, 0x05, 0x4a, - 0x70, 0xeb, 0xd1, 0x2c, 0x3a, 0x82, 0x88, 0xcd, 0xcb, 0x26, 0x46, 0xbf, - 0xe5, 0x30, 0x73, 0x7f, 0x3a, 0xce, 0xb8, 0x28, 0x75, 0xfd, 0x9c, 0x6b, - 0xbb, 0x4d, 0x12, 0x05, 0x7c, 0x3c, 0xd6, 0x05, 0x6f, 0xda, 0x71, 0x7d, - 0xce, 0xb8, 0x10, 0x75, 0x48, 0xf8, 0x37, 0x25, 0xe1, 0x35, 0xfe, 0x94, - 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0xee, 0x4e, 0xb8, 0x19, 0x68, 0xea, 0x83, - 0xe7, 0xc3, 0x4b, 0xec, 0x9d, 0xc2, 0x75, 0xff, 0xec, 0x9b, 0xae, 0xbf, - 0x76, 0x3c, 0x05, 0x9d, 0x53, 0xab, 0x06, 0x09, 0x16, 0x42, 0xad, 0x43, - 0x27, 0x87, 0x28, 0xc2, 0x5f, 0xc4, 0x1f, 0x48, 0x6f, 0xfe, 0x1c, 0x9d, - 0x8d, 0xb8, 0x11, 0xcf, 0x1d, 0x4c, 0x23, 0x23, 0x90, 0x83, 0xbf, 0xcc, - 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x91, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, - 0x8b, 0x5e, 0xff, 0xf6, 0x7d, 0x89, 0xd8, 0xc9, 0xbc, 0x18, 0x13, 0xaf, - 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x72, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, - 0x2e, 0xcb, 0xff, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x3a, 0xcc, - 0x61, 0xfe, 0xac, 0xce, 0xf8, 0x62, 0x4b, 0x3a, 0xd2, 0x3a, 0xfd, 0xc6, - 0xbb, 0xb4, 0xd1, 0x4a, 0xdf, 0xf3, 0x7a, 0x93, 0x76, 0x27, 0xc3, 0xaf, - 0xff, 0x76, 0x27, 0x8e, 0xa6, 0xc7, 0x0f, 0x50, 0xe6, 0x0d, 0xcd, 0xd2, - 0x63, 0x11, 0x8f, 0x33, 0x65, 0x6e, 0x98, 0x3b, 0xc3, 0x5e, 0xff, 0xce, - 0x9e, 0x90, 0x02, 0xe3, 0xf9, 0xd6, 0x60, 0x29, 0xc6, 0xae, 0x32, 0x7e, - 0x94, 0xd4, 0xec, 0x9b, 0xb9, 0x46, 0xf9, 0xba, 0xb2, 0x4e, 0x23, 0xac, - 0xa7, 0xf3, 0xf1, 0x3f, 0xd2, 0x67, 0xa1, 0x79, 0xb2, 0x3b, 0x5b, 0xfe, - 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x1c, 0x5f, 0xf2, 0x31, 0x9c, 0x6b, - 0xbb, 0x4d, 0x15, 0xad, 0x98, 0x74, 0x44, 0xf9, 0x16, 0xff, 0xf3, 0x0b, - 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xdd, 0xe0, 0x73, 0xf3, 0xae, - 0xcd, 0xce, 0xbf, 0xc1, 0xc5, 0xae, 0x13, 0x47, 0x5e, 0xd8, 0x09, 0x1d, - 0x4d, 0x44, 0x16, 0xe3, 0xa8, 0x2d, 0xb0, 0xc6, 0xf7, 0x43, 0x23, 0xaf, - 0xfb, 0x37, 0x1c, 0xff, 0xf7, 0x91, 0xd7, 0x2d, 0xa7, 0x54, 0x1e, 0x7c, - 0x8e, 0x6f, 0x86, 0x37, 0x91, 0xd7, 0xff, 0xe7, 0xdf, 0xf0, 0xf5, 0xe5, - 0x9a, 0x10, 0x3f, 0xd3, 0xa9, 0xa7, 0xf1, 0xd2, 0x1b, 0xf9, 0x38, 0x29, - 0xed, 0x1d, 0x7e, 0xe3, 0x8e, 0x41, 0xd4, 0x68, 0x86, 0xfa, 0x79, 0xee, - 0x57, 0x74, 0x09, 0xd7, 0xf2, 0x08, 0x71, 0x02, 0x75, 0x41, 0xbe, 0x90, - 0xa5, 0xf6, 0x4d, 0x2c, 0x3a, 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, - 0xa2, 0x60, 0xbf, 0x7f, 0xa7, 0x1f, 0xce, 0xbf, 0xc0, 0xdf, 0x89, 0x0b, - 0xc3, 0xaf, 0xfa, 0x27, 0xf0, 0xc0, 0x3d, 0xa3, 0xad, 0xee, 0x9f, 0x56, - 0xd9, 0x95, 0xf6, 0xed, 0x45, 0x0e, 0xac, 0x3c, 0xef, 0x15, 0xdf, 0xed, - 0x27, 0x51, 0x78, 0xa1, 0xd7, 0xff, 0x9e, 0x7e, 0xa4, 0x0e, 0x4c, 0x9c, - 0x43, 0xab, 0xc7, 0xf2, 0xc9, 0x95, 0xcd, 0xc3, 0xae, 0x07, 0xe5, 0x52, - 0x1a, 0xce, 0x0a, 0xdf, 0xec, 0x08, 0xe7, 0xbb, 0x87, 0x5f, 0xd3, 0xfd, - 0xdb, 0x71, 0xfc, 0xeb, 0xfb, 0x3d, 0xe8, 0xe6, 0x8e, 0xbf, 0x9c, 0x7f, - 0x9f, 0xff, 0x1d, 0x50, 0x88, 0xe1, 0x33, 0xdb, 0x2c, 0xb3, 0x10, 0xbb, - 0x13, 0x39, 0xf8, 0x5a, 0xf2, 0x13, 0x2d, 0x71, 0xdd, 0xcb, 0x84, 0x0b, - 0x21, 0x74, 0xa1, 0x87, 0x06, 0xa1, 0x35, 0xe4, 0xfd, 0x84, 0x1f, 0x61, - 0x7d, 0x79, 0x60, 0xe1, 0x57, 0xfe, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, - 0x13, 0x1d, 0xf4, 0x72, 0x36, 0x8e, 0xb3, 0x08, 0x88, 0x95, 0x8e, 0x75, - 0x2a, 0xfa, 0x27, 0x8e, 0x1d, 0x7e, 0xc8, 0x99, 0x16, 0x75, 0x21, 0xe3, - 0xf0, 0x86, 0xff, 0x76, 0x39, 0x3f, 0xd0, 0x7e, 0x75, 0xcf, 0xa3, 0xaf, - 0xbe, 0x7b, 0x3a, 0x75, 0xa3, 0xa6, 0xe3, 0x42, 0xb7, 0xa0, 0x67, 0x3a, - 0xff, 0xff, 0xfa, 0x5a, 0xee, 0x01, 0x9d, 0x77, 0x1b, 0x9a, 0xf9, 0x9b, - 0xcb, 0x48, 0x28, 0x75, 0xe7, 0x76, 0x9a, 0x2b, 0x1b, 0xe7, 0xfb, 0x0a, - 0x1d, 0x4d, 0x3c, 0xae, 0x13, 0xdf, 0xfb, 0x6f, 0x3c, 0x38, 0x08, 0x1f, - 0x1d, 0x4a, 0x26, 0xd4, 0xd2, 0x6d, 0xc6, 0xf9, 0x0c, 0x9f, 0x11, 0x5f, - 0xfc, 0x3e, 0x50, 0x10, 0x38, 0xd8, 0xe1, 0xd7, 0xfb, 0x93, 0xfb, 0x4f, - 0xbb, 0x4e, 0xa8, 0x3f, 0x77, 0x42, 0xbf, 0xa3, 0x6b, 0xd9, 0xbc, 0xc7, - 0x5f, 0xc0, 0xdb, 0x6f, 0x51, 0x52, 0x75, 0xfd, 0x9a, 0xde, 0x51, 0xd3, - 0xae, 0x8d, 0x87, 0x58, 0x3d, 0x3c, 0x41, 0x2d, 0xbf, 0xe8, 0xde, 0x53, - 0x49, 0xf9, 0x39, 0xd5, 0x08, 0xda, 0xc7, 0x84, 0x27, 0xbd, 0x12, 0xf1, - 0xd7, 0xfe, 0xc0, 0xf1, 0x01, 0x3f, 0xfa, 0x91, 0xd7, 0xcb, 0x7d, 0xfc, - 0x75, 0xff, 0xd3, 0xc7, 0xbe, 0x7d, 0x6f, 0xdd, 0xaf, 0xba, 0x3a, 0xff, - 0xb9, 0x1a, 0x7e, 0x0c, 0x48, 0xea, 0xe2, 0x21, 0xf6, 0x28, 0xde, 0x93, - 0xce, 0x75, 0xef, 0x93, 0xac, 0xeb, 0x83, 0xe3, 0xa9, 0x54, 0x98, 0xfe, - 0x42, 0xa7, 0x72, 0x54, 0x1c, 0x11, 0xfb, 0xff, 0x0b, 0x87, 0xb1, 0xb3, - 0xae, 0x27, 0x5f, 0xff, 0xf8, 0x13, 0xe3, 0x7e, 0x08, 0x36, 0xbe, 0x66, - 0xf2, 0xc0, 0x0f, 0xfa, 0x3a, 0xff, 0x9f, 0x71, 0xc0, 0xf5, 0xd9, 0x3a, - 0x82, 0x8e, 0xa1, 0x3d, 0xd3, 0xad, 0xfd, 0x3c, 0xd2, 0x55, 0x72, 0x73, - 0xaf, 0x84, 0x73, 0xc7, 0x52, 0xb2, 0x7a, 0x90, 0x6b, 0x7f, 0x4f, 0xf7, - 0x6d, 0xc7, 0xf3, 0xaf, 0xfe, 0x9b, 0xae, 0xbf, 0x76, 0x3c, 0x05, 0x9d, - 0x7f, 0xc9, 0x24, 0xe8, 0x16, 0xb4, 0x3a, 0xa1, 0x15, 0xf8, 0x67, 0xe4, - 0x5b, 0xdd, 0x46, 0x21, 0x90, 0xaf, 0x22, 0x1c, 0x8f, 0x65, 0xb0, 0xc9, - 0xe1, 0x07, 0x63, 0x0b, 0x72, 0xd1, 0x1b, 0xd4, 0x6b, 0xfe, 0x8c, 0xf3, - 0x6e, 0x10, 0x7f, 0x61, 0xab, 0x74, 0x84, 0xeb, 0xfb, 0x9c, 0x80, 0xe2, - 0xce, 0xbb, 0xef, 0xe7, 0x5e, 0xea, 0x2c, 0xeb, 0x4c, 0x75, 0x39, 0xac, - 0x00, 0xdd, 0xf9, 0xc6, 0x70, 0x68, 0xeb, 0xfe, 0x80, 0xf7, 0x03, 0xc7, - 0x69, 0xd4, 0x88, 0xef, 0xfc, 0xb0, 0x51, 0x74, 0x41, 0xe2, 0x7b, 0xda, - 0xfb, 0xa3, 0xaf, 0xb7, 0x9e, 0x14, 0x3a, 0x82, 0x78, 0x40, 0x1e, 0xbb, - 0xd0, 0x75, 0xf9, 0x78, 0x31, 0x23, 0xaf, 0x81, 0xec, 0xd1, 0xd7, 0xd1, - 0xc7, 0x13, 0xaf, 0xf3, 0xf2, 0x5f, 0xa6, 0xfa, 0x3a, 0xfb, 0x5a, 0x8f, - 0xce, 0xa8, 0x45, 0xda, 0x12, 0xf4, 0x84, 0x03, 0xec, 0x9a, 0x5f, 0x4b, - 0xf0, 0x48, 0xeb, 0xee, 0x7d, 0x8f, 0xce, 0xa8, 0x3c, 0x74, 0x23, 0xbf, - 0xc9, 0x3b, 0xaf, 0xff, 0xe0, 0xeb, 0xfe, 0x46, 0xf7, 0x26, 0x18, 0x09, - 0xd7, 0xd2, 0xf6, 0x7d, 0x3a, 0xf3, 0x63, 0xf3, 0xaf, 0x72, 0x16, 0x75, - 0x39, 0xed, 0x00, 0x8d, 0x91, 0xcb, 0xf4, 0x4f, 0xf7, 0x26, 0x3a, 0xf4, - 0x0c, 0x8e, 0xa9, 0x93, 0x58, 0xe1, 0x07, 0x4d, 0x06, 0x12, 0x3a, 0x2f, - 0xf1, 0x55, 0xff, 0xa3, 0x35, 0xf2, 0x10, 0x3f, 0x64, 0x75, 0xfc, 0x8c, - 0xea, 0x7c, 0x64, 0xea, 0x13, 0xef, 0xf2, 0x05, 0xfa, 0x03, 0xec, 0x69, - 0xd7, 0xdd, 0x81, 0x69, 0xd5, 0x23, 0xe7, 0xd1, 0x0f, 0x89, 0xaf, 0x9c, - 0x5e, 0x63, 0xaf, 0xc9, 0xe1, 0xc9, 0x1d, 0x7d, 0x0c, 0xc4, 0xc7, 0x5d, - 0xf5, 0x67, 0x5f, 0xf0, 0x3e, 0x78, 0x5f, 0xfc, 0x13, 0xaa, 0x74, 0x5c, - 0x28, 0x40, 0x84, 0xbd, 0x22, 0x11, 0x8b, 0xfd, 0x0c, 0x84, 0x0f, 0xc9, - 0x1d, 0x7f, 0x27, 0x37, 0xd4, 0x48, 0xeb, 0x6c, 0x3a, 0xb8, 0x7e, 0x5d, - 0x33, 0xda, 0x2d, 0xbc, 0x28, 0xa1, 0xd7, 0xd8, 0x14, 0xd8, 0x75, 0xd0, - 0xbc, 0x37, 0xae, 0x37, 0x6d, 0x1d, 0x48, 0x6e, 0x9c, 0xaa, 0xef, 0xe0, - 0xab, 0x99, 0x64, 0xaa, 0x43, 0x5c, 0xc8, 0xb5, 0xfe, 0x79, 0x0e, 0x7b, - 0xa8, 0x53, 0x06, 0x86, 0xf3, 0xef, 0xa3, 0xaf, 0xbe, 0xf5, 0xfc, 0x75, - 0x04, 0xdf, 0xf8, 0x72, 0xf4, 0x0c, 0xc7, 0x5c, 0x30, 0x75, 0xa6, 0x3a, - 0xa6, 0x3c, 0x0e, 0x0d, 0xb8, 0xa5, 0xff, 0xca, 0x20, 0xb7, 0x50, 0xb7, - 0xdf, 0xc7, 0x5e, 0xff, 0x36, 0x8e, 0xa5, 0x0f, 0x8f, 0x88, 0x97, 0xcb, - 0xd0, 0x16, 0x75, 0x94, 0x3a, 0xdb, 0x67, 0x5d, 0xc5, 0x0e, 0xa8, 0x3d, - 0xd4, 0x22, 0x00, 0x8f, 0xd1, 0x3b, 0xff, 0xee, 0xe4, 0xb5, 0x1e, 0x96, - 0x2b, 0xb8, 0xfe, 0x75, 0xff, 0xa4, 0x9e, 0xee, 0x6f, 0xe0, 0x41, 0xd7, - 0x66, 0x8e, 0xa8, 0x3d, 0x39, 0x1f, 0x56, 0x91, 0x8b, 0xe8, 0x52, 0x5f, - 0x92, 0x17, 0x0b, 0x3a, 0xd8, 0x75, 0x21, 0xee, 0x68, 0xa3, 0x6c, 0x96, - 0xa1, 0x58, 0x0e, 0x30, 0xa4, 0x24, 0xbb, 0x08, 0x07, 0x8d, 0x76, 0xf6, - 0xa2, 0x63, 0xa8, 0xeb, 0x2c, 0xea, 0xf1, 0x75, 0xb0, 0x2a, 0xfd, 0xfa, - 0x71, 0x14, 0x3a, 0xe7, 0x50, 0xea, 0x99, 0x12, 0xdd, 0x36, 0xfc, 0x88, - 0x4a, 0x2e, 0xf4, 0x1d, 0x7e, 0x8e, 0xe6, 0xc7, 0x3a, 0x9c, 0xde, 0x7e, - 0x2b, 0x7f, 0x27, 0xb3, 0xae, 0xa1, 0xd7, 0xf7, 0x40, 0xf3, 0xf5, 0x0e, - 0xbc, 0xcb, 0x2c, 0x95, 0x7f, 0xc1, 0x89, 0xfe, 0xe7, 0x5f, 0x72, 0x98, - 0x2f, 0xee, 0xc9, 0xce, 0xa0, 0xa2, 0xb5, 0xa9, 0x88, 0x97, 0x7a, 0x16, - 0x87, 0x56, 0x1e, 0x4b, 0x4b, 0xef, 0x93, 0x9b, 0x41, 0x3a, 0xfd, 0xd8, - 0xdd, 0xd5, 0xce, 0xbf, 0xfe, 0x8f, 0x68, 0x39, 0xe4, 0xe8, 0x33, 0x7f, - 0x1d, 0x5d, 0x3f, 0x9f, 0x15, 0x5b, 0x87, 0x5f, 0xec, 0xc6, 0xfd, 0xd9, - 0xdc, 0x3a, 0xe0, 0x68, 0xeb, 0xff, 0xf6, 0x06, 0x33, 0x7f, 0xbe, 0x41, - 0x04, 0xb3, 0x47, 0x5c, 0xbf, 0xce, 0xb9, 0xc4, 0xea, 0xe9, 0xab, 0x71, - 0x7b, 0xf2, 0xd3, 0xdf, 0xb9, 0xd5, 0x3a, 0x7c, 0x39, 0x09, 0xd5, 0x72, - 0x29, 0x84, 0x1c, 0xd4, 0x45, 0xbd, 0x08, 0x00, 0x10, 0x5f, 0x77, 0xc9, - 0x39, 0xd7, 0xf9, 0xa9, 0xa1, 0xcd, 0x8e, 0x75, 0xf4, 0x4e, 0xf2, 0x3a, - 0xec, 0xf1, 0xd7, 0xec, 0x9c, 0x73, 0x73, 0xab, 0x11, 0x63, 0xb9, 0x17, - 0x0c, 0xba, 0x42, 0x22, 0xb7, 0xbb, 0x01, 0x3a, 0xee, 0x68, 0xea, 0x39, - 0x0b, 0x6b, 0xfd, 0x03, 0x27, 0x5e, 0x04, 0xeb, 0xef, 0x2d, 0x7c, 0x3a, - 0xff, 0xef, 0xe0, 0x5a, 0xfe, 0xff, 0xe8, 0xc8, 0xeb, 0xd2, 0x4e, 0x9d, - 0x7d, 0xe1, 0xc9, 0x1d, 0x7e, 0xc0, 0x2a, 0x74, 0xe7, 0x5f, 0xfe, 0x4d, - 0x77, 0x02, 0x39, 0xb0, 0x73, 0x47, 0x54, 0x93, 0x45, 0x50, 0xc3, 0x72, - 0x29, 0x91, 0xb8, 0x36, 0x24, 0x1e, 0x2a, 0xa5, 0x53, 0x67, 0xe3, 0x11, - 0x82, 0x4f, 0x08, 0xb9, 0x11, 0x06, 0x1a, 0x19, 0x1f, 0x46, 0xf1, 0x99, - 0xa4, 0x39, 0xe6, 0x85, 0xe7, 0x21, 0x52, 0xb6, 0xee, 0xcb, 0x81, 0x78, - 0x77, 0x7e, 0xf4, 0xa9, 0x21, 0x18, 0xc8, 0xb5, 0x28, 0x0b, 0xd1, 0x97, - 0xb2, 0x93, 0xb6, 0x63, 0xf6, 0x35, 0xdb, 0xfe, 0x63, 0xc9, 0x9b, 0x5a, - 0x04, 0x1d, 0x7f, 0xff, 0xc0, 0x86, 0x3d, 0xa4, 0xeb, 0xa7, 0xb3, 0x9f, - 0xad, 0xe4, 0x75, 0x30, 0xa8, 0x76, 0x78, 0xdf, 0x02, 0x77, 0x7e, 0xe3, - 0x5d, 0xda, 0x68, 0xad, 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, - 0x27, 0x0b, 0x31, 0x87, 0xfa, 0xb3, 0x3b, 0x95, 0x41, 0x3a, 0xdd, 0x3a, - 0xda, 0x3a, 0x80, 0x68, 0x36, 0xc4, 0x2f, 0x9a, 0xee, 0xd3, 0x45, 0xa3, - 0x7f, 0xfb, 0x03, 0xd7, 0x52, 0x69, 0x93, 0x40, 0x59, 0xd5, 0xc3, 0xf9, - 0xe9, 0x6d, 0xf3, 0x5c, 0x7f, 0x3a, 0xff, 0xa6, 0xc5, 0x7d, 0x73, 0x8f, - 0xe3, 0xaf, 0xe8, 0x71, 0x00, 0x70, 0xeb, 0x91, 0x43, 0xaf, 0xff, 0xd3, - 0xc7, 0xa0, 0x3c, 0x8e, 0xbe, 0x87, 0x3f, 0x3a, 0xff, 0xd1, 0xbb, 0xab, - 0xf4, 0x5d, 0x5e, 0x73, 0xaf, 0xfd, 0x1c, 0xff, 0x13, 0x39, 0xe0, 0x1d, - 0x50, 0x8d, 0x5e, 0xaa, 0x69, 0x12, 0xd9, 0x32, 0x63, 0x5a, 0x87, 0x5d, - 0xfe, 0xef, 0x40, 0xa2, 0xe3, 0x47, 0x5f, 0xff, 0x93, 0x43, 0x9b, 0x1f, - 0xc3, 0x9a, 0xeb, 0xcc, 0x75, 0x62, 0x22, 0x26, 0x34, 0xbe, 0xcf, 0xdf, - 0xa7, 0x5d, 0xdd, 0x1d, 0x66, 0x15, 0x0a, 0xea, 0xd5, 0xb3, 0xac, 0x84, - 0xeb, 0x48, 0xa6, 0x21, 0x59, 0xe7, 0x63, 0x44, 0xf4, 0x2d, 0xf6, 0xc8, - 0xfe, 0x90, 0xdf, 0x35, 0xdd, 0xa6, 0x8b, 0x6a, 0xff, 0xfe, 0x87, 0xf4, - 0x76, 0x34, 0x89, 0x24, 0xe6, 0x04, 0xeb, 0xfb, 0xb0, 0xb8, 0x40, 0x9d, - 0x5c, 0x45, 0x76, 0x8b, 0x7c, 0xad, 0x7f, 0xee, 0xa0, 0x5e, 0x41, 0xea, - 0x2c, 0xeb, 0xe8, 0xd9, 0x88, 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, 0x27, - 0x3a, 0xff, 0xa3, 0x9f, 0x35, 0x1d, 0x74, 0x3a, 0xff, 0x75, 0x1e, 0x5e, - 0x49, 0xce, 0xac, 0x4c, 0xc5, 0xa6, 0x1c, 0x3d, 0x12, 0x16, 0x4e, 0x76, - 0xce, 0x2f, 0xe5, 0x1f, 0x81, 0x00, 0x9d, 0x7f, 0x0e, 0xda, 0x73, 0x14, - 0x3a, 0xfc, 0x93, 0xae, 0x1a, 0x75, 0xf9, 0xf7, 0x97, 0xdd, 0x1d, 0x66, - 0x14, 0x45, 0x68, 0x96, 0xf8, 0xbf, 0x61, 0x3d, 0x30, 0x9a, 0x6f, 0xf1, - 0x83, 0xdc, 0xbe, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb9, 0x6c, 0xc0, - 0x4f, 0x27, 0x05, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x17, 0x6d, 0xff, 0x24, - 0xa4, 0x83, 0xfc, 0x48, 0xeb, 0x31, 0x87, 0xd4, 0xe6, 0x75, 0x0e, 0xc5, - 0x3a, 0x72, 0x99, 0x4f, 0x31, 0x06, 0x36, 0x85, 0x29, 0x1a, 0x89, 0x5b, - 0x78, 0xab, 0xc2, 0xdf, 0xb2, 0xf4, 0xc6, 0x5e, 0xf6, 0x9d, 0x7d, 0x09, - 0x2b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x54, 0xf7, 0x83, 0x3a, 0xce, - 0xb7, 0x8e, 0xbf, 0xe8, 0x79, 0xfe, 0x6f, 0xa8, 0x09, 0xd4, 0x87, 0x96, - 0x22, 0x17, 0xcd, 0x77, 0x69, 0xa2, 0xb9, 0xbf, 0xcc, 0x67, 0x1a, 0xee, - 0xd3, 0x45, 0x9d, 0x79, 0xde, 0x47, 0x5f, 0xc9, 0xac, 0x17, 0x64, 0xea, - 0xe2, 0x2c, 0x7a, 0x5a, 0x27, 0xfe, 0x1a, 0xbf, 0xfd, 0xe8, 0xd7, 0xc0, - 0x6b, 0xd1, 0x34, 0xc8, 0x75, 0xfc, 0x8b, 0x9c, 0x1c, 0x91, 0xd7, 0xfa, - 0x3b, 0xf1, 0x6a, 0xda, 0xa3, 0xc7, 0x56, 0x22, 0xe7, 0xa9, 0xbb, 0x0b, - 0xaf, 0xdc, 0xcf, 0x22, 0xce, 0xbe, 0x71, 0x80, 0x9d, 0x7f, 0x64, 0xd0, - 0xb8, 0xfa, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x42, 0xbf, 0xf6, 0x2f, - 0x1f, 0x93, 0xfc, 0xdd, 0x67, 0x5f, 0xf2, 0x6f, 0xaf, 0x0c, 0x2f, 0x47, - 0x5d, 0x26, 0x31, 0x15, 0x9d, 0x33, 0xfd, 0x06, 0xff, 0xee, 0xa2, 0xf3, - 0x5f, 0x37, 0x96, 0x78, 0xeb, 0xe9, 0x77, 0xee, 0x8e, 0xa8, 0x3e, 0xac, - 0x46, 0xbe, 0x56, 0xfb, 0x0b, 0x3a, 0xfe, 0xee, 0xb5, 0x9c, 0x9c, 0xeb, - 0xa1, 0x93, 0xab, 0x0f, 0x11, 0x0b, 0xac, 0xc4, 0xeb, 0x99, 0xe1, 0x68, - 0xc8, 0x68, 0xa4, 0x3d, 0x78, 0x62, 0xb2, 0x6e, 0x8f, 0xbc, 0x36, 0x86, - 0x14, 0xfa, 0x20, 0xf3, 0x55, 0xff, 0xcc, 0x75, 0xf4, 0x39, 0xef, 0x47, - 0xe7, 0x5f, 0xfe, 0x61, 0x6f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x7c, - 0xa6, 0xaf, 0x2e, 0x2b, 0xce, 0x87, 0x2e, 0x16, 0x7d, 0x44, 0xb9, 0x37, - 0x3a, 0xff, 0xfa, 0x53, 0xaa, 0xd0, 0xad, 0xce, 0xde, 0x7c, 0xf9, 0xdd, - 0xb3, 0xaa, 0x47, 0xf5, 0xf8, 0xb5, 0xfb, 0x39, 0x99, 0x31, 0xd6, 0x63, - 0xa7, 0x93, 0xf4, 0x8e, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x59, 0x5f, 0xf9, - 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4d, 0xd6, 0x63, 0x0f, 0xf5, 0x66, - 0x74, 0xd4, 0x68, 0x24, 0x2a, 0x2f, 0xdc, 0x6b, 0xbb, 0x4d, 0x12, 0xb5, - 0xf8, 0x60, 0x2f, 0xd3, 0xaf, 0xcc, 0x2d, 0xe4, 0xc6, 0x1e, 0xc2, 0x19, - 0xdf, 0xfb, 0xd8, 0xc6, 0x71, 0x27, 0x75, 0x9d, 0x7f, 0xf9, 0x58, 0x56, - 0x55, 0x1a, 0xc7, 0x92, 0x67, 0x30, 0xeb, 0xff, 0x26, 0x80, 0xb1, 0x4d, - 0x80, 0x73, 0xaf, 0xe8, 0x17, 0x6b, 0xab, 0x9d, 0x52, 0x3e, 0xb5, 0x9f, - 0x5c, 0x1e, 0x1d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x97, 0x2f, 0xf9, 0x1e, - 0x5e, 0x18, 0x5e, 0x8e, 0xbf, 0x4b, 0x6d, 0x3a, 0xe7, 0x5e, 0x8d, 0xb8, - 0x3a, 0xf2, 0x0c, 0x1d, 0x52, 0x3d, 0xf0, 0x94, 0xec, 0x1d, 0xbf, 0xff, - 0x3f, 0x90, 0x12, 0x14, 0x94, 0x78, 0x41, 0x23, 0xaf, 0xe9, 0x77, 0x07, - 0x1a, 0x75, 0xe9, 0x77, 0xc7, 0x5d, 0xd8, 0x43, 0xc7, 0xe9, 0x5d, 0xff, - 0xc2, 0x9f, 0xeb, 0x90, 0x92, 0x7d, 0x1d, 0x58, 0x7d, 0xc8, 0x59, 0x79, - 0xe4, 0xc2, 0xaf, 0x56, 0x31, 0x10, 0xc0, 0x91, 0x16, 0x0b, 0x74, 0xcd, - 0xe1, 0x2b, 0xa3, 0x1f, 0x46, 0x0f, 0x66, 0x11, 0x5f, 0x72, 0xe5, 0xab, - 0x5f, 0xfc, 0xc3, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x8e, 0xef, 0xfb, - 0xdd, 0xc9, 0x30, 0xe3, 0xa3, 0xaf, 0xe5, 0x50, 0xc3, 0x70, 0x4e, 0xb8, - 0x1d, 0x3a, 0xfe, 0x54, 0x0e, 0x75, 0xfc, 0x75, 0xff, 0xfd, 0xe9, 0x20, - 0x7a, 0x9b, 0x3e, 0x60, 0x78, 0x80, 0x69, 0xd7, 0xfb, 0x19, 0xd4, 0x0f, - 0xb4, 0x75, 0xfe, 0x71, 0xfd, 0xf8, 0xff, 0x4e, 0xbf, 0xf2, 0x73, 0xe6, - 0x87, 0x17, 0x0d, 0x3a, 0xff, 0xd0, 0x20, 0xf2, 0x3e, 0xc7, 0x91, 0xd7, - 0xcd, 0x77, 0x69, 0xa2, 0xa1, 0xbf, 0xec, 0xee, 0x0b, 0xf3, 0x88, 0x75, - 0x28, 0x8d, 0xd6, 0x9f, 0x70, 0xf7, 0x45, 0xb7, 0x4b, 0x0e, 0xbf, 0xe9, - 0x79, 0x38, 0xed, 0x41, 0x3a, 0xff, 0xf3, 0xaf, 0x38, 0x38, 0x9b, 0x13, - 0x8e, 0x75, 0xff, 0xdd, 0x1c, 0x9b, 0xdd, 0xce, 0x26, 0x8e, 0xbf, 0x6e, - 0x28, 0xb4, 0x3a, 0xa1, 0x16, 0x18, 0x8e, 0x88, 0x77, 0xfa, 0x3c, 0xfd, - 0xf8, 0x18, 0x3a, 0xff, 0xc0, 0xf8, 0xe3, 0x9b, 0x5f, 0x3a, 0x03, 0xaf, - 0xf4, 0xa3, 0x93, 0xc7, 0x27, 0x3a, 0xff, 0xed, 0x6b, 0x07, 0xda, 0xc9, - 0x27, 0x4e, 0xbf, 0xfe, 0x8f, 0xf0, 0x7e, 0x3f, 0xbe, 0x77, 0x3f, 0x73, - 0xae, 0x19, 0xce, 0xa8, 0x46, 0xf6, 0x1a, 0x22, 0x10, 0xa9, 0x5f, 0xdb, - 0x1d, 0x7d, 0x65, 0xce, 0xbf, 0xff, 0xc9, 0x1e, 0x7e, 0xb1, 0xae, 0xe0, - 0xfb, 0xe7, 0xf2, 0xd1, 0xd6, 0xc4, 0x44, 0x90, 0x97, 0xdf, 0x77, 0xd9, - 0x39, 0xd7, 0xec, 0x9d, 0xc7, 0x61, 0xd7, 0xff, 0xff, 0xfa, 0x25, 0xf3, - 0xdd, 0x48, 0xd7, 0xcc, 0x03, 0x63, 0x67, 0xcc, 0xe7, 0x33, 0x60, 0x1f, - 0xa7, 0x5f, 0x74, 0x5f, 0x68, 0xea, 0xc4, 0xc0, 0xc4, 0x8b, 0x45, 0x1e, - 0x84, 0xb5, 0xff, 0xff, 0x01, 0xd5, 0xd2, 0x7e, 0xba, 0x7a, 0x3a, 0x9e, - 0xd6, 0x04, 0xeb, 0x30, 0xa8, 0x5f, 0x6a, 0x56, 0xcb, 0x95, 0x42, 0xd0, - 0x5f, 0x3a, 0xf0, 0x4c, 0xb2, 0x31, 0x06, 0x9f, 0x6e, 0x2b, 0xc8, 0x73, - 0x2c, 0xb7, 0xa6, 0x63, 0x19, 0x16, 0xa1, 0x97, 0xe8, 0xca, 0x76, 0xd0, - 0x6f, 0x9a, 0xee, 0xd3, 0x45, 0x51, 0x7f, 0xb9, 0x1b, 0x37, 0x96, 0x78, - 0xea, 0xe1, 0xf1, 0x00, 0xb6, 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, - 0xa2, 0x6b, 0xbc, 0xb7, 0xf1, 0xd6, 0x63, 0x11, 0x0e, 0xb2, 0x27, 0x4a, - 0xbf, 0x71, 0xae, 0xed, 0x34, 0x55, 0x97, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, - 0x9c, 0xeb, 0x31, 0x87, 0xd8, 0x26, 0x77, 0xfe, 0x63, 0xb1, 0xbf, 0xa3, - 0xae, 0xae, 0x75, 0xff, 0xcc, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, - 0x12, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x69, 0x5f, 0xf9, 0xe4, 0xc6, 0x71, - 0xae, 0xed, 0x34, 0x4f, 0xb6, 0x63, 0x0f, 0xf5, 0x66, 0x77, 0xff, 0x98, - 0x5b, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa1, 0x2f, 0xdd, 0x49, 0xe3, - 0x87, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x28, 0xfb, 0xfe, 0x89, 0x47, 0x27, - 0x8e, 0x4e, 0x75, 0xff, 0x86, 0x26, 0x81, 0x89, 0xbb, 0x07, 0x5f, 0xff, - 0xd8, 0x1e, 0xc7, 0xd6, 0x3c, 0x2f, 0xfe, 0xb5, 0x1f, 0x95, 0x7e, 0x61, - 0x6f, 0x26, 0x21, 0x32, 0xdc, 0x27, 0x13, 0x3f, 0x1c, 0xed, 0x9e, 0x54, - 0x36, 0x46, 0xf3, 0xce, 0x16, 0xc8, 0xcb, 0x14, 0x54, 0x9f, 0xa2, 0x6c, - 0x7e, 0xfb, 0xc2, 0x85, 0x09, 0xe6, 0x42, 0xec, 0x33, 0xbf, 0x28, 0xf4, - 0x70, 0x97, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x88, 0xaf, 0xec, 0xe3, - 0x5d, 0xda, 0x68, 0x8a, 0xef, 0xf9, 0x5d, 0x8c, 0xe3, 0x5d, 0xda, 0x68, - 0xae, 0x29, 0x84, 0x40, 0x39, 0xc5, 0xff, 0xef, 0xe0, 0x5a, 0xc3, 0xfb, - 0xff, 0xa3, 0x23, 0xaf, 0x98, 0x9e, 0x65, 0x73, 0xac, 0x9b, 0x9f, 0xaf, - 0xe9, 0xb7, 0xd9, 0xd7, 0xf1, 0xd7, 0xfb, 0x13, 0x9f, 0xfe, 0x0d, 0x1d, - 0x65, 0x40, 0x9e, 0xa6, 0x88, 0x2f, 0xff, 0xef, 0x69, 0x3a, 0xe9, 0x24, - 0x1f, 0x03, 0xbc, 0xc3, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x14, 0xf5, 0xfe, - 0x5a, 0x04, 0x0f, 0xc9, 0x1d, 0x72, 0xd0, 0xea, 0x83, 0xc7, 0x69, 0x95, - 0xff, 0xfe, 0x94, 0x7b, 0x40, 0x5b, 0x53, 0xf8, 0xce, 0xa0, 0x1a, 0x75, - 0xff, 0xfd, 0xce, 0x03, 0x9c, 0x81, 0xc5, 0x13, 0xbd, 0xcf, 0xa7, 0x5f, - 0xfc, 0x92, 0xc1, 0xfe, 0x16, 0x9c, 0x91, 0xd7, 0xfa, 0x51, 0xc9, 0xe3, - 0x93, 0x9d, 0x7d, 0xf0, 0x5e, 0x47, 0x5f, 0x9f, 0x3a, 0x8b, 0x3a, 0xb4, - 0x78, 0xfb, 0x08, 0xaa, 0x11, 0x3f, 0x8f, 0x77, 0xfd, 0x02, 0xdc, 0xd9, - 0x9e, 0xd1, 0xd7, 0xe7, 0x9e, 0x38, 0x03, 0xa9, 0x54, 0xac, 0xee, 0x0a, - 0xf1, 0x61, 0xaf, 0x5b, 0x90, 0xa3, 0x03, 0xae, 0x0c, 0x38, 0x76, 0x10, - 0xed, 0x9c, 0x5f, 0xfe, 0x79, 0x30, 0x11, 0x76, 0x75, 0xa8, 0xfc, 0xeb, - 0xff, 0xdf, 0xfe, 0x0d, 0x31, 0xf4, 0x5d, 0x63, 0x07, 0x5f, 0xfc, 0x39, - 0xfb, 0x8f, 0xec, 0x2d, 0x16, 0x75, 0x71, 0x12, 0x3e, 0x4d, 0xa6, 0x13, - 0x96, 0x0c, 0x25, 0xd2, 0x1b, 0x97, 0x07, 0x0e, 0xbf, 0xf9, 0x03, 0xc7, - 0xdd, 0x8e, 0x72, 0x27, 0x3a, 0x98, 0x3d, 0xbe, 0x8a, 0xdc, 0x18, 0x3a, - 0xff, 0xfd, 0xd8, 0xe6, 0x49, 0x1f, 0xd8, 0x14, 0x03, 0x4a, 0xbf, 0x44, - 0xbf, 0x04, 0x8e, 0xbe, 0x6b, 0xbb, 0x4d, 0x15, 0x9d, 0x4c, 0x7a, 0xbc, - 0x28, 0xbe, 0xf2, 0x2f, 0x47, 0x5f, 0xd3, 0xae, 0x06, 0x5a, 0x3a, 0xfd, - 0x9e, 0xd7, 0xdd, 0x1d, 0x7a, 0x27, 0x43, 0xaf, 0xde, 0xff, 0xe8, 0xc8, - 0xeb, 0xc0, 0x7d, 0x1d, 0x7f, 0xd9, 0x24, 0x02, 0xba, 0xb7, 0xfa, 0xce, - 0xbf, 0x64, 0xd3, 0x83, 0xf3, 0xac, 0xc4, 0x2a, 0x21, 0x08, 0xae, 0x42, - 0x9f, 0x72, 0x3e, 0x10, 0xac, 0xb7, 0xa5, 0x2e, 0x36, 0x25, 0x5a, 0x1b, - 0xfa, 0x83, 0x7f, 0xee, 0xa7, 0x9f, 0x93, 0xc2, 0x04, 0xeb, 0xf7, 0x90, - 0x71, 0x67, 0x5f, 0x49, 0xc5, 0x8c, 0x3e, 0x2d, 0xa3, 0xdb, 0xff, 0x3c, - 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x16, 0xff, 0xcf, 0xe6, 0x21, 0x38, - 0x9e, 0x01, 0xd4, 0xc2, 0x21, 0xdd, 0x2a, 0xfe, 0xce, 0x35, 0xdd, 0xa6, - 0x8b, 0x26, 0xff, 0xf7, 0xb5, 0xf7, 0x4c, 0x64, 0xe8, 0x32, 0xd1, 0xd4, - 0xc2, 0x21, 0x70, 0xe2, 0xff, 0xff, 0x3a, 0x78, 0x1c, 0x7d, 0x30, 0xde, - 0xa7, 0x22, 0x5a, 0x3a, 0xfe, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0x62, 0xff, - 0xfe, 0x54, 0x77, 0xe0, 0xe7, 0x3d, 0xae, 0xcd, 0xf3, 0xe7, 0x76, 0xce, - 0xbd, 0xc0, 0x74, 0xeb, 0xbc, 0xc4, 0x22, 0x1b, 0x8d, 0x54, 0xc2, 0x3b, - 0x52, 0x17, 0xd7, 0xb3, 0x58, 0x75, 0xf3, 0x5d, 0xda, 0x68, 0xb6, 0xef, - 0xb5, 0x3b, 0xf0, 0xea, 0xe1, 0xe7, 0xf8, 0xb6, 0xfe, 0x4e, 0xf9, 0x3f, - 0x01, 0xd7, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0x31, 0x24, 0x78, - 0xe3, 0x4c, 0xc4, 0x42, 0x5b, 0x7f, 0xfb, 0x07, 0xf6, 0x16, 0xe1, 0xcc, - 0x15, 0x0e, 0xbc, 0xaa, 0xe8, 0x4e, 0xbd, 0x3f, 0x50, 0xeb, 0xff, 0x2a, - 0x95, 0x4a, 0xd3, 0xdd, 0xc1, 0x8f, 0xce, 0xbf, 0xa0, 0x64, 0x10, 0x2c, - 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x78, 0x5f, 0xf9, 0xfd, 0x1b, 0x39, 0xcc, - 0xdf, 0x47, 0x57, 0x0f, 0xb4, 0x4b, 0x6f, 0xbd, 0xb7, 0x9d, 0x3a, 0xfc, - 0xb8, 0x19, 0x39, 0xd7, 0xfa, 0x50, 0x3e, 0xd8, 0xed, 0x3a, 0xff, 0x47, - 0x9f, 0xbf, 0x03, 0x07, 0x5f, 0xfb, 0xea, 0xf7, 0x97, 0xb0, 0x7d, 0xa3, - 0xae, 0xc5, 0x0e, 0xa8, 0x3d, 0x7c, 0x41, 0xbe, 0x49, 0xf1, 0x67, 0x5f, - 0xb0, 0x7f, 0xda, 0x83, 0xaf, 0xd1, 0xf4, 0x0f, 0xa3, 0xaf, 0xff, 0x62, - 0xe1, 0xbf, 0x30, 0x41, 0x2c, 0xd1, 0xd7, 0xff, 0x67, 0x7a, 0xf2, 0x5a, - 0x47, 0x24, 0x75, 0xd1, 0xf9, 0xd5, 0x23, 0xd8, 0xf2, 0x15, 0x2a, 0x15, - 0xce, 0xaa, 0x88, 0x15, 0x78, 0xe4, 0xe9, 0x99, 0x09, 0x9d, 0xc8, 0x50, - 0x92, 0x62, 0x55, 0x99, 0xf6, 0x11, 0x4e, 0x41, 0xf9, 0x08, 0x94, 0xe8, - 0xa3, 0xd0, 0xa1, 0xbf, 0xdb, 0xb1, 0x9f, 0xbf, 0x34, 0x75, 0xfe, 0xfd, - 0x89, 0xa5, 0x03, 0xe3, 0xa9, 0x84, 0xd5, 0x62, 0x1d, 0x7c, 0x35, 0xbc, - 0x99, 0xb9, 0xd7, 0xcd, 0x77, 0x69, 0xa2, 0xf4, 0xbf, 0xf2, 0x7b, 0xa2, - 0xf2, 0xfd, 0xff, 0x3a, 0xb8, 0x7d, 0x6b, 0x2d, 0xbc, 0xb4, 0xf1, 0xd7, - 0xfc, 0xfe, 0x94, 0x29, 0xe4, 0x9c, 0xea, 0x59, 0xea, 0x08, 0xdd, 0xfb, - 0x17, 0xd7, 0x09, 0xd4, 0x14, 0xd0, 0xf2, 0x10, 0xdf, 0x5d, 0xb6, 0x88, - 0x6f, 0xff, 0xf9, 0x36, 0x60, 0xb0, 0x1c, 0x0f, 0x71, 0x6b, 0x79, 0x60, - 0x9d, 0x4c, 0x22, 0xb3, 0x11, 0xea, 0x1b, 0x63, 0xf9, 0xe1, 0x7f, 0x28, - 0x4c, 0x64, 0xea, 0x73, 0x61, 0x2c, 0x92, 0x91, 0x26, 0x8c, 0x1f, 0x90, - 0xc2, 0x5c, 0x2a, 0x3a, 0x47, 0xfc, 0x69, 0xa3, 0x18, 0xce, 0x90, 0xc1, - 0x3a, 0x76, 0xcc, 0xa2, 0x5b, 0x81, 0xd3, 0xaf, 0xfe, 0x04, 0x4c, 0x39, - 0xb1, 0xd6, 0xb4, 0x3a, 0xfb, 0x3a, 0xfe, 0x3a, 0xff, 0x62, 0x73, 0xff, - 0xc1, 0xa3, 0xac, 0xa8, 0x51, 0x13, 0x02, 0x89, 0xa2, 0x0b, 0xef, 0x46, - 0xf3, 0x9d, 0x7f, 0xde, 0xd6, 0x6f, 0x2e, 0x81, 0x43, 0xa9, 0x0f, 0x78, - 0x48, 0xef, 0xa3, 0x64, 0x48, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x47, - 0x7f, 0xfd, 0xd0, 0x6b, 0x58, 0xb1, 0xcd, 0x9f, 0x21, 0x58, 0x3a, 0xff, - 0xa2, 0x7e, 0x67, 0xbc, 0x9e, 0x3a, 0xf0, 0xc6, 0xe7, 0x54, 0x8f, 0x4c, - 0x27, 0x17, 0xfd, 0x9c, 0xcd, 0x63, 0x8c, 0xe7, 0x5e, 0xc0, 0xac, 0xeb, - 0xff, 0xfd, 0xd7, 0x4f, 0x47, 0x47, 0x3d, 0xd4, 0xee, 0x23, 0x27, 0x5f, - 0xff, 0xfe, 0xf7, 0x91, 0x7c, 0x4c, 0xdc, 0x41, 0xe8, 0xef, 0xcd, 0x89, - 0xe9, 0xa0, 0xea, 0x84, 0x6c, 0x62, 0xed, 0xfe, 0x75, 0xe7, 0x25, 0x0b, - 0x3a, 0xe9, 0xd6, 0x55, 0xcc, 0xb2, 0x55, 0xff, 0x98, 0x6f, 0x52, 0x6e, - 0xc4, 0xec, 0x7e, 0x6b, 0xd9, 0x17, 0xbe, 0xd9, 0x1e, 0x83, 0xaa, 0x47, - 0xfa, 0x8b, 0x77, 0xf6, 0x3a, 0xf3, 0x7f, 0x1d, 0x7f, 0x9d, 0x8d, 0x27, - 0x1f, 0xf3, 0xac, 0xae, 0x75, 0xff, 0x46, 0x6f, 0x0f, 0x27, 0x91, 0xd4, - 0xac, 0x9e, 0x48, 0x44, 0xef, 0xe5, 0x71, 0xce, 0xbf, 0x8e, 0xbf, 0xa1, - 0x4c, 0x14, 0x50, 0xeb, 0xfb, 0x3d, 0xb5, 0xec, 0xe9, 0xd5, 0x88, 0x89, - 0x12, 0xed, 0x16, 0x5f, 0xff, 0xcd, 0x63, 0x8e, 0x29, 0xe6, 0x39, 0x1e, - 0x17, 0xfc, 0xea, 0x56, 0xd7, 0xac, 0x15, 0x50, 0xae, 0x88, 0x4c, 0x48, - 0x83, 0x08, 0x9a, 0x67, 0xbc, 0x2a, 0x90, 0x8a, 0x63, 0x6e, 0x43, 0xcf, - 0xa4, 0x2f, 0x0d, 0xdf, 0xc8, 0x44, 0xb3, 0x4f, 0x9e, 0x85, 0x86, 0xc2, - 0xeb, 0xb6, 0xba, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x2e, 0xbf, 0x7b, - 0xff, 0xa3, 0x22, 0xaf, 0xda, 0xf7, 0x63, 0xf3, 0xaf, 0xcf, 0x3c, 0x70, - 0x07, 0x59, 0x89, 0xd1, 0x8b, 0x83, 0x2e, 0x66, 0x02, 0xad, 0xb2, 0x8a, - 0x61, 0x51, 0x44, 0xa3, 0xd5, 0xbf, 0xf9, 0x6f, 0x26, 0x33, 0x8d, 0x77, - 0x69, 0xa2, 0x66, 0xbf, 0x95, 0x65, 0x68, 0xa8, 0xd4, 0x78, 0xeb, 0xdb, - 0xc6, 0x8e, 0xbc, 0xd4, 0x59, 0xd7, 0xca, 0xaf, 0x38, 0x9d, 0x76, 0xda, - 0xb2, 0x75, 0xd8, 0x03, 0xaf, 0xff, 0x76, 0x16, 0xfe, 0xcd, 0xff, 0x5f, - 0xde, 0x9d, 0x7f, 0x7b, 0x27, 0xcf, 0xe6, 0x3a, 0xff, 0x7c, 0xc1, 0x7e, - 0x7f, 0xb6, 0x75, 0xff, 0xf9, 0x6f, 0xdc, 0xdf, 0xfe, 0xb2, 0xfd, 0x9b, - 0xa0, 0x3a, 0x82, 0x89, 0x0c, 0x37, 0xbb, 0x58, 0x75, 0xdb, 0x5e, 0x3a, - 0xca, 0x93, 0xad, 0xfc, 0x1a, 0xd0, 0x0c, 0xdf, 0xff, 0xf9, 0x06, 0x1a, - 0x30, 0xbf, 0x91, 0xce, 0x26, 0xce, 0x3b, 0xfe, 0x75, 0x2b, 0x2a, 0x8d, - 0x9a, 0x3c, 0x82, 0xb3, 0x26, 0xf6, 0x17, 0xee, 0x45, 0xfa, 0x17, 0x89, - 0xef, 0xe6, 0x60, 0x47, 0x3c, 0x75, 0xf3, 0xf5, 0x26, 0x3a, 0xfb, 0xb3, - 0x40, 0x4e, 0xac, 0x3e, 0xe6, 0x95, 0xb9, 0x0d, 0xfe, 0x6a, 0x60, 0x87, - 0xb0, 0x75, 0x1d, 0x7e, 0xeb, 0xfa, 0x5f, 0x9d, 0x7f, 0xfb, 0xe7, 0x5d, - 0x3d, 0xf8, 0x04, 0x5e, 0x47, 0x56, 0x22, 0xb1, 0xa6, 0x08, 0x14, 0xb2, - 0x8b, 0xff, 0xff, 0xff, 0xff, 0xca, 0xbd, 0x51, 0x8a, 0xbd, 0x54, 0xad, - 0x15, 0xa3, 0x55, 0x30, 0xab, 0x95, 0x5c, 0x9f, 0x6b, 0x00, 0x15, 0x6b, - 0x1b, 0x7b, 0xfd, 0xea, 0xaa, 0x21, 0x54, 0xae, 0xab, 0x7b, 0xe7, 0xce, - 0xed, 0x9d, 0x7f, 0xfe, 0xff, 0x79, 0x74, 0x11, 0xc6, 0x3a, 0x8d, 0x7e, - 0x1d, 0x7f, 0xf6, 0xec, 0xc7, 0x82, 0x8a, 0xfa, 0x85, 0x9d, 0x7f, 0xff, - 0xe4, 0x5a, 0x73, 0xa0, 0xd4, 0xa3, 0x67, 0x20, 0x7d, 0xdc, 0x91, 0xd7, - 0xfe, 0x4f, 0x23, 0x50, 0x3e, 0xc6, 0x9d, 0x58, 0x8f, 0x0f, 0x24, 0x6d, - 0x36, 0x5f, 0x7b, 0x6f, 0x3a, 0x75, 0xff, 0xfe, 0x71, 0x68, 0xe0, 0x7a, - 0x0f, 0x9d, 0x89, 0x72, 0x27, 0x3a, 0xb1, 0x10, 0xa0, 0x24, 0xbf, 0xff, - 0xce, 0xa0, 0xe7, 0xe0, 0xd7, 0xc9, 0x27, 0x61, 0xa2, 0xe7, 0x5f, 0x79, - 0x3a, 0x87, 0x5f, 0xf3, 0xf2, 0x5f, 0x31, 0xa1, 0xc3, 0xa9, 0x54, 0xb8, - 0x0d, 0x11, 0x95, 0xe4, 0x69, 0x1d, 0x85, 0xbb, 0x91, 0x0b, 0x08, 0x08, - 0x2d, 0xc3, 0xaf, 0xef, 0x62, 0xf7, 0xc5, 0x9d, 0x6e, 0xe1, 0xbd, 0x41, - 0x0b, 0xfc, 0x00, 0xbc, 0xb4, 0x92, 0x3a, 0xff, 0xfc, 0x14, 0x19, 0xf3, - 0x48, 0xfd, 0x61, 0x96, 0x59, 0x2a, 0xfe, 0xf7, 0x62, 0x7e, 0x80, 0xeb, - 0xfb, 0x79, 0x6b, 0xf0, 0x4c, 0x75, 0xff, 0x4f, 0x9f, 0x84, 0x0f, 0xc9, - 0x1d, 0x79, 0xdd, 0xa6, 0x8b, 0x3e, 0xfe, 0xfd, 0xc6, 0x48, 0xb3, 0xaa, - 0x74, 0x46, 0xb4, 0xeb, 0xf2, 0x7b, 0xff, 0x27, 0x62, 0x49, 0xe8, 0xf6, - 0x8e, 0xbf, 0xfd, 0xce, 0xbf, 0xcc, 0xd8, 0x39, 0xac, 0x13, 0xaf, 0xfe, - 0xd7, 0x92, 0x66, 0x5c, 0x31, 0xbe, 0x8e, 0xa4, 0x44, 0x80, 0x12, 0xaf, - 0x32, 0xcb, 0x25, 0x5f, 0xf9, 0xe5, 0xa1, 0xc6, 0x87, 0x38, 0x53, 0x05, - 0xfd, 0xfb, 0x68, 0x0b, 0xc0, 0x9d, 0x7f, 0xbd, 0xdc, 0xd9, 0xf2, 0x4b, - 0x3a, 0xb0, 0xf8, 0x40, 0x55, 0x7f, 0xed, 0xe4, 0x20, 0xff, 0xe3, 0x57, - 0xf9, 0xd7, 0x42, 0x87, 0x54, 0x1e, 0xd4, 0xe8, 0x97, 0xfb, 0xa8, 0x11, - 0x77, 0x98, 0xeb, 0xfc, 0x1e, 0x81, 0xff, 0xdb, 0xc3, 0xaa, 0x0f, 0x9d, - 0x0c, 0x6f, 0xf9, 0x04, 0x3f, 0x42, 0x0f, 0x68, 0xeb, 0xd0, 0x2a, 0x1d, - 0x52, 0x5d, 0x00, 0x09, 0x2b, 0x4c, 0xb7, 0x58, 0x98, 0xbb, 0x90, 0xbe, - 0x59, 0x97, 0x61, 0x99, 0xfa, 0x08, 0xc2, 0xb7, 0x4f, 0x7e, 0x84, 0x4e, - 0xc2, 0x0f, 0xa7, 0x57, 0xfd, 0xc7, 0x67, 0xa9, 0x1c, 0x83, 0xaf, 0xfd, - 0xc4, 0xd4, 0xbe, 0xf6, 0x06, 0x0e, 0xbe, 0xe2, 0x42, 0xce, 0xbf, 0xff, - 0x79, 0x40, 0x46, 0x07, 0xb9, 0xad, 0xe5, 0x1d, 0x3a, 0xb8, 0x8b, 0x45, - 0x9f, 0x09, 0x05, 0xcf, 0x23, 0xaf, 0xff, 0xff, 0xe1, 0x76, 0x7d, 0x9d, - 0x1c, 0xf0, 0x3f, 0x5b, 0xc9, 0xc3, 0x02, 0xfc, 0x79, 0x1d, 0x7f, 0xb3, - 0xbd, 0x07, 0x9c, 0x4e, 0xbe, 0x5a, 0x4d, 0xa3, 0xac, 0x81, 0x47, 0x6c, - 0xc2, 0xbc, 0x84, 0x2a, 0xcc, 0x6f, 0xdc, 0x9b, 0x66, 0x04, 0xeb, 0xff, - 0x63, 0x3b, 0x5c, 0xcd, 0xa1, 0x03, 0x27, 0x54, 0x27, 0xa7, 0xd8, 0xc7, - 0x1d, 0x20, 0x4a, 0xaf, 0xff, 0xff, 0xbf, 0xd6, 0x60, 0xa9, 0xf7, 0x83, - 0x19, 0xd6, 0x34, 0x39, 0x3a, 0xf1, 0x67, 0x5f, 0xbe, 0xc0, 0xfd, 0x59, - 0xd5, 0x88, 0xa9, 0xf3, 0xfd, 0xfb, 0x63, 0xf6, 0x3e, 0x9d, 0x58, 0x79, - 0x88, 0x45, 0x7b, 0x51, 0x39, 0xd7, 0xfd, 0x18, 0xde, 0xa6, 0xc7, 0xe1, - 0xd7, 0x67, 0x4e, 0xa1, 0x3c, 0xdd, 0xb3, 0x8a, 0x92, 0x2b, 0x74, 0x41, - 0xe6, 0x9b, 0xdd, 0x03, 0x27, 0x5e, 0xfc, 0x0d, 0x3a, 0xf7, 0xb3, 0xe9, - 0xd7, 0xf4, 0x6f, 0xaf, 0x9c, 0x83, 0xaf, 0x04, 0x0d, 0x3a, 0xf8, 0x23, - 0x12, 0x3a, 0x90, 0xde, 0x38, 0xe5, 0x05, 0x1c, 0x3b, 0x8e, 0xa0, 0xea, - 0xc7, 0x7a, 0xd7, 0x76, 0x34, 0xeb, 0xfb, 0x89, 0xb3, 0x07, 0x47, 0x5f, - 0xdb, 0xfb, 0x3a, 0x05, 0x73, 0xaf, 0xee, 0x67, 0x7a, 0x0f, 0x1d, 0x7e, - 0xe8, 0xc6, 0x70, 0xcb, 0xfb, 0x39, 0x38, 0x1c, 0x26, 0x88, 0x35, 0x83, - 0x4b, 0x6e, 0x4e, 0x89, 0xd9, 0x29, 0x54, 0x23, 0xe1, 0x21, 0x9d, 0x7e, - 0x76, 0xa2, 0xe0, 0xeb, 0xfa, 0x5d, 0x17, 0xdf, 0xc7, 0x5b, 0x1a, 0x7a, - 0x42, 0x4b, 0x7e, 0x8f, 0x7c, 0x5b, 0x27, 0x5f, 0xe9, 0x22, 0xe3, 0xbf, - 0x42, 0x75, 0xff, 0xe8, 0xc1, 0xdf, 0xd9, 0xc4, 0x9d, 0xd6, 0x75, 0xf9, - 0xd9, 0xf6, 0x77, 0x47, 0xf9, 0xe3, 0x4a, 0x56, 0xd5, 0x5e, 0xc0, 0xac, - 0xa3, 0x25, 0xc7, 0x8e, 0x13, 0x0c, 0x29, 0xaf, 0x6b, 0x24, 0x75, 0xf9, - 0x37, 0x92, 0x09, 0xd7, 0x93, 0xb8, 0x75, 0xd0, 0xbc, 0x3c, 0x06, 0x93, - 0x5f, 0x07, 0x5d, 0x83, 0xaf, 0xc3, 0xc6, 0x5e, 0x73, 0xab, 0x0f, 0x25, - 0xc8, 0x6e, 0x00, 0x9d, 0x50, 0x98, 0x2a, 0x2d, 0xf1, 0xd7, 0x44, 0x17, - 0xbb, 0x82, 0x75, 0xfe, 0x9a, 0x27, 0x5b, 0xcd, 0x07, 0x5f, 0xff, 0x3a, - 0x9e, 0x8e, 0x7f, 0xc8, 0xf0, 0xbf, 0xe7, 0x5f, 0xff, 0xc2, 0xea, 0x7c, - 0xfa, 0x2f, 0xed, 0x26, 0xfd, 0x46, 0x4e, 0xac, 0x47, 0xeb, 0x8d, 0x09, - 0xa0, 0x14, 0x2e, 0xd6, 0xc3, 0xaf, 0x90, 0x5c, 0x27, 0x5f, 0xf9, 0x79, - 0xed, 0x7d, 0xd3, 0xcb, 0x0e, 0xbf, 0x6a, 0x39, 0xe8, 0x39, 0x83, 0x7f, - 0x41, 0x44, 0xae, 0x97, 0xaf, 0xdf, 0x66, 0x77, 0xe1, 0xd7, 0xdd, 0xc4, - 0xd8, 0x75, 0xfd, 0xa4, 0xe6, 0x03, 0x87, 0x5f, 0xff, 0xe8, 0x9b, 0xe2, - 0x34, 0x1c, 0xd0, 0x3e, 0x2d, 0x3d, 0xd4, 0x3a, 0xb1, 0x3a, 0xc4, 0x85, - 0x6a, 0xc8, 0xfa, 0x53, 0xe2, 0x2d, 0xa2, 0xcb, 0x96, 0xa8, 0x34, 0x5f, - 0x97, 0xda, 0xe6, 0x61, 0xd7, 0xff, 0x4b, 0xc0, 0x94, 0x97, 0xef, 0x42, - 0xce, 0xbf, 0xde, 0xd4, 0x4f, 0x9a, 0x09, 0xd7, 0x77, 0x0e, 0xbf, 0xfe, - 0xec, 0x07, 0x1b, 0xf3, 0x07, 0x03, 0xd8, 0x3a, 0xff, 0xe4, 0xc1, 0xcc, - 0xd7, 0xc9, 0x69, 0x67, 0x5f, 0xf9, 0xe3, 0x79, 0x7c, 0xd6, 0xe1, 0x83, - 0xa8, 0x29, 0xbf, 0xee, 0x40, 0x88, 0xaa, 0xe6, 0x73, 0x0a, 0xe9, 0x3b, - 0xc8, 0x77, 0x94, 0x8e, 0x1d, 0x7f, 0x06, 0x3f, 0xe6, 0x6e, 0x75, 0x30, - 0x79, 0x4b, 0x1c, 0xbf, 0xd0, 0xbc, 0x4e, 0x4d, 0x23, 0xae, 0x49, 0x8e, - 0xbf, 0xfd, 0xe8, 0xe8, 0xbc, 0xf1, 0xce, 0x3c, 0x8e, 0xbd, 0xe4, 0x9c, - 0xeb, 0xf7, 0xef, 0xbc, 0x4c, 0x75, 0xe1, 0x86, 0x9d, 0x7f, 0xf0, 0x52, - 0x6e, 0xc7, 0x37, 0x94, 0x70, 0xeb, 0xff, 0x85, 0xf7, 0xd6, 0xb3, 0x81, - 0xee, 0x1d, 0x7f, 0xfa, 0x1b, 0xf3, 0x98, 0x80, 0x54, 0xe6, 0xd6, 0x1d, - 0x48, 0x89, 0x31, 0x43, 0xaf, 0x89, 0xdb, 0x20, 0xb2, 0xd2, 0x1c, 0x70, - 0x4a, 0x74, 0x35, 0xb5, 0x0d, 0x8b, 0x41, 0xd7, 0xba, 0x9e, 0x3a, 0xdb, - 0x30, 0xd5, 0x7d, 0x0f, 0xa8, 0x5d, 0x82, 0x0a, 0xf6, 0x47, 0x4c, 0x90, - 0xb3, 0xe9, 0x1b, 0xc7, 0xd1, 0xfc, 0x25, 0xaf, 0xfb, 0x06, 0x43, 0x8b, - 0x86, 0x9d, 0x7e, 0xea, 0x6c, 0xc0, 0x9d, 0x7f, 0xe0, 0xc0, 0xe0, 0x82, - 0x59, 0xa3, 0xaf, 0xce, 0xb4, 0xda, 0xc3, 0xaf, 0x7a, 0x37, 0x3a, 0xb0, - 0xf1, 0x1c, 0xa2, 0xf4, 0x24, 0xc7, 0x5e, 0x15, 0x67, 0x68, 0xeb, 0xf6, - 0x4e, 0xb8, 0xd1, 0xd7, 0xff, 0xfe, 0x8e, 0xa2, 0xd8, 0x9a, 0x4f, 0xcf, - 0xbd, 0x4d, 0xf4, 0xd4, 0x9c, 0xea, 0x0a, 0x7a, 0x4a, 0x1a, 0xa1, 0x44, - 0xcf, 0xfd, 0x20, 0x11, 0xbd, 0x11, 0xed, 0x13, 0xdf, 0xcf, 0xc8, 0xef, - 0xd0, 0x9d, 0x7d, 0x09, 0x3c, 0x1d, 0x7c, 0xcb, 0xe6, 0x8e, 0xbf, 0xe9, - 0x2d, 0xe5, 0xed, 0x42, 0x87, 0x54, 0x1e, 0xd3, 0x90, 0xde, 0xd2, 0x09, - 0xd7, 0xe1, 0x6f, 0xcd, 0x6e, 0x75, 0x61, 0xe2, 0x38, 0xd5, 0x3a, 0x65, - 0x9f, 0x97, 0x0b, 0xd0, 0x19, 0x2e, 0x9e, 0x47, 0x5e, 0x4e, 0xa1, 0xd5, - 0xb9, 0xb1, 0xf0, 0xbd, 0xf7, 0xd0, 0x3e, 0x8e, 0xbf, 0xd2, 0x00, 0xcf, - 0xa4, 0xdc, 0xeb, 0xef, 0xff, 0xcd, 0xce, 0xbf, 0xb6, 0xbd, 0x8e, 0x2d, - 0x3a, 0xff, 0x80, 0xf2, 0x0e, 0x67, 0xfa, 0x3a, 0xff, 0x7e, 0x9b, 0xef, - 0x2c, 0xf1, 0xd5, 0xd3, 0xed, 0xd1, 0xc5, 0xfb, 0x7d, 0x2d, 0x15, 0xce, - 0xbf, 0xff, 0x66, 0xbe, 0x75, 0xd3, 0xdf, 0x80, 0x45, 0xe4, 0x75, 0x42, - 0x20, 0x04, 0xae, 0xfe, 0x79, 0xff, 0x71, 0x09, 0xd5, 0x32, 0x7c, 0x7c, - 0x34, 0xe9, 0x27, 0xa1, 0x37, 0xb2, 0x14, 0x5b, 0x64, 0x37, 0xfd, 0xdf, - 0xb0, 0xdd, 0xbc, 0xe4, 0x1d, 0x50, 0xaa, 0xab, 0x25, 0x03, 0x3b, 0x45, - 0xd3, 0x00, 0xeb, 0x2c, 0xea, 0xdc, 0xd3, 0xaa, 0x45, 0xef, 0xfe, 0x8e, - 0x66, 0xc7, 0x97, 0xf9, 0x81, 0x3a, 0xfe, 0x7d, 0xe4, 0x30, 0x13, 0xaf, - 0xfa, 0x37, 0x92, 0x0a, 0xdf, 0xc7, 0x53, 0x9f, 0x18, 0x96, 0x5f, 0x9e, - 0x59, 0x3c, 0x1d, 0x7f, 0xf4, 0x6b, 0x58, 0xbf, 0x0c, 0x2f, 0x47, 0x5f, - 0xfc, 0x91, 0xa1, 0x79, 0x7c, 0xd6, 0x70, 0xeb, 0xff, 0xfc, 0x9a, 0x9f, - 0x19, 0xc1, 0x06, 0xd4, 0x31, 0x82, 0xfc, 0x3a, 0xff, 0x6f, 0x2d, 0x4d, - 0x28, 0x9c, 0xea, 0x0a, 0x68, 0x6d, 0x26, 0x14, 0x2f, 0x21, 0x81, 0x8a, - 0xff, 0xff, 0xdd, 0x4d, 0xfd, 0x9b, 0xfb, 0x9c, 0x8f, 0x7f, 0xf4, 0x65, - 0xdc, 0x3a, 0xf8, 0x21, 0x71, 0x3a, 0xff, 0xd2, 0x81, 0xf7, 0x13, 0x66, - 0x04, 0xeb, 0xff, 0x3f, 0x5a, 0x8f, 0xf3, 0x4f, 0xd3, 0xaf, 0xff, 0xda, - 0x1f, 0x9d, 0x74, 0xf7, 0xe0, 0x11, 0x79, 0x1d, 0x7f, 0xba, 0x8a, 0x6d, - 0x83, 0x8a, 0x1d, 0x7f, 0xd0, 0xca, 0xfb, 0x08, 0x33, 0x9d, 0x7f, 0xfc, - 0x39, 0xac, 0x5c, 0x37, 0x3c, 0x9c, 0xc3, 0xad, 0x8d, 0x45, 0xdf, 0x8e, - 0x36, 0x1c, 0x5f, 0xd3, 0xe7, 0x11, 0xb0, 0x75, 0xf0, 0x86, 0x16, 0x75, - 0xfb, 0x66, 0x08, 0x1c, 0xeb, 0xf9, 0xff, 0xc0, 0xbc, 0x8e, 0xa8, 0x3f, - 0x3c, 0x20, 0x42, 0x7a, 0x44, 0x65, 0xf6, 0x13, 0xf5, 0x0b, 0xb7, 0xf3, - 0x93, 0x06, 0x14, 0xf9, 0x1b, 0x1b, 0x52, 0x91, 0xc2, 0x62, 0x0e, 0x9f, - 0x7e, 0x7c, 0x31, 0x88, 0x7a, 0x30, 0x2b, 0xff, 0xb0, 0x7f, 0xcc, 0xe6, - 0xbd, 0x18, 0x75, 0xff, 0x6f, 0xec, 0xe2, 0x4e, 0xeb, 0x3a, 0xd9, 0xf9, - 0xfd, 0x0a, 0x0d, 0xe5, 0x4c, 0x90, 0xeb, 0xe8, 0x17, 0x91, 0xd7, 0xec, - 0x57, 0x71, 0xff, 0xe1, 0xbe, 0xe0, 0xfd, 0xfd, 0xb3, 0xa9, 0x1c, 0xd1, - 0xd7, 0xff, 0xe8, 0x19, 0x67, 0x51, 0x61, 0xc9, 0xa3, 0x38, 0x75, 0xf3, - 0x7a, 0x93, 0x1d, 0x7f, 0xfe, 0x1c, 0x51, 0x44, 0x0f, 0x52, 0x6e, 0xa6, - 0xfe, 0x3a, 0xa0, 0xfe, 0x70, 0x8a, 0xf3, 0x5f, 0x87, 0x5f, 0xb4, 0xd8, - 0xe2, 0x87, 0x57, 0x4f, 0x0f, 0xf1, 0xbb, 0xfd, 0x92, 0xc4, 0x0f, 0x50, - 0xeb, 0xef, 0x49, 0x7d, 0x3a, 0xf9, 0x14, 0x46, 0x4e, 0xac, 0x3c, 0x41, - 0x22, 0xbb, 0xe6, 0x1d, 0x7d, 0xa1, 0x85, 0x9d, 0x50, 0x6d, 0xf7, 0x17, - 0xbe, 0xce, 0xc9, 0x67, 0x54, 0x2b, 0x33, 0x93, 0x2e, 0x21, 0x28, 0x5d, - 0xd8, 0x65, 0xbb, 0x18, 0x91, 0xe9, 0xd0, 0x0a, 0xfb, 0x64, 0x37, 0x82, - 0xb6, 0x9d, 0x6e, 0x9d, 0x76, 0xa4, 0x75, 0x7e, 0x69, 0x80, 0x21, 0x7f, - 0x4f, 0x34, 0x95, 0x5c, 0x9c, 0xeb, 0xcf, 0x9c, 0x3a, 0xf0, 0xe7, 0x8e, - 0xae, 0x9b, 0x41, 0x1a, 0xbb, 0xc2, 0x75, 0xe8, 0xdf, 0x47, 0x5f, 0x20, - 0xcb, 0x0e, 0xbd, 0x3b, 0x89, 0xd4, 0x13, 0xd6, 0x58, 0xe7, 0x87, 0xef, - 0xd9, 0xee, 0xa7, 0x8e, 0xbf, 0x3e, 0xf9, 0xbf, 0x8e, 0xb2, 0x9d, 0x3c, - 0xef, 0x13, 0x5c, 0x9c, 0x3a, 0xfe, 0x9f, 0xe4, 0xee, 0xfd, 0x3a, 0x95, - 0x94, 0xf7, 0xe1, 0xa6, 0x44, 0x18, 0xd6, 0x8f, 0xbd, 0x29, 0x71, 0x5b, - 0xfe, 0xc0, 0x85, 0x37, 0xcd, 0xfc, 0x75, 0xf3, 0x46, 0x24, 0x75, 0x74, - 0xf6, 0x5c, 0xe6, 0xff, 0x46, 0x7a, 0x3a, 0xe1, 0x3a, 0xa7, 0x3d, 0x10, - 0x90, 0xdf, 0xfc, 0x18, 0x0f, 0x23, 0xc8, 0xd4, 0x09, 0xd7, 0xd3, 0x46, - 0xd4, 0x8e, 0xbf, 0xbc, 0xd0, 0x85, 0x7c, 0x3a, 0xff, 0xa6, 0xd6, 0xc7, - 0x19, 0xc0, 0x13, 0xaf, 0xb3, 0xd8, 0xb3, 0xae, 0x15, 0x0e, 0xb6, 0x9c, - 0xdb, 0x00, 0x82, 0xfe, 0xe8, 0x27, 0x9b, 0xa8, 0x75, 0xf0, 0x8e, 0x78, - 0xea, 0x84, 0xe7, 0x82, 0x47, 0x88, 0x4a, 0x12, 0xa1, 0x74, 0xce, 0x5d, - 0x26, 0xf1, 0x7d, 0xfd, 0xf2, 0x68, 0xf0, 0xec, 0x3a, 0xff, 0xf0, 0xc6, - 0xce, 0x47, 0x31, 0x3b, 0x01, 0x3a, 0xf0, 0xba, 0xce, 0xa9, 0x22, 0x4f, - 0x0c, 0x51, 0x22, 0xcc, 0x2b, 0x2e, 0xe9, 0xf9, 0x5b, 0x3c, 0x56, 0x83, - 0x8a, 0xd4, 0x6e, 0x25, 0x2d, 0x4f, 0x0e, 0xb9, 0x43, 0x64, 0x33, 0x88, - 0x39, 0x3b, 0x6a, 0xa4, 0x37, 0x1b, 0x2a, 0xfb, 0x78, 0xf8, 0xd2, 0x31, - 0x19, 0xa5, 0x83, 0xf2, 0x36, 0xb5, 0xc6, 0x73, 0xd9, 0xf6, 0x87, 0x94, - 0x99, 0xfc, 0x74, 0x2a, 0x96, 0xe1, 0x95, 0x99, 0xa9, 0xe1, 0xcf, 0x4e, - 0x2f, 0x02, 0x12, 0x4c, 0xa1, 0x6d, 0xca, 0x01, 0xfb, 0x2a, 0xbb, 0x6a, - 0x30, 0x4a, 0x61, 0xde, 0x82, 0x76, 0xdd, 0x67, 0x5f, 0xfe, 0x61, 0x6f, - 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x6c, 0xbf, 0xcc, 0x67, 0x1a, 0xee, - 0xd3, 0x45, 0x5b, 0x7f, 0xa5, 0x20, 0x78, 0x62, 0x47, 0x5f, 0x67, 0x5f, - 0xc7, 0x59, 0x51, 0x87, 0xa4, 0x26, 0x57, 0xfb, 0x98, 0xd8, 0xff, 0xea, - 0xce, 0xbf, 0xe8, 0xec, 0x4f, 0xc8, 0xc0, 0x9d, 0x5c, 0x3e, 0xce, 0x9a, - 0xdf, 0xa3, 0x8b, 0xe8, 0x4e, 0xbc, 0x1c, 0x13, 0xaf, 0x3b, 0xb4, 0xd1, - 0x5a, 0x5f, 0x94, 0xdf, 0x40, 0xdc, 0xea, 0x69, 0xe9, 0x21, 0x3d, 0xff, - 0xe4, 0xf4, 0xa1, 0xbd, 0x4f, 0x69, 0xf7, 0x3a, 0xb8, 0x7d, 0x5b, 0x08, - 0x6f, 0xff, 0x75, 0x17, 0x0d, 0xc5, 0xe0, 0xfb, 0x6c, 0xeb, 0xff, 0xe6, - 0xc7, 0x33, 0xf7, 0x5b, 0xca, 0x11, 0xa7, 0x5f, 0xff, 0x4b, 0x58, 0x30, - 0xb7, 0xcf, 0x7a, 0x16, 0x75, 0xde, 0xf4, 0x22, 0x65, 0xd3, 0x6f, 0xff, - 0xff, 0x46, 0xc4, 0xf6, 0xb1, 0x46, 0xf5, 0x3d, 0x93, 0x0c, 0x2e, 0x7c, - 0x64, 0xeb, 0xfd, 0x1e, 0x7e, 0xfc, 0x0c, 0x1d, 0x7d, 0x2f, 0x24, 0xe7, - 0x5f, 0xbe, 0xf8, 0x63, 0xf3, 0xab, 0x73, 0xcb, 0xd8, 0x45, 0x7f, 0x9e, - 0x5e, 0x49, 0xfa, 0x87, 0x54, 0x1e, 0xba, 0x12, 0xdf, 0xb3, 0xa9, 0x8b, - 0x3a, 0xff, 0xe1, 0x74, 0x6f, 0x5c, 0x13, 0xf1, 0x0e, 0xa9, 0xcf, 0x9f, - 0xa4, 0xb7, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7b, 0x39, 0xf9, 0xd7, - 0xe9, 0xb0, 0x2b, 0x57, 0x3a, 0xfe, 0x18, 0x67, 0x79, 0x68, 0xea, 0x43, - 0xf5, 0x98, 0x73, 0x68, 0xae, 0xa1, 0x1b, 0x79, 0x0a, 0x9b, 0xff, 0xff, - 0xfb, 0x11, 0xb9, 0xe8, 0x1f, 0x6b, 0xe4, 0x20, 0x71, 0x7f, 0x39, 0x09, - 0x27, 0xd1, 0xd7, 0xf6, 0x79, 0xc7, 0xf0, 0x1d, 0x7f, 0x77, 0xe2, 0x4e, - 0xe2, 0x75, 0x48, 0xf6, 0xb0, 0xb2, 0xcc, 0x2a, 0x97, 0xb9, 0x62, 0x12, - 0xd3, 0x91, 0x04, 0x9f, 0x21, 0xac, 0xd2, 0x44, 0x87, 0x1f, 0x0b, 0x56, - 0xf5, 0xd8, 0x6a, 0xbc, 0x21, 0xc6, 0x1f, 0xda, 0x26, 0xf4, 0x38, 0x6f, - 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x60, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, - 0x27, 0x5b, 0xff, 0xfd, 0xd8, 0x9c, 0x38, 0xb6, 0x35, 0xac, 0xea, 0x68, - 0x13, 0x9d, 0x7e, 0x61, 0x6f, 0x26, 0x31, 0x12, 0xd3, 0x19, 0xdf, 0xe9, - 0x69, 0x85, 0x14, 0x85, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb6, 0x6f, - 0xff, 0xf3, 0xc9, 0x8d, 0x42, 0x60, 0x53, 0x35, 0x9e, 0x18, 0x3a, 0xff, - 0xdf, 0xc6, 0x98, 0xea, 0x35, 0xf8, 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, - 0x27, 0x3a, 0xcc, 0x62, 0x60, 0xeb, 0x33, 0x75, 0xc1, 0x3f, 0xbf, 0xff, - 0x3f, 0xff, 0x83, 0x4c, 0x67, 0x1f, 0x5d, 0x79, 0x1d, 0x7c, 0xd7, 0x76, - 0x9a, 0x2e, 0x6b, 0x2c, 0xea, 0xe1, 0xbd, 0x64, 0xb6, 0xff, 0x70, 0x73, - 0x7f, 0xd2, 0x47, 0x5d, 0x32, 0xce, 0xa3, 0xac, 0xc6, 0x1f, 0xb2, 0x11, - 0x32, 0x67, 0xb6, 0x2f, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xbb, 0xef, 0xf4, - 0x98, 0xd7, 0x38, 0x8c, 0x9d, 0x66, 0x30, 0xfa, 0x1c, 0xce, 0xf9, 0x85, - 0x03, 0xf9, 0xd5, 0x0f, 0x95, 0x6f, 0x96, 0xf4, 0xc1, 0xa6, 0xbb, 0xab, - 0xa4, 0xfb, 0xb7, 0x21, 0xd8, 0xb8, 0x6a, 0xba, 0x17, 0xf1, 0x9e, 0x8a, - 0x16, 0xa3, 0x0a, 0xf4, 0x2b, 0x7e, 0x93, 0xdf, 0xf9, 0x97, 0x19, 0xf4, - 0x83, 0xbc, 0x8e, 0xbf, 0xfb, 0x27, 0xc6, 0x7b, 0x9a, 0xc4, 0x13, 0xae, - 0x46, 0x3a, 0x88, 0x11, 0x3f, 0xbf, 0x6b, 0x4b, 0x79, 0x1d, 0x7f, 0xff, - 0xff, 0xee, 0xa7, 0x52, 0x07, 0xc2, 0xea, 0x67, 0x81, 0xe4, 0xf6, 0xba, - 0x9c, 0x89, 0xdf, 0x8d, 0x3a, 0xed, 0x41, 0xd7, 0xff, 0x6e, 0xd0, 0x3e, - 0xfe, 0xcc, 0x15, 0x0e, 0xbc, 0x2e, 0xc4, 0x26, 0x30, 0xd2, 0x7d, 0x42, - 0x5f, 0xc2, 0xb7, 0x80, 0xeb, 0x3a, 0xfd, 0x9b, 0x5e, 0x85, 0x0e, 0xb6, - 0xd1, 0xd5, 0x39, 0xbd, 0xc2, 0xaa, 0xe1, 0xfc, 0x8a, 0xc5, 0xff, 0xb4, - 0xea, 0x75, 0x20, 0x41, 0x07, 0x5f, 0xfb, 0xaf, 0xe7, 0xee, 0xf2, 0xcf, - 0x1d, 0x58, 0x7f, 0x48, 0x79, 0x73, 0xfe, 0x75, 0xff, 0xff, 0xe1, 0x76, - 0x47, 0x3d, 0xec, 0x9e, 0x05, 0xd4, 0xd2, 0xe3, 0x04, 0x27, 0x56, 0x22, - 0x2b, 0x82, 0xd7, 0xfb, 0xb8, 0x14, 0xd9, 0xcc, 0x3a, 0xf3, 0xbb, 0x4d, - 0x12, 0xbd, 0xfe, 0x51, 0xc7, 0xff, 0x67, 0x4e, 0xa6, 0x9e, 0xd2, 0x13, - 0xdf, 0xfe, 0xf7, 0x72, 0x4d, 0xea, 0x06, 0x07, 0xc7, 0x54, 0x91, 0xed, - 0xc8, 0x46, 0x89, 0x0d, 0xd2, 0x9c, 0xeb, 0xff, 0x0b, 0xb2, 0x1e, 0xc4, - 0xf8, 0xc9, 0xd7, 0xff, 0xec, 0x4f, 0xf1, 0x69, 0xed, 0x42, 0xdf, 0x7f, - 0x1d, 0x7f, 0xd0, 0xbf, 0x64, 0xd2, 0x4f, 0x1d, 0x52, 0x44, 0x67, 0x95, - 0x2f, 0x80, 0xfc, 0x91, 0xd7, 0xfd, 0x0d, 0x18, 0x9f, 0xf7, 0xf1, 0xd7, - 0xff, 0xf9, 0x3c, 0xeb, 0x71, 0xff, 0xac, 0xb8, 0xce, 0xd4, 0x9c, 0xea, - 0x0a, 0x2e, 0x90, 0x85, 0xce, 0x2f, 0xf8, 0x1f, 0xad, 0xe5, 0xae, 0x04, - 0xeb, 0xff, 0xfd, 0x88, 0x3e, 0xc1, 0xf8, 0x2e, 0x18, 0x19, 0xe3, 0x87, - 0x5b, 0x3c, 0x89, 0x7d, 0x87, 0x57, 0xfd, 0xbf, 0xf9, 0xcc, 0xcf, 0x68, - 0xea, 0x0a, 0xad, 0x0c, 0x86, 0x5f, 0x61, 0xba, 0x30, 0xc5, 0xfa, 0x55, - 0x7f, 0xef, 0x3c, 0xb5, 0xd8, 0xe7, 0xd0, 0x9d, 0x7f, 0xf7, 0x93, 0x62, - 0x7a, 0x69, 0x40, 0xf8, 0xeb, 0xff, 0xcf, 0x92, 0xee, 0x20, 0xe7, 0xfb, - 0x78, 0x75, 0xe7, 0x93, 0x10, 0xbd, 0x43, 0x28, 0x4d, 0x86, 0x15, 0x59, - 0x18, 0xc2, 0xcd, 0x35, 0x2b, 0x9f, 0xcb, 0x7f, 0x50, 0x36, 0x91, 0x6f, - 0xff, 0x67, 0x58, 0x1c, 0x0a, 0x0f, 0xb3, 0xa7, 0x5e, 0xf4, 0x04, 0xab, - 0xff, 0xdd, 0x74, 0xf4, 0x49, 0x39, 0x38, 0x3f, 0x2a, 0xff, 0x3b, 0x58, - 0x0f, 0x15, 0x2c, 0x41, 0xf2, 0xe8, 0x6e, 0xcc, 0x05, 0x94, 0xb8, 0xd8, - 0xd1, 0x97, 0x3e, 0xdb, 0xe8, 0x56, 0xec, 0x85, 0x65, 0xff, 0xe6, 0x16, - 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x26, 0x1b, 0xff, 0xfb, 0x36, 0x38, - 0x7b, 0x0c, 0x7b, 0xb8, 0x10, 0x7b, 0x47, 0x5f, 0xfe, 0xe3, 0xfe, 0xc2, - 0x9e, 0x93, 0x31, 0xa9, 0x1d, 0x76, 0x30, 0x28, 0xab, 0xfa, 0xbb, 0x7f, - 0xf2, 0xa3, 0x37, 0x90, 0x1f, 0xc3, 0x12, 0x3a, 0xfd, 0x8b, 0xf9, 0xba, - 0xb9, 0xd7, 0xf4, 0x2f, 0x3f, 0x8d, 0x87, 0x50, 0x4f, 0x6f, 0xa5, 0xb7, - 0xfb, 0x98, 0xd8, 0xff, 0xea, 0xce, 0xbf, 0x76, 0x02, 0x8a, 0x1d, 0x48, - 0x7f, 0xdc, 0x22, 0xda, 0x35, 0xbf, 0xd0, 0xf3, 0xf9, 0x47, 0xe1, 0xd7, - 0xe7, 0xe4, 0x9d, 0x67, 0x50, 0x9e, 0xc8, 0x0c, 0xef, 0xff, 0xc9, 0xce, - 0xbf, 0xc0, 0xe4, 0xbb, 0x1b, 0x03, 0x07, 0x5f, 0xf3, 0x3f, 0x7b, 0x0d, - 0xea, 0x4c, 0x75, 0xf0, 0x17, 0x81, 0x3a, 0xd9, 0xb9, 0xee, 0xed, 0x1e, - 0x57, 0x51, 0xbe, 0x30, 0xb4, 0xbf, 0x97, 0x18, 0x3e, 0xdb, 0x3a, 0xda, - 0x3a, 0xfd, 0x18, 0x3e, 0xdb, 0x3a, 0xfe, 0xea, 0x7b, 0x4f, 0xbf, 0xc3, - 0xe6, 0x98, 0xb9, 0x62, 0x17, 0xfa, 0x5e, 0x85, 0xec, 0xfe, 0x47, 0x5f, - 0xff, 0xe6, 0x76, 0xbd, 0x9d, 0xf8, 0x39, 0x3a, 0x60, 0xef, 0x2d, 0x1d, - 0x7e, 0x67, 0xd9, 0xd6, 0x9d, 0x61, 0xc4, 0x47, 0x3b, 0x35, 0xff, 0xef, - 0x0b, 0xff, 0xdc, 0x40, 0x83, 0xda, 0x3a, 0xff, 0xa2, 0x7f, 0xb2, 0xe8, - 0x1e, 0x73, 0xaa, 0x11, 0x0b, 0xc4, 0x9b, 0xff, 0xb3, 0x79, 0x7c, 0xeb, - 0xb6, 0x04, 0x27, 0x5f, 0xdb, 0x3e, 0xf8, 0x63, 0xf3, 0xaf, 0xff, 0x47, - 0xbf, 0x89, 0x66, 0xfe, 0x9c, 0x0c, 0x9d, 0x50, 0x7f, 0xc8, 0x63, 0x7f, - 0x3f, 0xfc, 0xe2, 0x70, 0xeb, 0xde, 0xf9, 0x87, 0x57, 0xe7, 0x95, 0xf4, - 0xb6, 0xfe, 0xd2, 0x28, 0xb7, 0xf1, 0xd7, 0xff, 0xfe, 0xe6, 0x6c, 0x81, - 0xf7, 0xcf, 0xa3, 0x1d, 0x74, 0xf4, 0x7b, 0x47, 0x5f, 0xc3, 0x9a, 0xf8, - 0xd5, 0x51, 0xd5, 0xba, 0x33, 0x78, 0x5b, 0xb1, 0xba, 0xfb, 0xe6, 0xcd, - 0xa9, 0xce, 0xac, 0x3d, 0xd5, 0x0c, 0xec, 0xae, 0x75, 0xde, 0xc3, 0xaf, - 0xff, 0x2a, 0x46, 0x16, 0xe9, 0xd7, 0xf7, 0x60, 0xea, 0x83, 0xdf, 0x00, - 0xad, 0xfe, 0xea, 0x4c, 0xed, 0xd4, 0x8e, 0xbf, 0xd0, 0x3e, 0x75, 0xa7, - 0x8e, 0xbf, 0xec, 0x4c, 0x58, 0xe4, 0xee, 0x75, 0xfa, 0x3d, 0xaf, 0xc0, - 0x75, 0x2b, 0x29, 0xa9, 0xe3, 0x93, 0x48, 0x7a, 0x66, 0x26, 0x1e, 0x35, - 0xbf, 0xff, 0x74, 0x73, 0xdd, 0x4c, 0xdf, 0xd9, 0xb2, 0x34, 0x75, 0xff, - 0xce, 0x3d, 0x84, 0x0a, 0x6b, 0x24, 0x75, 0xe8, 0xff, 0xe9, 0xd5, 0x88, - 0xb3, 0x75, 0x51, 0x40, 0xbd, 0xf4, 0x38, 0x75, 0xe5, 0x4e, 0x95, 0x47, - 0x53, 0x9e, 0x0e, 0x87, 0x6f, 0xf0, 0xbb, 0x31, 0xec, 0x9c, 0xeb, 0x30, - 0xaa, 0x65, 0x6e, 0xc4, 0x64, 0x01, 0x84, 0x56, 0x46, 0x00, 0xd8, 0x46, - 0xee, 0xab, 0x34, 0x31, 0x39, 0x0a, 0xb5, 0x91, 0x76, 0x18, 0x7f, 0xb5, - 0x0c, 0x69, 0xfa, 0x8d, 0xd7, 0xd1, 0x87, 0x01, 0xbb, 0x6c, 0x86, 0xff, - 0xfb, 0x89, 0xbc, 0xb4, 0x9e, 0xec, 0x73, 0xd0, 0x75, 0xfb, 0x8d, 0x77, - 0x69, 0xa2, 0xae, 0xbd, 0xc8, 0x59, 0xd7, 0xfd, 0x26, 0x33, 0x8d, 0x77, - 0x69, 0xa2, 0x3c, 0xbf, 0xe8, 0x94, 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0xfa, - 0x3c, 0x80, 0x54, 0xe4, 0xa7, 0x98, 0xeb, 0x30, 0x14, 0xd7, 0xb1, 0x3f, - 0x86, 0x6e, 0x36, 0x28, 0xba, 0x39, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x58, - 0x37, 0x94, 0x89, 0xce, 0xbf, 0xff, 0x84, 0x0f, 0x3a, 0xf3, 0x6c, 0x1c, - 0xce, 0x4b, 0xec, 0x8e, 0xbf, 0x60, 0xe7, 0xb4, 0x75, 0xfe, 0xe3, 0xaf, - 0xef, 0x1f, 0x73, 0xac, 0xc6, 0x26, 0x14, 0xa1, 0x9b, 0x47, 0x5d, 0x83, - 0xe9, 0x2d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2c, 0xab, 0xf7, 0x1a, - 0xee, 0xd3, 0x45, 0xa7, 0x7f, 0xce, 0x1e, 0xbc, 0xdd, 0x45, 0x9d, 0x66, - 0x30, 0xfa, 0xd6, 0x67, 0x7e, 0x56, 0x8a, 0xbd, 0x59, 0x56, 0x55, 0xb3, - 0xaf, 0xf9, 0x55, 0xd4, 0x64, 0x2e, 0xed, 0x3a, 0xfc, 0xad, 0x15, 0x1a, - 0xc8, 0x3a, 0xff, 0x7d, 0x5e, 0x7b, 0x49, 0xa3, 0xac, 0x87, 0x52, 0xa8, - 0xf0, 0xf6, 0xcd, 0x2f, 0xff, 0xe4, 0xeb, 0x8f, 0xa5, 0x9c, 0xc8, 0x11, - 0xcf, 0x1d, 0x7e, 0xd8, 0xe1, 0xc5, 0x9d, 0x7c, 0xb8, 0xdf, 0x47, 0x54, - 0x91, 0x3f, 0x8a, 0xb3, 0x14, 0x5f, 0xbe, 0x73, 0x80, 0xe9, 0xd7, 0xe4, - 0x52, 0x05, 0xa7, 0x5b, 0x34, 0x7a, 0x1e, 0x2a, 0xbf, 0xfe, 0x16, 0xf5, - 0x3a, 0x9c, 0x89, 0x99, 0xce, 0x9d, 0x7f, 0xe5, 0xad, 0xe5, 0xb6, 0x0e, - 0xa7, 0x0e, 0xbf, 0x3e, 0xbd, 0x01, 0x3a, 0xa0, 0xf9, 0xc0, 0x83, 0x50, - 0x8d, 0x7e, 0xc2, 0xda, 0xfa, 0x3e, 0xc7, 0x4e, 0xbe, 0x6b, 0xbb, 0x4d, - 0x16, 0xe5, 0xff, 0xb3, 0x98, 0x3f, 0x3b, 0x9b, 0xb2, 0x75, 0xf8, 0x7f, - 0x7d, 0xf4, 0x75, 0x41, 0xf4, 0x3a, 0x05, 0x6e, 0x8d, 0x7e, 0x11, 0x6a, - 0x12, 0xb7, 0xf9, 0xc7, 0xf9, 0x86, 0x16, 0x75, 0xe5, 0x8a, 0x1d, 0x61, - 0x3a, 0xff, 0xba, 0x07, 0xd6, 0x60, 0xa8, 0x75, 0xfb, 0x4f, 0xbb, 0x84, - 0xeb, 0x20, 0x4f, 0x7b, 0xc6, 0xf5, 0x08, 0xae, 0xc1, 0xae, 0xb6, 0xdf, - 0xf4, 0x38, 0xf7, 0x30, 0x5a, 0x75, 0xfe, 0xf7, 0x92, 0x75, 0xc0, 0x9d, - 0x52, 0x3e, 0x6c, 0x34, 0xbf, 0xe8, 0x10, 0x2e, 0x35, 0xe4, 0x3a, 0xf8, - 0x31, 0x9c, 0x3a, 0xfd, 0xf3, 0x7d, 0x22, 0x87, 0x59, 0xe7, 0x3c, 0xbd, - 0xc8, 0x2f, 0xfe, 0x96, 0x75, 0x38, 0x1e, 0xc0, 0xb4, 0xeb, 0xfd, 0xbc, - 0xa0, 0x7d, 0x9f, 0x9d, 0x7d, 0xaf, 0xd3, 0xc7, 0x53, 0xa3, 0x03, 0x45, - 0x20, 0x42, 0xfa, 0x67, 0x7f, 0xf7, 0x93, 0xf8, 0x90, 0x7b, 0x02, 0xd3, - 0xa8, 0xeb, 0xc0, 0x7f, 0x1d, 0x70, 0x20, 0xea, 0x91, 0xb0, 0xf0, 0xdd, - 0x1d, 0x7d, 0xbb, 0x53, 0x87, 0x5e, 0x85, 0xb1, 0x88, 0x87, 0xdc, 0xe9, - 0x64, 0x3e, 0x0a, 0xa8, 0x4c, 0x65, 0x21, 0x95, 0x78, 0x7d, 0xb6, 0x75, - 0xff, 0x49, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa1, 0xe9, 0x0f, 0x8d, 0xc7, - 0xaf, 0xdf, 0xc3, 0x71, 0x67, 0x5f, 0x44, 0xd8, 0x13, 0xab, 0x87, 0x91, - 0xa2, 0x7b, 0xfe, 0xc8, 0x0f, 0x63, 0x6a, 0x26, 0x3a, 0xff, 0x7e, 0x9d, - 0xee, 0x7e, 0xe7, 0x52, 0xcf, 0xb7, 0xf3, 0xaa, 0x84, 0x59, 0x3c, 0x23, - 0xef, 0xfc, 0xe1, 0x80, 0xf5, 0x05, 0x16, 0x75, 0xff, 0xda, 0x81, 0x9b, - 0x07, 0xf7, 0xf6, 0x1d, 0x7f, 0xb4, 0x06, 0xe7, 0x86, 0x0e, 0xa5, 0xa2, - 0xbb, 0xa7, 0x7e, 0x42, 0xbf, 0xf8, 0x12, 0xeb, 0xf3, 0x7f, 0x42, 0x4e, - 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, 0x27, 0x3a, 0xfc, 0x9e, 0xd3, 0xa1, - 0xd7, 0xfd, 0xcf, 0xf8, 0xe3, 0xec, 0xfc, 0xea, 0xfc, 0xf7, 0x80, 0x4b, - 0x7b, 0xef, 0x24, 0x75, 0xfd, 0xf7, 0xc0, 0x8c, 0x9c, 0xea, 0x91, 0xe6, - 0xcc, 0x3d, 0x7f, 0xf3, 0x46, 0x3c, 0x39, 0xb3, 0x39, 0x23, 0xaf, 0xf8, - 0x02, 0xa7, 0xde, 0xf4, 0x1a, 0x3a, 0xff, 0x08, 0xbf, 0xbe, 0xc3, 0x4e, - 0xbe, 0x1f, 0xe7, 0xfc, 0xea, 0xc3, 0xd6, 0x43, 0x2b, 0xfd, 0xaf, 0x9e, - 0xf8, 0x1c, 0x13, 0xad, 0xf9, 0xd6, 0x4d, 0xcf, 0x1f, 0x86, 0xd7, 0xe7, - 0xdf, 0x5e, 0x43, 0xaa, 0x13, 0xae, 0xc2, 0x34, 0x43, 0xec, 0x24, 0x85, - 0x9f, 0x45, 0x17, 0xe7, 0x02, 0x91, 0xf4, 0xeb, 0xf2, 0xab, 0x39, 0x1a, - 0x3a, 0xa6, 0x3d, 0x31, 0x29, 0xbf, 0xe7, 0xd4, 0x4d, 0xbc, 0xb3, 0x61, - 0xd7, 0xff, 0xe0, 0xf6, 0x3e, 0xb1, 0xe1, 0x7f, 0xf5, 0xa8, 0xfc, 0xab, - 0x83, 0x87, 0x5f, 0xa7, 0x89, 0xdf, 0x47, 0x56, 0x22, 0x59, 0x16, 0x5c, - 0x56, 0xef, 0xc0, 0x75, 0xfc, 0xff, 0xcc, 0x30, 0x13, 0xaa, 0x0f, 0x13, - 0xa2, 0xf6, 0x61, 0x58, 0x6c, 0x1b, 0x15, 0xb4, 0x35, 0x5e, 0x78, 0xab, - 0x39, 0xc4, 0x32, 0x25, 0x08, 0x00, 0xc3, 0xfb, 0x21, 0xfc, 0xa1, 0xb3, - 0x61, 0xc1, 0xbc, 0x25, 0x10, 0x86, 0x68, 0xd0, 0x79, 0x1a, 0xba, 0xe1, - 0x15, 0xd8, 0xc6, 0x9e, 0x1a, 0x9f, 0x98, 0x0a, 0x2e, 0xa1, 0x2f, 0xe9, - 0x43, 0xc0, 0x85, 0x66, 0xc2, 0x2d, 0xb8, 0x68, 0xfd, 0x71, 0xbf, 0x98, - 0x9e, 0x39, 0x25, 0x9d, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0xce, - 0xa1, 0xd2, 0x14, 0x49, 0xbc, 0x31, 0x81, 0x65, 0x2c, 0x37, 0x79, 0x50, - 0x1c, 0x8d, 0x99, 0x6a, 0x7d, 0x85, 0x50, 0xd6, 0x12, 0x9a, 0x8f, 0x17, - 0x61, 0x7d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x29, 0x6b, 0xf7, 0x1a, - 0xee, 0xd3, 0x45, 0x85, 0x7f, 0xfe, 0x8c, 0x10, 0xc7, 0x63, 0x7f, 0x60, - 0xba, 0xce, 0xbf, 0x81, 0xc4, 0x9d, 0xd6, 0x75, 0x98, 0xc4, 0x58, 0xac, - 0xcf, 0x6d, 0x46, 0xff, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, 0x5d, 0xdc, - 0x50, 0xeb, 0xe6, 0x14, 0x55, 0x95, 0x83, 0xaf, 0x31, 0xf5, 0x67, 0x53, - 0x4f, 0x34, 0x05, 0xd4, 0x28, 0x86, 0xd3, 0x25, 0xbf, 0x3a, 0xe5, 0x27, - 0x3a, 0xe7, 0xe4, 0x8d, 0x4e, 0x08, 0xdf, 0xf3, 0xee, 0x39, 0xbf, 0xa1, - 0x43, 0xaf, 0xf4, 0xfb, 0xea, 0x03, 0xe4, 0x3a, 0xfd, 0x19, 0xb2, 0x34, - 0x75, 0xa1, 0xcf, 0x6d, 0x93, 0x4a, 0x74, 0x5d, 0x8c, 0x25, 0x2f, 0x9e, - 0x52, 0x09, 0xd7, 0xf3, 0xf2, 0x3c, 0xfd, 0x3a, 0xf3, 0x2c, 0xb2, 0x55, - 0xff, 0x44, 0xb7, 0xf7, 0x23, 0x37, 0x29, 0x82, 0xfe, 0xff, 0x80, 0xfb, - 0xe7, 0x93, 0x76, 0x4e, 0xba, 0x34, 0x75, 0x05, 0x30, 0x3e, 0x90, 0x8a, - 0x56, 0x92, 0x76, 0x1d, 0x5f, 0xc8, 0xfa, 0xff, 0x40, 0x3a, 0xff, 0xfe, - 0xea, 0x7b, 0xb9, 0xa1, 0xc5, 0x83, 0x5d, 0x79, 0x1d, 0x7f, 0xa2, 0x5e, - 0x7e, 0xb8, 0x4e, 0xac, 0x44, 0x57, 0x16, 0x6d, 0x23, 0xad, 0x23, 0xad, - 0x23, 0xaa, 0x0d, 0x82, 0x82, 0x08, 0x21, 0x7f, 0xfe, 0xf6, 0x91, 0xb8, - 0x3c, 0x81, 0xc0, 0xe2, 0x87, 0x5b, 0x73, 0xae, 0xd0, 0x0e, 0xac, 0x3f, - 0x9d, 0x29, 0x78, 0x46, 0xe4, 0x83, 0xaf, 0xe1, 0x85, 0x8c, 0x61, 0xd7, - 0x4a, 0x0e, 0xa0, 0x9e, 0x94, 0xc2, 0x80, 0x29, 0xbf, 0xff, 0xfe, 0xec, - 0x7b, 0x49, 0xad, 0x47, 0xba, 0x91, 0xcf, 0xd6, 0xf2, 0x97, 0x94, 0x3a, - 0xe4, 0xdc, 0xeb, 0xa1, 0x67, 0x5f, 0xff, 0xd2, 0x81, 0x04, 0xa5, 0x1e, - 0xee, 0x2f, 0xec, 0x7e, 0x75, 0xcd, 0x62, 0x17, 0x82, 0xa7, 0x4b, 0x0c, - 0x39, 0xb2, 0x32, 0x96, 0xa6, 0x72, 0x16, 0xee, 0xa4, 0x30, 0xa6, 0xd4, - 0x20, 0x3c, 0x61, 0xb1, 0xfb, 0x6c, 0x5b, 0xe8, 0xad, 0xff, 0xe6, 0x16, - 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0xcb, 0xf6, 0xc8, 0xe4, 0x7e, - 0x75, 0xf8, 0x5f, 0xf8, 0xfa, 0x75, 0xff, 0xdb, 0xb5, 0x39, 0xdc, 0xc1, - 0x96, 0x8e, 0xb3, 0x10, 0x89, 0x4e, 0x94, 0xf8, 0xa2, 0xa4, 0xc9, 0xf9, - 0xe4, 0x3c, 0x16, 0x72, 0xf3, 0xd9, 0xfa, 0x87, 0x07, 0xa1, 0xd7, 0x7f, - 0xf3, 0x0f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x39, 0xbf, 0xfc, 0xc2, - 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xe5, 0x7f, 0x98, 0xce, 0x35, - 0xdd, 0xa6, 0x8b, 0x32, 0xff, 0xa5, 0xa7, 0x5b, 0x1d, 0xf7, 0xe7, 0x5f, - 0xf2, 0xae, 0x0e, 0x2e, 0x37, 0x85, 0x9d, 0x7f, 0xdf, 0xf2, 0x3d, 0xd7, - 0xde, 0x47, 0x5f, 0xec, 0xd7, 0x39, 0x9b, 0xe8, 0xeb, 0xfb, 0x8d, 0xeb, - 0xa2, 0xa4, 0xeb, 0xb7, 0x59, 0xd6, 0x61, 0x58, 0x47, 0x94, 0x1f, 0x48, - 0xe8, 0x06, 0x7b, 0x66, 0x17, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xb7, - 0x6f, 0xe1, 0x76, 0x39, 0x3f, 0x4e, 0xbc, 0x9b, 0xfe, 0x75, 0xfb, 0x8d, - 0x77, 0x69, 0xa2, 0x90, 0xbf, 0xf6, 0x75, 0x36, 0x77, 0x30, 0x5a, 0x75, - 0xe7, 0x93, 0x18, 0x7e, 0x1a, 0x33, 0xb3, 0x0d, 0x47, 0x77, 0x0b, 0x97, - 0x08, 0xdb, 0xff, 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x95, - 0x4e, 0xb8, 0x4d, 0x32, 0x8a, 0xd5, 0xdc, 0xff, 0xf8, 0xcb, 0x45, 0x63, - 0xd1, 0x96, 0xed, 0x1e, 0x5f, 0xe9, 0x20, 0xfb, 0x10, 0x27, 0x5e, 0xd0, - 0x16, 0x75, 0x98, 0xdc, 0xf3, 0x10, 0xc2, 0xf0, 0xbc, 0x8e, 0xbf, 0xf3, - 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9d, 0xae, 0x9d, 0x5c, 0xeb, 0xff, - 0xf2, 0x04, 0x0b, 0x8d, 0xa7, 0x08, 0xc0, 0xe3, 0x4e, 0xbf, 0xe8, 0x94, - 0x72, 0x78, 0xe4, 0xe7, 0x59, 0x8c, 0x4c, 0x2d, 0x63, 0x5d, 0x4a, 0x71, - 0xa1, 0x54, 0xbf, 0xfe, 0x63, 0xee, 0xdb, 0x8f, 0xf9, 0xe8, 0x14, 0xfc, - 0xeb, 0xff, 0x9d, 0x7d, 0xc6, 0xbf, 0x63, 0xec, 0x8e, 0xbc, 0x81, 0x73, - 0xaf, 0xfe, 0x1c, 0xeb, 0xcf, 0x9a, 0x17, 0xdc, 0xeb, 0xb6, 0xd8, 0x0a, - 0x28, 0x3a, 0x89, 0xa1, 0xaa, 0x92, 0xab, 0x75, 0xc6, 0x69, 0xa4, 0xfd, - 0xb8, 0x7a, 0x5f, 0xff, 0xc1, 0x7f, 0x31, 0x9a, 0x81, 0xdf, 0xfd, 0x6a, - 0x3f, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x16, 0x5f, 0xf9, 0xe4, 0xc6, - 0x71, 0xae, 0xed, 0x34, 0x4b, 0xb7, 0xff, 0xf6, 0x07, 0xb1, 0xf5, 0x8f, - 0x0b, 0xff, 0xad, 0x47, 0xe5, 0x59, 0x8c, 0x46, 0xda, 0xcc, 0xf6, 0xd2, - 0xaf, 0xff, 0x30, 0xb7, 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x31, 0x5f, - 0xb8, 0xd7, 0x76, 0x9a, 0x2a, 0x9b, 0x61, 0xd5, 0x87, 0x84, 0xa1, 0x9d, - 0xff, 0xff, 0xee, 0x3f, 0x77, 0x96, 0x79, 0x8e, 0xbe, 0xb8, 0x8c, 0xfb, - 0xa9, 0xc9, 0x1d, 0x4c, 0x22, 0x71, 0xc8, 0xaf, 0xff, 0x30, 0xb7, 0x93, - 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x3a, 0x5f, 0xe4, 0x7e, 0x44, 0x9f, 0x61, - 0xd7, 0xe9, 0xa2, 0x68, 0xd1, 0xd7, 0xf3, 0x38, 0x9b, 0x30, 0x4e, 0xa4, - 0x3d, 0x5d, 0x14, 0x5e, 0x4e, 0xc1, 0xcc, 0x1a, 0x1b, 0xff, 0x81, 0xaf, - 0x46, 0xec, 0x02, 0x64, 0x59, 0xd4, 0xb3, 0xf2, 0xe9, 0x5d, 0xff, 0x9e, - 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xef, 0x7e, 0xf0, 0x1d, 0x68, 0x55, - 0xff, 0x86, 0x3d, 0x9a, 0xcc, 0xde, 0x47, 0x50, 0x53, 0xe8, 0xc8, 0xc6, - 0x96, 0x44, 0xe9, 0x5e, 0x26, 0xbf, 0xa1, 0x8f, 0xc7, 0x02, 0x75, 0x30, - 0x7f, 0x82, 0x9f, 0x7f, 0xf9, 0x85, 0xbc, 0x98, 0xce, 0x35, 0xdd, 0xa6, - 0x8a, 0x16, 0xff, 0xff, 0xf7, 0x40, 0xb5, 0xbc, 0x98, 0x6f, 0x41, 0xe8, - 0x1c, 0x9d, 0x40, 0x44, 0xc7, 0x5f, 0x81, 0xbf, 0x91, 0xa7, 0x5f, 0xb3, - 0xfc, 0x71, 0x3a, 0xf4, 0x7e, 0xc4, 0xe7, 0x9a, 0x25, 0x14, 0x88, 0xfd, - 0x18, 0x64, 0x5f, 0xfe, 0x61, 0x6f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, - 0x92, 0xbf, 0xff, 0xd9, 0xa6, 0x3e, 0xe4, 0xdd, 0x75, 0xfb, 0xb1, 0xe0, - 0x2c, 0xea, 0x85, 0xfd, 0xb9, 0xe3, 0x38, 0x91, 0xcb, 0x63, 0x35, 0xe1, - 0x1a, 0xe5, 0x5d, 0xfe, 0x45, 0xe8, 0xd5, 0x00, 0x4d, 0xb6, 0xaf, 0x7f, - 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x92, 0xff, 0xf3, 0x0b, 0x79, 0x31, - 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xf5, 0xf7, 0x01, 0xed, 0x1d, 0x7e, 0xe7, - 0xeb, 0x4d, 0x1d, 0x7a, 0x07, 0x73, 0xaf, 0xde, 0xfa, 0xb1, 0x83, 0xac, - 0x9d, 0x3c, 0x31, 0x1b, 0xbf, 0xfd, 0xdd, 0x90, 0x3f, 0xab, 0xe0, 0x73, - 0x9b, 0x9d, 0x74, 0x78, 0xeb, 0xff, 0xc0, 0x0a, 0x73, 0xec, 0xdb, 0x40, - 0x71, 0x98, 0xea, 0x92, 0x36, 0x90, 0x9b, 0xf4, 0xfd, 0x0a, 0xdf, 0xfc, - 0xf3, 0x6a, 0x36, 0x3f, 0x63, 0x79, 0x8e, 0xbf, 0x64, 0xf9, 0xa5, 0x9d, - 0x7f, 0xf4, 0xdf, 0x3e, 0x8c, 0x6c, 0x7d, 0x91, 0x31, 0xd4, 0x75, 0xfd, - 0x34, 0x9f, 0xcf, 0xb0, 0xea, 0x84, 0x42, 0xe2, 0x63, 0x85, 0x5d, 0xc8, - 0x3a, 0x82, 0xab, 0x65, 0x08, 0xa6, 0x8d, 0x17, 0x87, 0xa2, 0x8f, 0xb2, - 0x15, 0x9b, 0x45, 0xb7, 0x83, 0x82, 0x75, 0xc1, 0xdc, 0xeb, 0xfe, 0x47, - 0x10, 0x7a, 0x68, 0x50, 0xeb, 0xff, 0xe4, 0xe7, 0xce, 0xc2, 0x7b, 0x40, - 0x68, 0x20, 0xeb, 0xe4, 0x9f, 0xf5, 0x73, 0xaf, 0x9a, 0xee, 0xd3, 0x45, - 0x2f, 0x7c, 0x3e, 0x8e, 0x1d, 0x7f, 0xd9, 0xc5, 0x7c, 0x0e, 0x73, 0x73, - 0xa9, 0x0f, 0x6f, 0x61, 0x05, 0x28, 0x99, 0x0c, 0xca, 0x1c, 0x26, 0xec, - 0x22, 0x2f, 0xc3, 0xe9, 0xf1, 0x93, 0xaf, 0xfd, 0x03, 0x1d, 0xf8, 0x01, - 0x03, 0x4e, 0xbc, 0x07, 0xd1, 0xd7, 0xe8, 0xfd, 0xf7, 0xd1, 0xd7, 0x85, - 0x3f, 0x3a, 0xf6, 0x7b, 0x47, 0x54, 0x1b, 0x6d, 0x0d, 0xd0, 0x51, 0xaf, - 0x31, 0xf7, 0xe3, 0x7e, 0x5e, 0xbf, 0x2b, 0xb8, 0x87, 0x68, 0xeb, 0xfe, - 0xff, 0x5c, 0x8d, 0xe4, 0x8b, 0x3a, 0xf7, 0x9f, 0x61, 0xd7, 0xfc, 0xf3, - 0xfc, 0x9c, 0x13, 0x42, 0xb9, 0xd5, 0x08, 0x97, 0x73, 0xa0, 0x0e, 0xdf, - 0xf2, 0x6a, 0x64, 0x1f, 0x47, 0xe7, 0x54, 0x8f, 0x99, 0x65, 0xd7, 0x38, - 0x9d, 0x7f, 0xd1, 0xff, 0xce, 0xc2, 0xdc, 0x4e, 0xb7, 0x37, 0x3c, 0xdd, - 0x82, 0x95, 0x09, 0xe1, 0xe4, 0x65, 0x28, 0xdf, 0x7b, 0x90, 0xb3, 0xaf, - 0xe8, 0x19, 0xbc, 0x8a, 0x1d, 0x7f, 0xd2, 0xce, 0x4d, 0x83, 0x0b, 0x3a, - 0xfd, 0xfc, 0x37, 0x16, 0x75, 0x21, 0xef, 0x70, 0xde, 0xe9, 0x61, 0xd7, - 0xa3, 0xfd, 0x1d, 0x50, 0x7a, 0x41, 0x21, 0x64, 0x56, 0xfd, 0xd0, 0x29, - 0x82, 0x75, 0xff, 0x47, 0x74, 0xfe, 0x8e, 0x6d, 0x1d, 0x7f, 0xe5, 0xb8, - 0x7e, 0xcd, 0x28, 0x1d, 0xce, 0xa0, 0x9f, 0xda, 0x1d, 0x5f, 0x73, 0xff, - 0xbb, 0x0e, 0xbc, 0x8c, 0xf8, 0xea, 0xe9, 0xe1, 0xe8, 0x9e, 0x82, 0x99, - 0x47, 0x61, 0x45, 0xe6, 0x4b, 0xfe, 0xfd, 0x3b, 0x9c, 0x79, 0xb4, 0x75, - 0xff, 0xfa, 0x24, 0x31, 0x3f, 0xd9, 0xb5, 0xdc, 0xda, 0xe7, 0xe7, 0x5f, - 0xdf, 0x17, 0x9e, 0x7f, 0x1d, 0x66, 0x9d, 0x76, 0xfa, 0xc3, 0x7c, 0xe5, - 0xd5, 0xba, 0x3f, 0xd6, 0x72, 0xf0, 0x9a, 0xbf, 0xd8, 0xcc, 0x93, 0x40, - 0x59, 0xd7, 0x6c, 0xd1, 0xd7, 0xec, 0x9f, 0x3b, 0xa3, 0xaa, 0x0d, 0xf8, - 0x8c, 0x5e, 0xce, 0x68, 0xea, 0x69, 0xba, 0xd8, 0x3f, 0x7f, 0xdf, 0xc7, - 0xff, 0x76, 0x40, 0xed, 0x1d, 0x50, 0x98, 0x7e, 0x42, 0xb1, 0x08, 0xef, - 0xff, 0xfe, 0xec, 0x73, 0x76, 0xa6, 0xff, 0x14, 0x7f, 0x9a, 0xeb, 0xb6, - 0x04, 0x27, 0x5f, 0x78, 0x51, 0x67, 0x5f, 0xe1, 0x87, 0x1f, 0x60, 0x9d, - 0x7f, 0xba, 0xf3, 0x27, 0x22, 0x73, 0xae, 0xc5, 0x9d, 0x41, 0x4c, 0x37, - 0x1d, 0xd6, 0x40, 0xe5, 0xdb, 0x0c, 0xef, 0xdb, 0x48, 0xb8, 0xd1, 0xd7, - 0xe7, 0xd9, 0x9c, 0xd1, 0xd4, 0x13, 0xd1, 0x59, 0x4d, 0xfb, 0xae, 0x28, - 0xb3, 0xaf, 0x94, 0x9b, 0x50, 0x75, 0xfe, 0x7f, 0xf5, 0x1d, 0x8d, 0x1d, - 0x50, 0x89, 0xcc, 0x22, 0x42, 0x51, 0x23, 0xbb, 0xf6, 0x9d, 0x6d, 0x1d, - 0x72, 0x29, 0xa3, 0x4e, 0x01, 0x7b, 0xdf, 0xbb, 0x4e, 0xbf, 0xff, 0x20, - 0x73, 0x63, 0xf2, 0x6f, 0xb2, 0x7f, 0x3a, 0xce, 0xa8, 0x3f, 0x4e, 0x0e, - 0x59, 0x88, 0x66, 0xed, 0xce, 0xeb, 0x21, 0xa0, 0x8b, 0xe4, 0x6b, 0x3b, - 0xa2, 0xa4, 0x3f, 0xe6, 0x94, 0x05, 0xc3, 0x45, 0x8d, 0xf6, 0x1b, 0xaf, - 0x1a, 0xbf, 0xf1, 0x9a, 0x8c, 0x68, 0x9a, 0x8d, 0x03, 0xd1, 0x9c, 0x6d, - 0xb0, 0x7d, 0x85, 0x0d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x29, 0xcb, - 0xff, 0x27, 0x1f, 0x5d, 0xcc, 0x16, 0x9d, 0x7e, 0x5f, 0x39, 0x9a, 0x3a, - 0xff, 0xfd, 0xd0, 0x7b, 0x91, 0xed, 0x63, 0x75, 0x1c, 0x69, 0xd7, 0xf9, - 0x16, 0x18, 0xd0, 0x04, 0xeb, 0xfb, 0x3d, 0xbc, 0xa1, 0x93, 0xaf, 0xfe, - 0x51, 0x37, 0xd0, 0xe0, 0x7a, 0xec, 0x9d, 0x7f, 0xec, 0xec, 0x73, 0x18, - 0x65, 0x96, 0x4a, 0xb9, 0x19, 0x3a, 0xe9, 0xd8, 0x0a, 0x76, 0x58, 0x76, - 0xd2, 0x7e, 0xaa, 0x89, 0x8f, 0x8b, 0xb6, 0xd1, 0x76, 0x90, 0x6f, 0xdc, - 0x6b, 0xbb, 0x4d, 0x15, 0xe5, 0xff, 0xfd, 0x81, 0xec, 0x7d, 0x63, 0xc2, - 0xff, 0xeb, 0x51, 0xf9, 0x56, 0x63, 0x11, 0x23, 0xb6, 0x67, 0x7f, 0xf3, - 0x0f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x47, 0xbc, 0xdc, 0x59, 0xd7, - 0x93, 0xf8, 0x3a, 0xf3, 0x71, 0x65, 0x30, 0x5d, 0xdf, 0xb8, 0xd7, 0x76, - 0x9a, 0x24, 0x8b, 0xff, 0xfa, 0x13, 0x89, 0xb5, 0x03, 0x3c, 0x79, 0x3a, - 0xf3, 0x9d, 0x74, 0x98, 0x84, 0x5c, 0xe1, 0x5f, 0x4c, 0xef, 0xd9, 0xd6, - 0x31, 0x67, 0x59, 0x88, 0x4d, 0x45, 0xe1, 0xdf, 0xe3, 0xbb, 0xff, 0x98, - 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x55, 0xfb, 0x8d, 0x77, 0x69, - 0xa2, 0xf1, 0xbf, 0xe9, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x6d, 0x98, - 0xc3, 0xf8, 0x73, 0x3b, 0x99, 0xe9, 0xd7, 0xe4, 0xff, 0x58, 0x27, 0x5f, - 0xff, 0x01, 0xf7, 0xcc, 0x51, 0x47, 0x96, 0x6f, 0xe3, 0xaa, 0x47, 0xef, - 0xa2, 0x6b, 0xdf, 0x46, 0x73, 0xae, 0xe7, 0x8e, 0xbd, 0x30, 0xce, 0x75, - 0x84, 0xeb, 0xbe, 0xfd, 0x3a, 0xbf, 0x35, 0x3f, 0x43, 0xee, 0xdb, 0x62, - 0x13, 0x4e, 0xc8, 0x47, 0x74, 0x89, 0xc7, 0xb4, 0x2d, 0xf5, 0x1a, 0xa1, - 0xba, 0x3f, 0x9c, 0xfe, 0x55, 0x88, 0x58, 0x63, 0x3c, 0x48, 0xfc, 0x66, - 0x8c, 0x55, 0x65, 0x9d, 0x8e, 0x8b, 0xc7, 0x60, 0x86, 0x4f, 0xd8, 0xdd, - 0x6a, 0x25, 0xfe, 0x10, 0x4f, 0x29, 0x1a, 0x53, 0xae, 0xe1, 0x9d, 0x4a, - 0xcc, 0x46, 0xc3, 0x29, 0x38, 0xdc, 0xdb, 0xd4, 0xdd, 0xde, 0xb2, 0xe3, - 0x4a, 0x4b, 0xea, 0xbc, 0xa2, 0x39, 0xad, 0x86, 0x3f, 0x2d, 0x09, 0x92, - 0xf3, 0x6c, 0x87, 0xed, 0x2a, 0x31, 0xed, 0x94, 0x17, 0xf3, 0xe6, 0xaa, - 0x98, 0xf8, 0xc6, 0xb2, 0xb6, 0xd5, 0x6e, 0x23, 0xeb, 0xd4, 0xa9, 0x05, - 0xaf, 0xeb, 0xd9, 0x4a, 0xc8, 0x66, 0x72, 0x5f, 0x6e, 0x5c, 0x3f, 0xda, - 0x41, 0x46, 0xd5, 0x75, 0xd5, 0x40, + 0x3f, 0x95, 0x96, 0xfe, 0x3d, 0x7d, 0x82, 0x93, 0x1d, 0x7f, 0xfb, 0xb1, + 0x3f, 0xb3, 0xa3, 0x9e, 0xea, 0x1d, 0x65, 0x9d, 0x7f, 0xdd, 0x89, 0xc3, + 0x8c, 0xe9, 0x89, 0x8f, 0x63, 0xea, 0x45, 0xfb, 0xd2, 0xd7, 0xdd, 0x1d, + 0x7b, 0x5d, 0x09, 0xd7, 0xef, 0xbe, 0x18, 0xfc, 0xea, 0x59, 0xe2, 0xec, + 0x1c, 0xbf, 0xfb, 0xda, 0x4d, 0x40, 0xe7, 0xba, 0x87, 0x5e, 0x1c, 0xe9, + 0xd4, 0xb3, 0xdb, 0xd8, 0x83, 0x7e, 0x0c, 0x2b, 0x81, 0x67, 0x5f, 0xf3, + 0xea, 0x30, 0x43, 0xd8, 0x3a, 0xff, 0xec, 0x5f, 0x33, 0x7e, 0x8b, 0xab, + 0xce, 0x75, 0xda, 0xd7, 0x0f, 0xf0, 0x4d, 0x6a, 0x13, 0x76, 0xc7, 0xf4, + 0x24, 0x78, 0x53, 0x5f, 0x3a, 0x0f, 0x8e, 0xbd, 0xc8, 0xf1, 0xd7, 0xf4, + 0xce, 0x1e, 0xa2, 0xce, 0xbf, 0xbc, 0x98, 0x18, 0x59, 0xd5, 0xe3, 0xd8, + 0x64, 0xb6, 0xed, 0x09, 0xd7, 0xf6, 0xfa, 0x86, 0xe2, 0xce, 0xae, 0x23, + 0x61, 0xdc, 0xf4, 0x46, 0x01, 0x5b, 0xee, 0xa8, 0x15, 0x9d, 0x76, 0x48, + 0xea, 0xc3, 0x70, 0x24, 0x74, 0xad, 0xaf, 0x45, 0x44, 0x27, 0x24, 0x46, + 0x17, 0x7c, 0x85, 0x42, 0x18, 0x4c, 0xf1, 0xc5, 0x6e, 0xc7, 0xcb, 0xf9, + 0xf8, 0xc3, 0xdf, 0xce, 0x97, 0xf3, 0xee, 0xc2, 0xdf, 0xc7, 0x53, 0x08, + 0xee, 0x18, 0x60, 0x5f, 0xc1, 0x63, 0x5e, 0xd6, 0xe7, 0x5c, 0xac, 0xab, + 0x67, 0x5e, 0x5b, 0xee, 0x75, 0xdb, 0x10, 0xeb, 0xee, 0x73, 0x3e, 0x9d, + 0x7e, 0xd4, 0xf8, 0xcb, 0x0a, 0xc1, 0xfb, 0x41, 0x04, 0xc3, 0x8e, 0x2f, + 0x50, 0x98, 0x32, 0x42, 0x9a, 0xff, 0xff, 0xf2, 0x35, 0xf8, 0xfd, 0x96, + 0x7b, 0x03, 0xa7, 0x5e, 0x72, 0x78, 0xdc, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, + 0x45, 0x29, 0x7f, 0xfc, 0xfe, 0x1c, 0x9f, 0x91, 0xd4, 0xee, 0x70, 0xeb, + 0xcf, 0x26, 0x21, 0x1e, 0xd8, 0xed, 0xf9, 0x9d, 0xff, 0x49, 0x8c, 0xe3, + 0x5d, 0xda, 0x68, 0x93, 0xac, 0xc2, 0xd1, 0x0c, 0xe8, 0x35, 0x10, 0x8d, + 0xbc, 0x9e, 0x70, 0x52, 0x51, 0xbd, 0x06, 0xf8, 0xb9, 0x32, 0x1d, 0xcd, + 0x8d, 0x1d, 0x21, 0x04, 0xaf, 0x0a, 0x09, 0x89, 0xf9, 0x0b, 0x65, 0xd6, + 0x7a, 0x7d, 0x8c, 0xb1, 0xca, 0x7f, 0x86, 0x48, 0xc2, 0x47, 0x53, 0xf3, + 0x5e, 0x8c, 0xbb, 0x64, 0x74, 0x77, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0x7e, + 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x53, 0xb3, 0x18, 0x7f, + 0xab, 0x33, 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0x4f, 0x7f, 0x4c, + 0x9e, 0xd0, 0x16, 0x75, 0xff, 0xe5, 0x59, 0x46, 0x55, 0xe7, 0x0a, 0xab, + 0xe7, 0xce, 0xed, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x8c, 0x6f, 0xff, + 0xdf, 0xca, 0x75, 0x5a, 0x15, 0xb9, 0xdb, 0xcf, 0x9f, 0x3b, 0xb6, 0x75, + 0xf2, 0x6f, 0x25, 0x6c, 0xeb, 0x31, 0x09, 0xaa, 0xc8, 0xbb, 0x18, 0xba, + 0x67, 0xe6, 0xbb, 0xff, 0xcc, 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, + 0x4f, 0x37, 0xf3, 0x1f, 0xc0, 0xcb, 0x47, 0x54, 0x2a, 0x91, 0x9c, 0xa2, + 0x51, 0xca, 0x75, 0x43, 0xca, 0xf7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0x82, + 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x54, 0xb3, 0x18, 0x7f, + 0xab, 0x33, 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0x51, 0x7f, 0x98, + 0xce, 0x35, 0xdd, 0xa6, 0x88, 0xca, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x32, + 0xdf, 0xa5, 0x9e, 0x76, 0x9d, 0x7e, 0x61, 0x6f, 0x26, 0x30, 0xf6, 0x77, + 0x33, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x54, 0x96, 0x13, 0xad, 0xf4, 0xeb, + 0x31, 0x87, 0xa8, 0xae, 0x66, 0x00, 0xfb, 0xfc, 0xc6, 0x71, 0xae, 0xed, + 0x34, 0x57, 0x57, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xb1, 0x6f, 0xfe, + 0x5b, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9e, 0xaf, 0xf9, 0x96, 0x1e, + 0x13, 0x6d, 0x36, 0x8e, 0xbf, 0xff, 0x4c, 0x30, 0xb6, 0x33, 0x48, 0xc8, + 0x5d, 0xd4, 0x3a, 0xed, 0x78, 0xeb, 0xf0, 0xba, 0xc6, 0x0e, 0xbf, 0x81, + 0xae, 0xbc, 0x98, 0x56, 0xcd, 0xd7, 0xd1, 0x6b, 0xf6, 0x7b, 0x48, 0xb3, + 0xaf, 0xff, 0x46, 0xfe, 0xc9, 0x93, 0x9e, 0xd0, 0x15, 0xce, 0xbc, 0xfb, + 0xb0, 0x27, 0xe9, 0xe2, 0x6b, 0x7b, 0x13, 0x84, 0xe4, 0x24, 0x35, 0x0c, + 0x0a, 0x61, 0x52, 0x94, 0x28, 0x24, 0x78, 0x57, 0xe4, 0xe8, 0xbc, 0xc7, + 0x5f, 0xa5, 0x81, 0xf9, 0x87, 0x52, 0xa0, 0xf3, 0xa0, 0x9a, 0xfd, 0x9e, + 0x40, 0x68, 0xeb, 0x95, 0x85, 0x6a, 0x75, 0x2b, 0x53, 0xc7, 0x55, 0x89, + 0xaf, 0xca, 0xb9, 0x58, 0xd7, 0x3c, 0x75, 0xfe, 0xfa, 0x39, 0xce, 0x43, + 0x4e, 0xa5, 0x60, 0xf9, 0x95, 0x46, 0x77, 0xdc, 0x5f, 0xb7, 0x3a, 0xfe, + 0x56, 0x15, 0x95, 0x44, 0x49, 0x67, 0x5e, 0x6e, 0x74, 0xab, 0xcb, 0x8d, + 0x1d, 0x7b, 0xfe, 0x41, 0xd7, 0xf6, 0x7e, 0x93, 0x23, 0x27, 0x5f, 0xf9, + 0xf5, 0xf3, 0x5a, 0xc9, 0x4a, 0x0e, 0xbf, 0xff, 0x0b, 0xa8, 0x9c, 0x89, + 0x4b, 0x35, 0xff, 0xf0, 0x75, 0x05, 0x18, 0x4a, 0x17, 0x74, 0xfe, 0xff, + 0xfe, 0xe2, 0x6d, 0x3a, 0xd8, 0x8e, 0x71, 0x36, 0x9a, 0x09, 0xce, 0xbe, + 0x4e, 0xfd, 0x59, 0xd7, 0xff, 0x91, 0x4f, 0x98, 0x2f, 0xbe, 0x94, 0x51, + 0xce, 0xa6, 0x9f, 0x80, 0x91, 0xdf, 0xfe, 0x7d, 0x0e, 0x7e, 0xc7, 0x51, + 0xaf, 0xc3, 0xaf, 0xe0, 0xe2, 0x9e, 0xc6, 0x9d, 0x7d, 0xd8, 0x5b, 0x4e, + 0xa7, 0x3c, 0xef, 0x16, 0xdf, 0x82, 0x93, 0x23, 0x27, 0x5f, 0xfd, 0xf2, + 0x20, 0x61, 0x7f, 0x3e, 0x77, 0x6c, 0xea, 0x83, 0xf3, 0x12, 0x8b, 0xff, + 0x77, 0x26, 0xea, 0x76, 0x39, 0x07, 0x5c, 0xfb, 0x9d, 0x7f, 0x9f, 0x4f, + 0xd0, 0x0c, 0xe7, 0x50, 0x9e, 0x40, 0x05, 0xaa, 0x75, 0xc0, 0xe9, 0x0d, + 0xa4, 0x37, 0xb8, 0x62, 0xb8, 0x69, 0x74, 0x84, 0x61, 0x2f, 0xe8, 0x4a, + 0x7d, 0x20, 0xda, 0x84, 0x2d, 0xe1, 0x7f, 0x1d, 0x78, 0x53, 0x47, 0x59, + 0x95, 0x41, 0xb4, 0x81, 0xab, 0xee, 0x6c, 0x75, 0x9d, 0x7e, 0x58, 0xbf, + 0xb4, 0x75, 0xe8, 0xce, 0x1d, 0x7f, 0xf9, 0xaf, 0xc7, 0xf2, 0x6a, 0x06, + 0x3f, 0x3a, 0xd2, 0xe9, 0xf0, 0xfd, 0x1a, 0xad, 0xd1, 0x63, 0xc8, 0x43, + 0xd6, 0x26, 0x50, 0x85, 0x60, 0x86, 0xa5, 0xed, 0x6d, 0x6d, 0x1d, 0x7f, + 0xdd, 0x7f, 0x44, 0xda, 0x45, 0x9d, 0x7f, 0xa2, 0x43, 0x9b, 0xfb, 0x0e, + 0xbd, 0xd0, 0x2c, 0xea, 0xc4, 0x53, 0xa1, 0x17, 0x0e, 0x00, 0x63, 0x7f, + 0x7b, 0x53, 0x40, 0xce, 0x75, 0xf8, 0x54, 0x4c, 0xd1, 0xd7, 0xe6, 0x5f, + 0xce, 0xd3, 0xaf, 0xfe, 0xc6, 0x5f, 0xfc, 0x6f, 0x5f, 0xfd, 0x1d, 0x7f, + 0xed, 0x3e, 0xf0, 0x2e, 0x1c, 0x50, 0xea, 0x44, 0x67, 0xf4, 0x98, 0x49, + 0xfc, 0x8b, 0x74, 0x74, 0xeb, 0x04, 0xea, 0x59, 0xa5, 0x11, 0x5b, 0xe1, + 0x0f, 0xc5, 0x0e, 0xbf, 0xb3, 0x4c, 0xb8, 0xce, 0x75, 0x61, 0xf8, 0xb9, + 0x00, 0x92, 0x5f, 0x80, 0xa6, 0x83, 0x07, 0x5e, 0x5a, 0x68, 0xeb, 0xfa, + 0x37, 0x96, 0x90, 0x4e, 0xa8, 0x54, 0xd3, 0x90, 0xfd, 0x48, 0x68, 0xf4, + 0xb1, 0xca, 0x04, 0x6e, 0xff, 0xf2, 0x8f, 0x9b, 0xfb, 0xd1, 0x9b, 0x11, + 0xa7, 0x5f, 0xe1, 0xcd, 0x79, 0xdc, 0x4e, 0xa5, 0x0f, 0xeb, 0x62, 0x5d, + 0xff, 0xff, 0x93, 0x9c, 0x8f, 0xbe, 0x41, 0x04, 0xb3, 0x41, 0x03, 0xf2, + 0x47, 0x5f, 0xff, 0xc3, 0x8a, 0x60, 0xfc, 0xd7, 0xbb, 0x8b, 0xfb, 0x1f, + 0x9d, 0x50, 0x8c, 0xac, 0x6c, 0xbf, 0xc0, 0x7d, 0x24, 0xc8, 0xc9, 0xd4, + 0x89, 0xa1, 0xf6, 0x1d, 0xe2, 0x43, 0x7b, 0xb0, 0x27, 0x5e, 0xdf, 0xcb, + 0x3a, 0x9a, 0x6d, 0xdc, 0x6a, 0xfd, 0x38, 0x78, 0x8c, 0x9d, 0x7f, 0xbe, + 0xbe, 0xc4, 0x99, 0x19, 0x3a, 0xff, 0xe4, 0x1c, 0x07, 0x27, 0x5c, 0x67, + 0x8e, 0xa8, 0x3f, 0x90, 0x9b, 0xdf, 0xc1, 0x7e, 0x7f, 0xb7, 0x87, 0x5e, + 0xef, 0xdd, 0x87, 0x5f, 0xf4, 0x2c, 0x71, 0xbc, 0x4f, 0xce, 0xa9, 0x1e, + 0xbe, 0x88, 0x2f, 0xfa, 0x25, 0x89, 0xad, 0x02, 0x0e, 0xbf, 0xf7, 0xa1, + 0x7b, 0xb5, 0x37, 0xce, 0x1d, 0x7e, 0xee, 0x71, 0x34, 0x75, 0xe1, 0x49, + 0x6e, 0x7c, 0xbe, 0x3f, 0xbf, 0xf3, 0xe7, 0xf0, 0x2e, 0x1c, 0x50, 0xea, + 0x9d, 0x30, 0xa9, 0x42, 0x6f, 0xf3, 0x3b, 0xfc, 0xfb, 0xeb, 0xde, 0xc5, + 0x73, 0xaf, 0xff, 0x27, 0x3a, 0xf8, 0xd0, 0xe7, 0x3f, 0x43, 0xaf, 0xe5, + 0x3d, 0x18, 0x2d, 0x3a, 0xff, 0xf4, 0x66, 0xfe, 0xec, 0x78, 0x63, 0xfd, + 0x1d, 0x74, 0x7e, 0x75, 0xdd, 0x59, 0xd4, 0xd3, 0x59, 0xa1, 0x6a, 0x44, + 0x61, 0x78, 0xb0, 0x0e, 0xb7, 0xa7, 0x4e, 0x1d, 0x7f, 0x03, 0x5e, 0xd6, + 0x78, 0xeb, 0xf8, 0x0a, 0x94, 0x99, 0x19, 0x3a, 0xec, 0xe9, 0xd7, 0x99, + 0x65, 0x92, 0xaf, 0xff, 0x79, 0x3d, 0xae, 0xa6, 0xdf, 0xde, 0x44, 0x8a, + 0x60, 0xbf, 0xa5, 0x13, 0x0d, 0x41, 0xc7, 0x2d, 0xf1, 0x90, 0x0d, 0x2f, + 0xff, 0xf9, 0x3d, 0x28, 0x1c, 0xf7, 0x53, 0x3d, 0x0b, 0x4e, 0x48, 0xea, + 0x92, 0xf3, 0x08, 0x5a, 0xf0, 0x81, 0xb0, 0xa2, 0x42, 0x19, 0xa1, 0x0f, + 0xc8, 0xcb, 0x16, 0x71, 0xd3, 0x61, 0x8c, 0x2b, 0xd1, 0x9e, 0x6c, 0x4a, + 0xbf, 0xed, 0xe5, 0xad, 0x60, 0x5f, 0xc7, 0x5b, 0x0e, 0xbe, 0xe0, 0xbe, + 0xc3, 0xaa, 0x0f, 0xa9, 0x43, 0x94, 0x0f, 0xb3, 0x9d, 0x7a, 0x3b, 0xa3, + 0xab, 0x73, 0x54, 0x81, 0xf7, 0xff, 0xf3, 0xf9, 0x3a, 0xeb, 0xf9, 0x9a, + 0x8c, 0xe6, 0x09, 0xd7, 0xff, 0x91, 0xba, 0x8d, 0xbc, 0xf4, 0xa5, 0x9a, + 0x3a, 0xb8, 0x8c, 0x41, 0x21, 0xd8, 0xb1, 0x7d, 0xce, 0xe0, 0x9d, 0x48, + 0x7a, 0x2e, 0x63, 0x7d, 0xe8, 0xdd, 0x93, 0xab, 0xa7, 0x86, 0xc9, 0x05, + 0xcc, 0xf4, 0xeb, 0xff, 0xd0, 0x2d, 0xfb, 0xc7, 0xfd, 0x3d, 0xd8, 0x3a, + 0xff, 0x23, 0x3a, 0xcc, 0x19, 0xce, 0xbe, 0x8d, 0x46, 0xc3, 0xaf, 0xfe, + 0x81, 0x7f, 0x4a, 0x14, 0x76, 0x7c, 0x75, 0x74, 0xf9, 0x40, 0x45, 0x7b, + 0xe3, 0xb4, 0xea, 0x6a, 0x66, 0xff, 0x8b, 0xe9, 0x2b, 0xd0, 0x97, 0xda, + 0x22, 0xbe, 0x5f, 0xd8, 0x13, 0xaf, 0x90, 0x38, 0xb3, 0xaf, 0x9d, 0xc7, + 0xf3, 0xac, 0xcc, 0x1e, 0x02, 0x84, 0x17, 0x01, 0x67, 0x5f, 0xe6, 0x5e, + 0x6c, 0x94, 0x2b, 0x9d, 0x48, 0x7e, 0xbd, 0x29, 0xd0, 0xb5, 0xfe, 0x87, + 0xe7, 0x59, 0x70, 0x95, 0x73, 0x2c, 0x95, 0x41, 0x3c, 0xa6, 0x4c, 0xaf, + 0x79, 0x15, 0xca, 0x60, 0xd1, 0xdf, 0xdb, 0xb5, 0x35, 0xd4, 0x3a, 0xf8, + 0x12, 0x07, 0x8e, 0xa4, 0x4f, 0xc2, 0x68, 0x6b, 0xea, 0x13, 0x7e, 0x2f, + 0xdb, 0x2d, 0xb9, 0x9d, 0x1d, 0x6c, 0x3a, 0xdb, 0xe1, 0xa6, 0xf0, 0xbd, + 0xf6, 0xf2, 0x54, 0x6e, 0x75, 0xff, 0xda, 0xd0, 0x46, 0x03, 0xd8, 0xf6, + 0x8e, 0xa8, 0x44, 0x96, 0x13, 0x80, 0xa2, 0xff, 0xde, 0x4e, 0x3f, 0xfb, + 0x5e, 0xce, 0x9d, 0x7f, 0xc8, 0xc8, 0xe7, 0x90, 0x1f, 0x9d, 0x7f, 0x9f, + 0x9e, 0xd0, 0xa2, 0x87, 0x5f, 0xfe, 0xd6, 0x29, 0x80, 0xe3, 0x86, 0x3b, + 0x07, 0x54, 0x93, 0x21, 0x42, 0xe5, 0x74, 0x17, 0x38, 0xd1, 0x95, 0xec, + 0x4e, 0x1d, 0x7f, 0xa4, 0x8b, 0xee, 0xee, 0xae, 0x75, 0xf3, 0xf2, 0x24, + 0x75, 0xff, 0x3e, 0xff, 0x37, 0xd6, 0x0a, 0x87, 0x54, 0xe8, 0xac, 0xdc, + 0x69, 0x66, 0xde, 0x20, 0xbe, 0xea, 0xba, 0x2c, 0xeb, 0xc3, 0x1f, 0x9d, + 0x7a, 0x17, 0x9f, 0x0d, 0xfe, 0x89, 0x2f, 0xfd, 0x1b, 0xf6, 0x16, 0xde, + 0xa4, 0xc7, 0x56, 0x23, 0xc1, 0x1f, 0xb8, 0x67, 0x7e, 0x6b, 0xcf, 0x8c, + 0x9d, 0x7e, 0x8e, 0x07, 0x04, 0xea, 0x13, 0xcd, 0xf1, 0x45, 0xff, 0xd1, + 0xfc, 0x75, 0x62, 0xea, 0x75, 0x0e, 0xb2, 0xa8, 0xeb, 0xfc, 0x1e, 0xc0, + 0xb2, 0xfb, 0x9d, 0x7f, 0xf2, 0x07, 0xb0, 0xd8, 0xfd, 0xc7, 0xf3, 0xaf, + 0xff, 0xf9, 0x6e, 0x3b, 0xc9, 0x86, 0x71, 0x36, 0x60, 0xe0, 0x5e, 0x47, + 0x8b, 0xd6, 0xfc, 0xa7, 0x9d, 0xc4, 0xeb, 0xc2, 0x09, 0xce, 0xa7, 0x3c, + 0x2f, 0x13, 0x52, 0x23, 0x5c, 0x61, 0x6d, 0x50, 0x9f, 0x5f, 0x08, 0x56, + 0x86, 0xe2, 0x9a, 0x33, 0x04, 0x63, 0x57, 0x2b, 0x0a, 0xd9, 0xd7, 0x92, + 0x38, 0x75, 0x2a, 0x8d, 0xd7, 0x48, 0x2f, 0xfe, 0xe2, 0x2e, 0x15, 0xc7, + 0x17, 0xbc, 0x1d, 0x52, 0x3e, 0xa9, 0x89, 0x6f, 0x90, 0x5c, 0x27, 0x5e, + 0x9d, 0x68, 0x75, 0x04, 0xdd, 0x88, 0xfd, 0xfa, 0x59, 0xb2, 0x24, 0x75, + 0xec, 0xe4, 0x1d, 0x5b, 0xa3, 0x01, 0x17, 0xb8, 0x41, 0xd2, 0x8b, 0xff, + 0xec, 0xf6, 0xb2, 0x6e, 0xc6, 0xcc, 0xef, 0x60, 0xeb, 0xff, 0xff, 0xf2, + 0x66, 0xfa, 0x4c, 0x67, 0xe6, 0x6f, 0x2d, 0x27, 0xb4, 0x9b, 0x84, 0x20, + 0x9c, 0xeb, 0xff, 0xf2, 0x08, 0x7e, 0x7d, 0xf2, 0x69, 0xd0, 0x41, 0x23, + 0xa8, 0x53, 0x2e, 0xf2, 0x86, 0xc8, 0x44, 0x5e, 0x07, 0x24, 0x75, 0xfc, + 0xfe, 0xff, 0xe8, 0xc8, 0xea, 0xf8, 0x79, 0x73, 0x8e, 0x5f, 0xe8, 0x92, + 0x30, 0xcb, 0x2c, 0x95, 0x79, 0x4c, 0x09, 0xd7, 0xf7, 0x5f, 0x8d, 0x8f, + 0x1d, 0x73, 0x84, 0xeb, 0xfb, 0x8f, 0xae, 0xbc, 0x8e, 0xb6, 0xe7, 0x5c, + 0x8c, 0x9d, 0x77, 0xdf, 0xce, 0xa9, 0x8d, 0x7f, 0xe2, 0xd7, 0xa4, 0xe1, + 0x3a, 0xe6, 0x59, 0x3a, 0xa4, 0x8d, 0x7c, 0x15, 0x69, 0x62, 0x20, 0x68, + 0x8d, 0x91, 0xbb, 0xde, 0xfb, 0xf9, 0x4c, 0x1e, 0xb5, 0xff, 0x20, 0x71, + 0x69, 0x32, 0x32, 0x75, 0xff, 0xe7, 0x0e, 0x60, 0xa9, 0xad, 0x60, 0xfe, + 0x75, 0xf7, 0x40, 0xea, 0x42, 0x20, 0x16, 0x71, 0x7f, 0xff, 0x49, 0xf5, + 0xa8, 0xc9, 0xc1, 0x20, 0xf0, 0x5d, 0x93, 0xae, 0xf4, 0x05, 0x12, 0xa8, + 0x75, 0x7e, 0xd3, 0xcf, 0xae, 0x9d, 0x52, 0x56, 0x20, 0x11, 0xcd, 0xe3, + 0x59, 0x48, 0xd1, 0xbc, 0x5b, 0x7e, 0xd9, 0xf7, 0xa9, 0xe3, 0xaf, 0xfb, + 0x3d, 0xd8, 0xe7, 0xb1, 0xa7, 0x5e, 0x8e, 0x4c, 0x75, 0x42, 0xf1, 0x76, + 0x46, 0xd6, 0x90, 0x82, 0xe9, 0x2b, 0xcb, 0x46, 0xfd, 0x60, 0x4a, 0xf6, + 0xcd, 0xef, 0x69, 0xe6, 0x3a, 0xff, 0xe4, 0x0b, 0xf9, 0x35, 0x92, 0xce, + 0x9d, 0x73, 0xed, 0x1d, 0x6c, 0xe9, 0xec, 0xf9, 0x06, 0xb7, 0x44, 0xe0, + 0xba, 0xdf, 0x66, 0xf3, 0xec, 0x3a, 0xff, 0x84, 0x38, 0x20, 0x96, 0x68, + 0xeb, 0xfd, 0xf7, 0xc3, 0x93, 0xa7, 0x0e, 0xbe, 0xf2, 0x69, 0x0e, 0xae, + 0x22, 0xbd, 0xc9, 0x44, 0xd8, 0x06, 0x97, 0xfd, 0xd4, 0x0a, 0x2a, 0x60, + 0x50, 0xeb, 0xfc, 0xf2, 0xc0, 0xf3, 0x5a, 0x3a, 0xfa, 0x33, 0xe8, 0x4e, + 0xbf, 0xca, 0x27, 0x9f, 0xac, 0xab, 0x9d, 0x7f, 0xdc, 0xc9, 0xbb, 0x9a, + 0x71, 0x3a, 0xff, 0xbb, 0x92, 0xc0, 0x2a, 0x5c, 0x4e, 0xbf, 0xff, 0xc8, + 0x39, 0xbf, 0x94, 0x7f, 0x76, 0x3b, 0x9b, 0x1e, 0x47, 0x50, 0x53, 0x5d, + 0x69, 0x92, 0x11, 0x70, 0xdf, 0xc6, 0xfb, 0x0e, 0xaf, 0xf8, 0x29, 0xc8, + 0xd9, 0xfe, 0xa4, 0x75, 0xd0, 0xb3, 0xad, 0xe8, 0x3d, 0x0e, 0x9d, 0xdf, + 0xfa, 0x34, 0xfd, 0x40, 0xb5, 0x27, 0x3a, 0xa1, 0x55, 0x1e, 0x47, 0x2c, + 0xf0, 0xa9, 0x01, 0x3d, 0xe8, 0x1f, 0x1d, 0x7f, 0x93, 0xa9, 0xc9, 0x4d, + 0x07, 0x5f, 0xff, 0x90, 0x0d, 0xfb, 0xbf, 0xef, 0xa7, 0xe2, 0x6f, 0xf9, + 0xd7, 0xcf, 0xc8, 0x91, 0xd7, 0xff, 0xf2, 0x0b, 0xa0, 0xff, 0xc8, 0xeb, + 0xa7, 0xa3, 0xa7, 0x50, 0x9f, 0xb7, 0x88, 0x2f, 0xc9, 0xed, 0x02, 0x73, + 0xaf, 0xff, 0xa0, 0x53, 0xff, 0x6e, 0xd4, 0xe7, 0xd8, 0x09, 0xd4, 0x14, + 0xda, 0x92, 0x1a, 0x0b, 0x21, 0xf1, 0x45, 0xfb, 0x80, 0x6f, 0x60, 0xeb, + 0xfb, 0x93, 0x49, 0x3d, 0xa3, 0xac, 0x30, 0x7a, 0xb8, 0x4f, 0x7f, 0xa6, + 0x79, 0x9f, 0x79, 0x68, 0xeb, 0xf9, 0xe7, 0x49, 0x91, 0x93, 0xab, 0x0f, + 0x8d, 0xcd, 0x6f, 0xe9, 0xf0, 0x67, 0xc6, 0x4e, 0xbf, 0xe8, 0x9f, 0xec, + 0xba, 0x07, 0x9c, 0xea, 0xc3, 0xea, 0xe1, 0x75, 0xfa, 0x39, 0xcc, 0xe9, + 0xd7, 0xf0, 0xba, 0x90, 0xb8, 0x3a, 0xa4, 0x7a, 0x20, 0x26, 0xbe, 0x89, + 0xd4, 0x50, 0xeb, 0xff, 0xf2, 0x36, 0x17, 0xa7, 0xe6, 0x2c, 0x0d, 0x79, + 0x1d, 0x72, 0x6c, 0x3a, 0xdd, 0x3a, 0xa4, 0x7f, 0x4a, 0xea, 0x60, 0x17, + 0xbc, 0x18, 0x59, 0xd7, 0xfb, 0x3f, 0xc9, 0xa3, 0x7d, 0x1d, 0x50, 0x79, + 0xf8, 0x37, 0x7f, 0x75, 0xe5, 0x1a, 0x91, 0xd7, 0xfd, 0x9d, 0x4d, 0xf5, + 0xd0, 0x68, 0xeb, 0xb0, 0x5a, 0x7c, 0xbf, 0x96, 0x5f, 0xc2, 0xff, 0x87, + 0x04, 0xeb, 0xf2, 0x6d, 0xe7, 0x14, 0x3a, 0xe5, 0x24, 0x75, 0xfb, 0xa9, + 0xb1, 0x1a, 0x75, 0xd9, 0xd9, 0x1b, 0xf6, 0x8b, 0xd2, 0xd1, 0x2b, 0xb6, + 0xd3, 0x79, 0x96, 0x59, 0x2a, 0xff, 0xdc, 0x10, 0x3f, 0xdc, 0x9a, 0x16, + 0x73, 0x05, 0xfd, 0xfb, 0xa9, 0x32, 0x32, 0x75, 0x41, 0xfb, 0xe2, 0x7d, + 0xfe, 0x80, 0xe4, 0xa0, 0x5a, 0x75, 0x42, 0xfc, 0x84, 0x86, 0xb2, 0x39, + 0xc5, 0x78, 0x4b, 0xcd, 0x08, 0x8e, 0x42, 0x29, 0x6e, 0x5d, 0x22, 0x78, + 0x4f, 0x0c, 0x20, 0x75, 0x08, 0x5f, 0x16, 0x82, 0x18, 0x0c, 0xc2, 0xf3, + 0xe9, 0x05, 0xf7, 0x39, 0x9d, 0x3a, 0xfe, 0xea, 0x6d, 0x6d, 0x01, 0x43, + 0xaa, 0x0f, 0x55, 0xa4, 0x36, 0x54, 0x9d, 0x64, 0x3a, 0xff, 0xbd, 0x1c, + 0xd7, 0x60, 0x7c, 0x75, 0x95, 0x27, 0x5f, 0xf7, 0xa3, 0x9a, 0xec, 0x0f, + 0x8e, 0xbb, 0x50, 0x75, 0xe5, 0x86, 0x0e, 0xbf, 0xc3, 0xe7, 0x9b, 0x51, + 0xe3, 0xa9, 0x0f, 0x35, 0xc6, 0xef, 0x91, 0xf1, 0xa7, 0x5f, 0xfb, 0x36, + 0x0e, 0x6a, 0x61, 0x80, 0x9d, 0x7c, 0xd0, 0xc4, 0xe7, 0x5d, 0xfc, 0x1d, + 0x7b, 0x49, 0xc3, 0xab, 0x0f, 0x4f, 0xf2, 0x2f, 0x0b, 0x5f, 0xe9, 0x60, + 0xa0, 0x70, 0x4e, 0xbd, 0xed, 0x31, 0x09, 0xed, 0xe0, 0xa4, 0xc6, 0xfd, + 0x62, 0xfc, 0x80, 0x47, 0xf5, 0x09, 0x1f, 0x17, 0xdd, 0xa8, 0x3a, 0xf2, + 0xc3, 0x07, 0x5f, 0xe1, 0xf3, 0xcd, 0xa8, 0xf1, 0xd4, 0x87, 0x9a, 0xe3, + 0x77, 0xc8, 0xf8, 0xd3, 0xaf, 0xfd, 0x9b, 0x07, 0x35, 0x30, 0xc0, 0x4e, + 0xbe, 0x68, 0x62, 0x73, 0xaf, 0xe9, 0xbf, 0x45, 0x77, 0x98, 0xeb, 0xbf, + 0x83, 0xaf, 0x69, 0x38, 0x75, 0x62, 0x21, 0x5a, 0x45, 0xf9, 0x97, 0x85, + 0xaf, 0xf4, 0xb0, 0x50, 0x38, 0x27, 0x5f, 0xc2, 0xe1, 0xc5, 0x18, 0x85, + 0xc8, 0xe0, 0x8a, 0x60, 0x7b, 0x65, 0x09, 0x4d, 0x08, 0x9e, 0xb1, 0x7e, + 0x40, 0x23, 0xfa, 0x86, 0x1f, 0x8f, 0x6f, 0xfe, 0xe4, 0x6f, 0xa1, 0x85, + 0xe6, 0xfe, 0x3a, 0xff, 0xfc, 0xe1, 0xcc, 0x15, 0x3e, 0x8c, 0x0c, 0xe9, + 0xc3, 0xaf, 0x3f, 0x27, 0x3c, 0x82, 0x57, 0xd2, 0xcd, 0xe4, 0x79, 0x04, + 0xaf, 0x69, 0x02, 0x79, 0x04, 0xae, 0x65, 0x93, 0xc8, 0x25, 0x4d, 0x45, + 0x2c, 0xc5, 0x3e, 0x2f, 0x64, 0xa2, 0xe7, 0xf1, 0x64, 0x12, 0x30, 0x6f, + 0xef, 0xec, 0xee, 0x60, 0xa8, 0x75, 0xe7, 0x1f, 0xfe, 0x2f, 0xa5, 0xc4, + 0xe5, 0x7f, 0x21, 0x82, 0xb4, 0x41, 0x8c, 0xe3, 0xc6, 0x97, 0xdb, 0x78, + 0xfd, 0x3a, 0xd8, 0xae, 0x8a, 0x1f, 0xdf, 0xad, 0x23, 0xaf, 0xf4, 0xd2, + 0x04, 0xfe, 0x49, 0xca, 0xb4, 0x1d, 0x7f, 0x92, 0x40, 0x7d, 0x75, 0x0e, + 0xbf, 0xb3, 0x63, 0xaf, 0x3a, 0x75, 0xa4, 0x55, 0xe7, 0xe4, 0xe5, 0x51, + 0x55, 0x06, 0xd9, 0xa2, 0x0b, 0x1c, 0xbd, 0x1f, 0xb4, 0xa6, 0x0d, 0x6d, + 0x2d, 0x17, 0xa3, 0x09, 0x0a, 0x84, 0xc5, 0x72, 0x1d, 0xd7, 0xff, 0xdf, + 0x46, 0x5a, 0xe8, 0x73, 0x9f, 0xad, 0x34, 0x75, 0xf0, 0x1f, 0x92, 0x3a, + 0xcb, 0x3a, 0xec, 0x90, 0x4d, 0x8c, 0xc4, 0x37, 0xe6, 0x72, 0x64, 0x59, + 0xd7, 0xf3, 0x62, 0x69, 0x47, 0xe5, 0x59, 0x0e, 0xbf, 0xe9, 0xc1, 0x20, + 0xf4, 0x0e, 0x27, 0x5f, 0xc9, 0x0b, 0x9f, 0x19, 0x3a, 0xfd, 0x93, 0xaf, + 0x16, 0x75, 0xed, 0x27, 0x0e, 0xa1, 0x3c, 0x2f, 0x13, 0xdf, 0xc2, 0xff, + 0xfe, 0x0d, 0x1d, 0x7f, 0x22, 0x9f, 0x61, 0x6c, 0x05, 0x30, 0x6c, 0x0f, + 0xe1, 0xce, 0x9b, 0xfc, 0x43, 0x58, 0x9e, 0x62, 0x14, 0x0c, 0x66, 0x97, + 0xc3, 0x93, 0x80, 0xeb, 0xfe, 0xcf, 0x7c, 0x1c, 0xff, 0xee, 0xe7, 0x54, + 0x97, 0x32, 0xc2, 0x59, 0x82, 0x1c, 0x36, 0xec, 0x64, 0x9f, 0x93, 0x8c, + 0x20, 0xf5, 0x1f, 0xcf, 0x8d, 0x36, 0xc8, 0x6f, 0xff, 0xd3, 0xf3, 0x98, + 0x17, 0x5f, 0x5f, 0xc3, 0x13, 0x1d, 0x7f, 0xff, 0xf8, 0x1c, 0x04, 0xc2, + 0xff, 0xeb, 0x58, 0xa6, 0x03, 0x8e, 0x18, 0xec, 0x1d, 0x7d, 0xb5, 0xd0, + 0x7d, 0x3a, 0xf3, 0x2c, 0xb2, 0x55, 0xd2, 0x82, 0x98, 0x2f, 0xea, 0x13, + 0x38, 0x9d, 0x57, 0x77, 0x8e, 0x23, 0x5f, 0xca, 0x47, 0x39, 0x9d, 0x3a, + 0xfe, 0x9e, 0x69, 0x2a, 0xb9, 0x39, 0xd7, 0xdd, 0x7d, 0xd9, 0x3a, 0xfd, + 0x3f, 0x12, 0x16, 0x75, 0xff, 0xf4, 0x7d, 0xf0, 0xc7, 0xef, 0xef, 0xfe, + 0x8c, 0x8e, 0xa5, 0x65, 0x1a, 0x48, 0x6a, 0xe4, 0x7e, 0x27, 0xbf, 0xf3, + 0xfb, 0x4c, 0xe7, 0x7f, 0x7f, 0x1d, 0x7f, 0xff, 0xec, 0xf4, 0x34, 0x73, + 0x06, 0x25, 0xee, 0xba, 0xc7, 0x36, 0x1d, 0x41, 0x45, 0x3b, 0x27, 0xf7, + 0xbe, 0x86, 0x63, 0xaf, 0x49, 0x04, 0xeb, 0xe9, 0xfe, 0xed, 0x32, 0x75, + 0xff, 0x47, 0x5d, 0x3d, 0x32, 0x32, 0x75, 0xff, 0xe5, 0x23, 0x5c, 0x8e, + 0x8e, 0x7a, 0x16, 0x75, 0xff, 0x68, 0x73, 0x62, 0x4c, 0x8c, 0x9d, 0x7f, + 0xff, 0x01, 0xe7, 0x68, 0x27, 0xf6, 0x74, 0x73, 0xdd, 0x43, 0xaf, 0xd1, + 0x30, 0x83, 0x47, 0x56, 0x26, 0x08, 0x89, 0x1d, 0x3a, 0xf2, 0xdd, 0xc8, + 0x27, 0x5f, 0xce, 0x3f, 0xe7, 0x94, 0x3a, 0xa1, 0x51, 0xfc, 0xe4, 0x92, + 0x1f, 0x71, 0xa1, 0x29, 0xf4, 0x67, 0x9b, 0x0f, 0x36, 0xc5, 0x2f, 0xba, + 0x05, 0xc1, 0xd7, 0x3e, 0x8e, 0xb8, 0x0a, 0x93, 0xa9, 0xcf, 0x40, 0x48, + 0x40, 0x2b, 0x73, 0xb0, 0xa8, 0x7c, 0xa8, 0x65, 0x6d, 0xb1, 0x55, 0x09, + 0x35, 0x68, 0x56, 0xad, 0x48, 0xd5, 0x71, 0xdc, 0x4e, 0x14, 0xcf, 0x28, + 0x1e, 0x50, 0xdb, 0x0c, 0xaa, 0x4c, 0xa4, 0x3e, 0x29, 0x19, 0x73, 0x63, + 0xb0, 0xde, 0x35, 0xa4, 0x94, 0x89, 0x34, 0xa3, 0x1e, 0x47, 0xd0, 0xb9, + 0x4c, 0xdd, 0x9f, 0xee, 0x78, 0xc8, 0x7f, 0x86, 0x90, 0xca, 0xde, 0xd4, + 0xfe, 0xbf, 0xa9, 0xc1, 0x80, 0x8f, 0x65, 0x93, 0xfd, 0xb8, 0x7f, 0xfd, + 0x96, 0x4d, 0xb5, 0x0c, 0xcb, 0xf2, 0xf1, 0x1f, 0xf3, 0xaf, 0x9a, 0xee, + 0xd3, 0x45, 0x15, 0x7f, 0xfe, 0x7f, 0xe1, 0xbd, 0x4d, 0x75, 0x3d, 0xdc, + 0x13, 0xab, 0x88, 0x80, 0x12, 0xdb, 0xf3, 0x0b, 0x79, 0x31, 0x08, 0xc8, + 0xc8, 0x53, 0x5f, 0xe6, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0xe8, 0xbf, 0xf9, + 0x87, 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x25, 0xdf, 0xb8, 0xd7, 0x76, + 0x9a, 0x2f, 0x2b, 0x9f, 0x61, 0xd6, 0x63, 0x0f, 0x2b, 0x6c, 0xce, 0xa1, + 0xf5, 0x03, 0xa7, 0x28, 0x91, 0xfe, 0x42, 0x61, 0xb0, 0x95, 0x98, 0xe1, + 0x67, 0xfd, 0x95, 0x22, 0x37, 0x96, 0x17, 0xa9, 0x63, 0xbe, 0x45, 0x01, + 0xfe, 0xc8, 0x4d, 0xdf, 0xfe, 0x61, 0x6f, 0x26, 0x33, 0x8d, 0x77, 0x69, + 0xa2, 0x59, 0xb8, 0x1d, 0x3a, 0xff, 0x20, 0x7b, 0x88, 0x2a, 0x1d, 0x7d, + 0xd7, 0xf0, 0x0e, 0xbe, 0xec, 0x2b, 0xac, 0xeb, 0xc0, 0x6b, 0x9d, 0x52, + 0x44, 0x8a, 0x18, 0xab, 0x90, 0xfd, 0x24, 0xbf, 0x83, 0xe0, 0x3c, 0xb4, + 0x75, 0xef, 0x3a, 0xce, 0xbf, 0xf7, 0x63, 0xa8, 0xa7, 0xb4, 0xff, 0x9d, + 0x7f, 0x0f, 0xb9, 0x0e, 0xd3, 0xaf, 0x9a, 0xee, 0xd3, 0x44, 0x67, 0x7f, + 0x24, 0x2e, 0x7c, 0x64, 0xeb, 0x86, 0x47, 0x59, 0x67, 0x5f, 0x93, 0x9d, + 0x76, 0x38, 0x7a, 0x4b, 0x2d, 0xfa, 0x2b, 0x7f, 0x3c, 0x93, 0x8f, 0xc3, + 0xaf, 0xfe, 0xd2, 0x03, 0x58, 0x20, 0x96, 0x68, 0xeb, 0xda, 0x8d, 0xce, + 0xa9, 0x27, 0x81, 0x87, 0xfc, 0x2b, 0x5b, 0xf8, 0xa7, 0x68, 0xaf, 0xc8, + 0x57, 0xfd, 0xc7, 0x67, 0xa9, 0x1c, 0x83, 0xaf, 0xfa, 0x5a, 0xc8, 0xf9, + 0x1a, 0x59, 0xd7, 0xdb, 0xf6, 0x34, 0x75, 0xf6, 0xa3, 0xda, 0x3a, 0xb0, + 0xf0, 0xf4, 0x45, 0x7f, 0xf7, 0x93, 0x8f, 0xff, 0xcd, 0xe5, 0x0b, 0x3a, + 0xfc, 0x31, 0x2d, 0x39, 0xd4, 0x87, 0xd9, 0xb1, 0x1e, 0xff, 0xff, 0xfb, + 0x3d, 0xe4, 0x5f, 0x13, 0x37, 0x10, 0x7a, 0x3b, 0xf3, 0x62, 0x7a, 0x68, + 0x3a, 0xff, 0x3c, 0xb5, 0xa7, 0x19, 0x1d, 0x7e, 0x53, 0xde, 0x85, 0x9d, + 0x7f, 0xfb, 0xd0, 0xd4, 0xf2, 0x2e, 0x6d, 0x20, 0x9d, 0x69, 0x1d, 0x48, + 0x7b, 0x1f, 0x52, 0x2f, 0xdf, 0xc7, 0xa0, 0x27, 0x52, 0x23, 0x29, 0xe1, + 0x00, 0x02, 0x3b, 0xff, 0xe0, 0x7b, 0x5b, 0xca, 0x07, 0xfd, 0x7c, 0x00, + 0x9d, 0x7a, 0x3d, 0x07, 0x50, 0x4f, 0xb7, 0x62, 0x9d, 0xee, 0xe0, 0x9d, + 0x48, 0x6f, 0x80, 0x49, 0x77, 0x66, 0x3a, 0xff, 0x6f, 0xa1, 0xce, 0x06, + 0x0e, 0xa4, 0x3c, 0x97, 0x17, 0xbe, 0xf7, 0x41, 0xb6, 0x75, 0xfe, 0xc8, + 0xe3, 0xc9, 0x3a, 0x75, 0xfe, 0x46, 0x75, 0x1d, 0x75, 0x73, 0xab, 0x87, + 0xcb, 0xe3, 0x0a, 0x44, 0x56, 0x2e, 0x11, 0x57, 0xff, 0x93, 0xa0, 0x57, + 0x0f, 0x41, 0xad, 0xe4, 0xe7, 0x56, 0x1f, 0xab, 0x93, 0xde, 0xfb, 0x8a, + 0xa3, 0xaf, 0xff, 0x03, 0xf5, 0xa0, 0xe7, 0xe3, 0x8f, 0x31, 0xd7, 0xfd, + 0x09, 0xd4, 0x81, 0x98, 0x07, 0x5f, 0xf8, 0x01, 0xe6, 0x03, 0xb0, 0xbc, + 0x3a, 0xb1, 0x1b, 0xbc, 0x21, 0xea, 0x4e, 0x8d, 0xaf, 0xff, 0xb7, 0x92, + 0x70, 0x3d, 0x07, 0x31, 0xbd, 0xc3, 0xae, 0x46, 0x4e, 0xbb, 0x6b, 0x0e, + 0xad, 0x1a, 0xef, 0x0b, 0x5f, 0xda, 0x8f, 0x6b, 0xa8, 0x75, 0xf8, 0x71, + 0x7c, 0xc3, 0xaf, 0xb9, 0xb3, 0x02, 0x75, 0x61, 0xfa, 0x2c, 0xb0, 0x04, + 0xb7, 0xdf, 0xa6, 0xf2, 0x3a, 0xff, 0x40, 0xf9, 0x27, 0x18, 0x3a, 0xff, + 0xf2, 0x71, 0x27, 0x81, 0xce, 0xf0, 0x1b, 0x0e, 0xaf, 0xd1, 0x3a, 0x24, + 0x7e, 0x30, 0xb3, 0x0a, 0xdb, 0x30, 0x02, 0x21, 0x4f, 0x3a, 0x08, 0x4b, + 0x72, 0x3d, 0xb5, 0x18, 0xf7, 0x37, 0x47, 0xc9, 0xa1, 0x1b, 0xc2, 0x35, + 0xc2, 0x03, 0xb0, 0xfb, 0x78, 0x6f, 0x7e, 0xd2, 0x31, 0xa0, 0xea, 0x1f, + 0xbe, 0x3c, 0xd8, 0xfd, 0xb7, 0x09, 0x5f, 0xb0, 0xcb, 0xbf, 0xfc, 0xc2, + 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xd3, 0x7f, 0xf9, 0x85, 0xbc, + 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0xc6, 0xff, 0xf3, 0x0b, 0x79, 0x31, + 0x9c, 0x6b, 0xbb, 0x4d, 0x14, 0x0d, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xe0, + 0xbf, 0x87, 0x3c, 0xd4, 0xd1, 0xd7, 0x42, 0x1d, 0x7f, 0x86, 0x50, 0x81, + 0xc5, 0x9d, 0x58, 0x8a, 0x25, 0x99, 0xf4, 0xac, 0x02, 0x97, 0xe9, 0x30, + 0xa2, 0xa1, 0x43, 0xa9, 0x83, 0xeb, 0x83, 0xcb, 0x9f, 0xf3, 0xaf, 0xd3, + 0x4a, 0x06, 0x47, 0x51, 0xd5, 0x86, 0xc4, 0x49, 0xef, 0xa3, 0xfc, 0x64, + 0xeb, 0x91, 0x8e, 0x22, 0x20, 0x51, 0xfe, 0x8f, 0xdf, 0xf4, 0x98, 0xce, + 0x35, 0xdd, 0xa6, 0x89, 0x26, 0xcc, 0x75, 0x10, 0x4e, 0x7b, 0x73, 0x3f, + 0x9d, 0x7f, 0x9f, 0xc3, 0x93, 0xb8, 0x9d, 0x7f, 0x60, 0xbe, 0xf2, 0xd1, + 0xd7, 0xf4, 0x2f, 0x98, 0x1f, 0x1d, 0x73, 0xb0, 0x14, 0x50, 0x28, 0x31, + 0xc3, 0x0d, 0x16, 0x54, 0xed, 0x90, 0x04, 0xa9, 0x8a, 0xed, 0x8d, 0x62, + 0x65, 0x7f, 0xd5, 0xf5, 0x1b, 0x27, 0xa3, 0x2c, 0xd9, 0x0c, 0x9b, 0xff, + 0x28, 0xec, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0xa9, 0x7f, 0xe7, 0x93, 0x19, + 0xc6, 0xbb, 0xb4, 0xd1, 0x2a, 0xdc, 0x8c, 0x9d, 0x47, 0x59, 0x85, 0x11, + 0x6a, 0xb4, 0xbf, 0x25, 0x6d, 0x0b, 0x5f, 0xd9, 0xc6, 0xbb, 0xb4, 0xd1, + 0x14, 0xdf, 0xfc, 0xb6, 0x3c, 0x2f, 0xfe, 0xbd, 0x8d, 0x3a, 0x98, 0x3f, + 0xd7, 0x38, 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0x69, 0x70, 0x3a, + 0x75, 0xff, 0x83, 0x8b, 0x4e, 0x66, 0xa6, 0x83, 0xaf, 0xff, 0xf9, 0xc1, + 0xae, 0xe0, 0x7e, 0xfd, 0xd2, 0x7d, 0xf2, 0x6a, 0x6f, 0xa7, 0x5e, 0x47, + 0x64, 0xea, 0x44, 0x63, 0xab, 0x9e, 0xad, 0xbe, 0xf9, 0xae, 0xed, 0x34, + 0x53, 0xf7, 0x7a, 0x0e, 0xae, 0x1e, 0x17, 0x8b, 0x6f, 0xfd, 0xe9, 0xa3, + 0xdd, 0x79, 0xbe, 0x61, 0xd7, 0xff, 0x91, 0x62, 0x0e, 0xa7, 0x33, 0x53, + 0x41, 0xd7, 0xff, 0x03, 0xdc, 0x04, 0xda, 0x6b, 0xcd, 0xa3, 0xaf, 0xfe, + 0xc9, 0x80, 0x33, 0xe9, 0xaf, 0x36, 0x8e, 0xb3, 0x0a, 0xda, 0xa8, 0x98, + 0x86, 0xee, 0x3a, 0x21, 0x13, 0xa0, 0x8a, 0x47, 0x91, 0xef, 0xff, 0x30, + 0xb7, 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x35, 0x5f, 0xe6, 0x33, 0x8d, + 0x77, 0x69, 0xa2, 0xbb, 0xbe, 0x6b, 0xbb, 0x4d, 0x15, 0xf5, 0xe6, 0x59, + 0x64, 0xab, 0x09, 0x4c, 0x17, 0xf5, 0xc3, 0xeb, 0x5a, 0x65, 0xe9, 0x46, + 0xe7, 0x5e, 0x9b, 0x3a, 0x75, 0xff, 0xb3, 0xac, 0xbf, 0xb5, 0x19, 0x39, + 0xd6, 0xf1, 0xd7, 0xfc, 0x9c, 0xc9, 0xd2, 0x58, 0x13, 0xab, 0x87, 0x8e, + 0xe2, 0x17, 0xed, 0xf6, 0xba, 0x0f, 0xa7, 0x5b, 0x87, 0x51, 0xd6, 0xea, + 0x17, 0x5c, 0x10, 0xb3, 0x18, 0x9b, 0x6c, 0xc4, 0x4e, 0x38, 0x23, 0x9a, + 0x84, 0x28, 0x08, 0x76, 0xd2, 0x2f, 0xff, 0x30, 0xb7, 0x93, 0x19, 0xc6, + 0xbb, 0xb4, 0xd1, 0x3d, 0xdf, 0xbb, 0x1b, 0x4f, 0xb9, 0xd7, 0xee, 0x35, + 0xdd, 0xa6, 0x8b, 0x86, 0xcc, 0x41, 0xee, 0xe1, 0x55, 0xff, 0xcc, 0x3c, + 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x3e, 0xa1, 0x90, 0x5b, 0x3c, 0x31, + 0x64, 0x44, 0xa4, 0xac, 0x86, 0xb9, 0x4c, 0xaf, 0xc9, 0x42, 0xfd, 0x72, + 0xd4, 0x2d, 0x36, 0x13, 0xdf, 0xe6, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x2a, + 0xbf, 0x71, 0xae, 0xed, 0x34, 0x53, 0x37, 0xf2, 0x77, 0x1f, 0x7f, 0xce, + 0xb3, 0x18, 0x7c, 0x1b, 0x66, 0x77, 0xff, 0x98, 0x5b, 0xc9, 0x8c, 0xe3, + 0x5d, 0xda, 0x68, 0x99, 0xef, 0xff, 0x30, 0xb7, 0x93, 0x19, 0xc6, 0xbb, + 0xb4, 0xd1, 0x46, 0xd4, 0xe9, 0xbc, 0x06, 0x13, 0xea, 0x15, 0xf9, 0x5e, + 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x3a, 0xbf, 0xfb, 0x93, + 0xb1, 0xa1, 0xcf, 0x6a, 0x16, 0x75, 0x30, 0x88, 0xf8, 0x4a, 0xb8, 0x1d, + 0x3a, 0xf9, 0xad, 0x03, 0x4e, 0xbf, 0x60, 0x87, 0x27, 0x3a, 0xff, 0x44, + 0x37, 0x39, 0xcc, 0x3a, 0x90, 0xf5, 0x84, 0x9a, 0xfd, 0x9c, 0x68, 0x14, + 0x3a, 0xff, 0xc3, 0x8a, 0x3c, 0xda, 0xec, 0x04, 0xeb, 0xd3, 0x3f, 0x8e, + 0xbe, 0x6b, 0xbb, 0x4d, 0x14, 0xd5, 0xfb, 0x37, 0x65, 0xfa, 0x75, 0xff, + 0xda, 0xc1, 0x0c, 0x7c, 0x55, 0xfb, 0x3f, 0x43, 0xa8, 0x29, 0x92, 0x21, + 0x44, 0xc7, 0xdc, 0x1c, 0x12, 0xdd, 0x14, 0x5f, 0xff, 0xf6, 0x0f, 0xb4, + 0x8d, 0xc1, 0xd3, 0x7a, 0x9d, 0x6f, 0xd9, 0xce, 0xbf, 0xed, 0x3e, 0xf9, + 0x34, 0x77, 0x47, 0x5d, 0xd4, 0x14, 0x50, 0x79, 0x9e, 0xff, 0xe9, 0x75, + 0x06, 0x7d, 0x02, 0x39, 0x31, 0xd7, 0xfd, 0xad, 0x35, 0x39, 0xc4, 0x9c, + 0xeb, 0xff, 0x63, 0x2f, 0xfb, 0xfb, 0xd9, 0xd3, 0xaf, 0xfc, 0x20, 0xf7, + 0x72, 0x69, 0x46, 0xe7, 0x5a, 0x63, 0xaf, 0xd9, 0xd7, 0x10, 0x9d, 0x53, + 0x9b, 0x6f, 0xc4, 0x6e, 0x85, 0x0e, 0xbf, 0x9f, 0xfd, 0x2a, 0xca, 0xb2, + 0xac, 0x75, 0xfc, 0x90, 0xb9, 0xf1, 0x93, 0xaf, 0xff, 0xb3, 0xdd, 0xc9, + 0x71, 0xc7, 0xdd, 0x79, 0x1d, 0x74, 0x7e, 0x75, 0xfe, 0x7d, 0xe1, 0xa8, + 0xd6, 0x38, 0x89, 0x01, 0x2d, 0xfa, 0x9b, 0x58, 0x9e, 0xaa, 0x3a, 0xf4, + 0x8c, 0x45, 0xb5, 0x0c, 0xdb, 0xf7, 0xba, 0xcb, 0xce, 0x75, 0x98, 0x56, + 0xd7, 0x7f, 0x60, 0x58, 0x2f, 0x19, 0x1a, 0x23, 0x61, 0xef, 0xb9, 0x6f, + 0x11, 0x44, 0xe7, 0xd2, 0x84, 0xfe, 0xa6, 0xdf, 0xb8, 0xd7, 0x76, 0x9a, + 0x2a, 0xab, 0xff, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0xb6, 0xcc, + 0x61, 0xfe, 0xac, 0xce, 0xff, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x15, 0xfd, + 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xc6, 0xbb, 0x6a, 0x47, 0x59, 0x8c, 0x3c, + 0xc9, 0x8c, 0xef, 0xda, 0x6f, 0x61, 0x43, 0xaf, 0xf0, 0x82, 0x59, 0xa7, + 0xf1, 0xd7, 0x73, 0xc7, 0x5f, 0xf6, 0x7b, 0xd9, 0xc0, 0xe0, 0x9d, 0x79, + 0x49, 0x61, 0xd6, 0x63, 0x11, 0x32, 0xe6, 0x22, 0x2d, 0xa3, 0x6b, 0x23, + 0x09, 0x81, 0x72, 0x18, 0x37, 0xee, 0x35, 0xdd, 0xa6, 0x8b, 0x56, 0xff, + 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x82, 0xbf, 0x43, 0x3b, 0x79, + 0xc3, 0xac, 0xc6, 0x22, 0x9d, 0x66, 0x7f, 0x52, 0xaf, 0xf4, 0x0f, 0xf0, + 0xae, 0xeb, 0x3a, 0xee, 0x41, 0xd5, 0x23, 0xc9, 0xda, 0x34, 0xbe, 0x6b, + 0xbb, 0x4d, 0x17, 0x15, 0xfc, 0x07, 0xdc, 0x39, 0xc3, 0xab, 0x87, 0xb5, + 0xa2, 0xdb, 0xdc, 0x85, 0x9d, 0x7c, 0xfb, 0x49, 0x39, 0xd7, 0xee, 0x81, + 0x4c, 0x13, 0xaf, 0x6d, 0x23, 0x4e, 0xa0, 0x9e, 0x2e, 0xd1, 0x3d, 0xfe, + 0x5b, 0xcb, 0x48, 0x1c, 0x3a, 0xff, 0x42, 0xdf, 0x64, 0x73, 0x68, 0xeb, + 0xfb, 0x38, 0xfe, 0x04, 0x1d, 0x7f, 0xfc, 0xe3, 0x09, 0xb5, 0xa4, 0xd6, + 0x77, 0x36, 0xce, 0xa0, 0x9f, 0xe6, 0xc2, 0xbb, 0xff, 0x90, 0x41, 0x2c, + 0xd6, 0x90, 0x38, 0x75, 0x4c, 0x7c, 0xbe, 0x24, 0xb3, 0x10, 0xaa, 0xd7, + 0x1f, 0xf8, 0x45, 0xd1, 0xb7, 0x69, 0xfc, 0x97, 0xc6, 0x3f, 0x63, 0x17, + 0xbf, 0x2a, 0x95, 0xa7, 0xea, 0x41, 0xd7, 0xfe, 0x4d, 0xd5, 0x6d, 0x73, + 0xe7, 0xce, 0xed, 0x9d, 0x7d, 0xd8, 0xf3, 0x4e, 0xa5, 0x6a, 0x7d, 0xa1, + 0x4c, 0xbf, 0xfc, 0xab, 0x28, 0xca, 0xbc, 0xe1, 0x55, 0x7c, 0xf9, 0xdd, + 0xb3, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x17, 0x4d, 0xfa, 0x05, 0xc3, 0x07, + 0x5e, 0x8f, 0x6d, 0x1d, 0x7d, 0x81, 0xc0, 0x9d, 0x7f, 0xcf, 0xb2, 0x3d, + 0xa0, 0x35, 0x52, 0x75, 0x98, 0x55, 0x93, 0xfd, 0x88, 0x50, 0x48, 0xa3, + 0x18, 0x90, 0xcf, 0xa4, 0x8e, 0x3c, 0x24, 0x17, 0xff, 0xd8, 0x3e, 0x45, + 0xf6, 0x10, 0x5f, 0x8a, 0x1d, 0x7f, 0x4f, 0x1e, 0x75, 0x00, 0x75, 0x1d, + 0x7f, 0xf4, 0x73, 0xff, 0x9a, 0xec, 0x2d, 0xc4, 0xeb, 0xfd, 0x1c, 0xfb, + 0xde, 0xe7, 0xe7, 0x54, 0x8f, 0xeb, 0xa8, 0xb7, 0xf4, 0x9e, 0x4e, 0x2d, + 0x3a, 0xff, 0xf6, 0x7a, 0x19, 0xfb, 0x3e, 0xb1, 0x70, 0xae, 0x75, 0x98, + 0x56, 0x53, 0x20, 0xc8, 0x42, 0x4c, 0x44, 0x25, 0x75, 0xc4, 0xe7, 0x17, + 0x1a, 0x75, 0xf6, 0x32, 0xac, 0xac, 0xeb, 0xfe, 0x4e, 0x0c, 0x6e, 0xb7, + 0xf1, 0xd7, 0xff, 0xfc, 0x0e, 0x4b, 0x5d, 0x74, 0xe7, 0x38, 0x0d, 0xd3, + 0x8f, 0xa3, 0xaf, 0xfc, 0x2e, 0xcf, 0xb3, 0xaf, 0x33, 0x9d, 0x7f, 0xff, + 0x74, 0x40, 0xea, 0xf9, 0x2e, 0xe2, 0x98, 0x19, 0x80, 0x75, 0xcd, 0xc3, + 0xaa, 0x0f, 0xcd, 0x45, 0xeb, 0xca, 0x6a, 0x47, 0x5f, 0xfa, 0x59, 0xce, + 0x3c, 0xa7, 0xc6, 0x4e, 0xbf, 0xfb, 0x03, 0x12, 0x8e, 0x47, 0xd7, 0x13, + 0xaf, 0xfd, 0xb3, 0x24, 0xb0, 0xa6, 0xc8, 0x09, 0xd4, 0xb4, 0x41, 0xba, + 0x15, 0xce, 0xc4, 0xea, 0x8e, 0xa6, 0x67, 0xe4, 0x2c, 0x34, 0x45, 0xe1, + 0xdf, 0xb0, 0xc2, 0xae, 0xaa, 0xe4, 0x19, 0x4e, 0x37, 0xfe, 0xf2, 0x35, + 0x02, 0xe2, 0xa4, 0x1d, 0x7f, 0xd1, 0xbf, 0x5f, 0x5e, 0x86, 0x4e, 0xa8, + 0x3f, 0x5e, 0x1e, 0x5c, 0x0e, 0x9d, 0x7e, 0x1c, 0xeb, 0xf8, 0xeb, 0xfa, + 0x4f, 0x9b, 0x20, 0x27, 0x52, 0xa0, 0xf4, 0x95, 0x79, 0x2d, 0xf2, 0x02, + 0x50, 0x75, 0xf9, 0xe6, 0x92, 0x78, 0xeb, 0xff, 0x40, 0x79, 0x12, 0x4d, + 0xfd, 0x87, 0x54, 0x91, 0x09, 0xf9, 0x07, 0x89, 0xef, 0xff, 0xfa, 0x03, + 0xdc, 0xdf, 0xc2, 0xfd, 0xfd, 0xf5, 0xa7, 0xe3, 0x4e, 0xbf, 0xd9, 0x98, + 0xa2, 0x8f, 0x23, 0xa9, 0x44, 0x4c, 0x79, 0x9a, 0xfd, 0xb1, 0x39, 0x81, + 0x3a, 0xff, 0xfb, 0x5d, 0x4d, 0x7b, 0xb8, 0x14, 0xd6, 0x09, 0xd7, 0xbb, + 0x03, 0x87, 0xea, 0x02, 0x8b, 0xfd, 0x0b, 0xc4, 0x5c, 0x2b, 0x9d, 0x7f, + 0xa4, 0xbd, 0x20, 0xef, 0x23, 0xa9, 0xa7, 0xcd, 0x31, 0x9d, 0xe7, 0x76, + 0x9a, 0x24, 0xcb, 0xdb, 0x49, 0xa3, 0xa9, 0xa7, 0x8b, 0xb4, 0x4f, 0x7e, + 0x6a, 0xac, 0xaa, 0x56, 0x55, 0x07, 0x5f, 0xec, 0xdf, 0xde, 0x79, 0x68, + 0xea, 0x83, 0xed, 0xe1, 0xd5, 0xfe, 0x17, 0xf6, 0x9a, 0x01, 0x3a, 0xff, + 0xfe, 0xe6, 0x7e, 0x9f, 0xb3, 0x89, 0xb0, 0x73, 0xdd, 0x43, 0xab, 0x11, + 0x1a, 0x86, 0x35, 0x25, 0x4c, 0x19, 0x09, 0x7e, 0x34, 0x2e, 0x12, 0x5d, + 0x85, 0x75, 0xfc, 0x1f, 0xd5, 0x1a, 0xff, 0x6c, 0xeb, 0xda, 0x40, 0x9d, + 0x7f, 0x0c, 0x6e, 0xb7, 0xf1, 0xd7, 0xfd, 0x0d, 0xf0, 0x3b, 0xc8, 0x64, + 0xeb, 0xfc, 0xd4, 0xe6, 0xa6, 0x87, 0x3a, 0xff, 0xe0, 0x6b, 0xaf, 0x2e, + 0xbc, 0xa0, 0x4e, 0xad, 0xcf, 0xd3, 0x86, 0x57, 0x75, 0x26, 0x4c, 0x5f, + 0x83, 0x6b, 0x2c, 0xf4, 0x2b, 0x6f, 0xbc, 0x8b, 0x73, 0xaf, 0xf2, 0x77, + 0x51, 0xe8, 0x09, 0xd5, 0x87, 0xa3, 0xe2, 0x0b, 0xfe, 0x8e, 0xf9, 0x27, + 0x5c, 0x34, 0xeb, 0xff, 0xf3, 0xb7, 0x91, 0xd1, 0xcf, 0x63, 0x0c, 0xb2, + 0xc9, 0x55, 0x24, 0x58, 0x68, 0x87, 0xc7, 0x17, 0xf3, 0x5a, 0x06, 0x8c, + 0x1d, 0x7f, 0xfb, 0x37, 0x90, 0xc4, 0xb9, 0x1e, 0x7f, 0x1d, 0x7f, 0xe7, + 0xf4, 0x73, 0x5d, 0x81, 0xf1, 0xd7, 0xec, 0x92, 0x3e, 0xc3, 0xa8, 0x4f, + 0x8f, 0x47, 0x95, 0x24, 0x66, 0x02, 0x15, 0x77, 0xff, 0x86, 0x25, 0xce, + 0x03, 0x74, 0xe3, 0xe8, 0xeb, 0xff, 0xed, 0x62, 0x83, 0x9e, 0xd6, 0x48, + 0x5d, 0x93, 0xae, 0xd8, 0x9d, 0x44, 0xbf, 0x92, 0x6f, 0xb6, 0xa3, 0xba, + 0x3a, 0xa0, 0xf5, 0x30, 0xc2, 0xfe, 0xf0, 0x82, 0x7d, 0xd5, 0xce, 0xbf, + 0xfd, 0x13, 0x8e, 0x64, 0xfe, 0x52, 0x06, 0x47, 0x5f, 0xf9, 0xc6, 0x7e, + 0xba, 0xd3, 0x48, 0x75, 0x3a, 0x2d, 0xc4, 0xc9, 0x94, 0x9b, 0xcc, 0xb2, + 0xc9, 0x57, 0xd3, 0xad, 0x34, 0x53, 0x05, 0xfd, 0xd0, 0x13, 0xad, 0xc7, + 0x3c, 0x71, 0x32, 0xbf, 0xff, 0xf8, 0x0e, 0x2d, 0xe6, 0x6c, 0x81, 0xf2, + 0xe3, 0x04, 0x39, 0xbf, 0x8e, 0xbf, 0xd2, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, + 0xfb, 0x5a, 0x4c, 0x1f, 0xce, 0xbd, 0xcc, 0x57, 0x3a, 0xff, 0xd0, 0xcf, + 0xd9, 0xf5, 0x8b, 0x85, 0x73, 0xab, 0x88, 0x8e, 0x59, 0x67, 0x87, 0xaa, + 0x11, 0xe5, 0x90, 0xc2, 0xbf, 0x27, 0xa7, 0xc6, 0x4e, 0xbf, 0xe8, 0x6f, + 0x44, 0x1e, 0x8d, 0x1d, 0x7f, 0xf2, 0x6d, 0x43, 0x61, 0x78, 0x17, 0x59, + 0xd7, 0xff, 0xef, 0x77, 0x25, 0xf1, 0xbd, 0x4f, 0x6e, 0xd4, 0xe1, 0xd5, + 0xc4, 0x7d, 0xac, 0xa3, 0xa6, 0xe2, 0x89, 0x7f, 0xcb, 0x8e, 0x6c, 0xce, + 0x44, 0xc7, 0x5f, 0xfb, 0x8d, 0x5c, 0x6f, 0xac, 0xd9, 0x87, 0x5f, 0xe1, + 0xff, 0x6f, 0x03, 0x8b, 0x3a, 0xfe, 0x1f, 0x9b, 0x79, 0xc8, 0x3a, 0xa1, + 0x14, 0xb8, 0x80, 0xe6, 0xb7, 0xfd, 0x8f, 0xff, 0xcc, 0x0b, 0xc8, 0xeb, + 0xff, 0xcf, 0x3f, 0x52, 0x07, 0x26, 0x4e, 0x21, 0xd5, 0x89, 0xe4, 0x7e, + 0x79, 0xa8, 0x6f, 0xf8, 0xb5, 0x93, 0x9b, 0xf0, 0xe7, 0x5f, 0xc7, 0x5f, + 0xfa, 0x50, 0x33, 0xfd, 0xe0, 0x82, 0x47, 0x52, 0xb9, 0xf2, 0xcc, 0x4b, + 0x7d, 0xe9, 0xf0, 0x27, 0x5f, 0xf2, 0x29, 0xf7, 0x9f, 0xad, 0x34, 0x75, + 0x4c, 0x7b, 0xdb, 0x64, 0x57, 0x99, 0x65, 0x93, 0xaf, 0xff, 0xd8, 0xbf, + 0x0c, 0x7f, 0x81, 0xd6, 0x2e, 0x1a, 0x53, 0x05, 0xfd, 0xfe, 0xc6, 0xf5, + 0x20, 0x5a, 0x75, 0xfe, 0xe4, 0x79, 0x1a, 0x81, 0x3a, 0xfd, 0x29, 0xb3, + 0x1a, 0x75, 0xb8, 0x75, 0x2b, 0x07, 0xd1, 0x06, 0x3f, 0x49, 0xeb, 0x13, + 0xf9, 0x48, 0x42, 0x75, 0x14, 0x58, 0xf5, 0x09, 0x8b, 0xde, 0x97, 0x4e, + 0xb2, 0x1d, 0x7f, 0x76, 0x3e, 0x35, 0x27, 0x3a, 0xfe, 0xe3, 0xf0, 0x62, + 0x47, 0x5f, 0xff, 0x42, 0x9a, 0xeb, 0xa7, 0xa1, 0x62, 0xea, 0x1d, 0x7f, + 0xec, 0xd9, 0xd4, 0xf9, 0xad, 0x22, 0xce, 0xb9, 0xfd, 0x24, 0x47, 0xf5, + 0x3a, 0xff, 0xc9, 0x24, 0xe6, 0xf0, 0x31, 0xa3, 0xa9, 0x5a, 0x26, 0xc4, + 0x10, 0xfe, 0x17, 0x8c, 0x2e, 0xbc, 0x5d, 0x74, 0x98, 0x56, 0xdb, 0x4b, + 0xe5, 0x53, 0x44, 0x42, 0xc2, 0x50, 0xc9, 0xc9, 0x5f, 0x2a, 0x2d, 0x36, + 0x34, 0xed, 0xe3, 0x50, 0x43, 0x09, 0xa1, 0xf1, 0xc8, 0xc4, 0xfb, 0x0d, + 0x77, 0x84, 0xaf, 0xe4, 0xc3, 0x1b, 0x16, 0xa5, 0x74, 0xfa, 0x55, 0x7e, + 0xda, 0x97, 0xd8, 0xdf, 0xaf, 0xff, 0x73, 0x19, 0x0f, 0x72, 0x61, 0xce, + 0x48, 0xeb, 0xdc, 0xc5, 0x73, 0xaf, 0xfd, 0x0c, 0xfd, 0x9f, 0x58, 0xb8, + 0x57, 0x3a, 0xb8, 0x8a, 0xc5, 0xa5, 0x78, 0x7a, 0xff, 0xf9, 0xd7, 0x1c, + 0x6f, 0x00, 0xa7, 0x00, 0xfa, 0x3a, 0xb1, 0x10, 0x00, 0x30, 0xbf, 0xdc, + 0x68, 0x1c, 0x2b, 0x83, 0xaf, 0xfe, 0x8e, 0x7d, 0xf2, 0x7b, 0xb8, 0x14, + 0x3a, 0xff, 0xdd, 0x18, 0x9f, 0xef, 0x7a, 0xea, 0xe7, 0x54, 0x22, 0xe6, + 0x73, 0x2c, 0x44, 0xbc, 0xfc, 0x9c, 0xeb, 0x99, 0x64, 0xeb, 0xce, 0xd6, + 0x1a, 0x6d, 0x19, 0x1c, 0xbf, 0xa3, 0x8f, 0x24, 0xe9, 0xd7, 0xec, 0x5f, + 0x5c, 0x27, 0x59, 0x88, 0x6f, 0xbd, 0xb2, 0x3e, 0x85, 0x0a, 0x9b, 0x2c, + 0x2f, 0x90, 0xa0, 0x7a, 0xd3, 0x7c, 0x65, 0x4b, 0xea, 0x1b, 0x7b, 0x18, + 0xd9, 0x34, 0xda, 0x2b, 0xa9, 0x3a, 0xff, 0x30, 0xcf, 0x10, 0x6f, 0x19, + 0x4f, 0x0a, 0x17, 0x08, 0xbe, 0xc6, 0x57, 0xfc, 0x35, 0xb5, 0x2c, 0xdb, + 0xd2, 0x9f, 0x41, 0x5f, 0xba, 0x5f, 0xda, 0x89, 0xa4, 0x93, 0x1d, 0x7f, + 0xfa, 0x27, 0xcf, 0x40, 0xa7, 0xf9, 0xbf, 0x8e, 0xb3, 0x1a, 0x3f, 0x7f, + 0xa5, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0xd6, 0xf2, 0x9b, 0xe8, 0xeb, + 0x31, 0x87, 0xa3, 0xe3, 0x3b, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x4b, 0x73, + 0xb4, 0xd1, 0x0d, 0x59, 0x8c, 0x3d, 0x57, 0x33, 0xbf, 0x71, 0xae, 0xed, + 0x34, 0x47, 0xd7, 0xff, 0xc2, 0xfe, 0x94, 0x29, 0xf2, 0x3d, 0xa8, 0xfc, + 0xeb, 0xcf, 0x26, 0x31, 0x10, 0x9f, 0x4c, 0xef, 0xfc, 0xf3, 0xc7, 0x53, + 0x89, 0x0b, 0x3a, 0xff, 0x47, 0x30, 0x7d, 0x9d, 0x3a, 0xf2, 0xf1, 0x8d, + 0xb3, 0xec, 0xfa, 0x79, 0x4c, 0x23, 0x6e, 0x21, 0x45, 0x7f, 0xff, 0xd2, + 0x07, 0x14, 0x7d, 0x60, 0x63, 0x7d, 0x7d, 0xf2, 0x88, 0xa1, 0xd7, 0xf0, + 0x37, 0xde, 0x59, 0xe3, 0xaf, 0xff, 0x2a, 0xca, 0x32, 0xaf, 0x38, 0x55, + 0x5f, 0x3e, 0x77, 0x6c, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x8f, 0x73, + 0xe8, 0xeb, 0xfa, 0x7f, 0xbc, 0xe6, 0x70, 0xea, 0x91, 0xe2, 0xb8, 0xad, + 0xff, 0x0b, 0xa9, 0xd4, 0x81, 0x9c, 0xeb, 0xff, 0xf7, 0xf2, 0x9d, 0x56, + 0x85, 0x6e, 0x76, 0xf3, 0xe7, 0xce, 0xed, 0x9d, 0x7e, 0x4f, 0x79, 0x3c, + 0x75, 0xf7, 0x39, 0x9b, 0x67, 0x56, 0x1e, 0x53, 0x93, 0x5f, 0xb3, 0x99, + 0x93, 0x1d, 0x66, 0x21, 0x56, 0x44, 0xed, 0x92, 0x2f, 0xc6, 0x24, 0x78, + 0x98, 0x87, 0xa6, 0xfa, 0x85, 0xaf, 0xd2, 0x0b, 0xca, 0xb2, 0xd4, 0x3a, + 0xfe, 0x54, 0x0e, 0x75, 0xfc, 0x75, 0xfe, 0x7f, 0xf4, 0xfe, 0xf3, 0x9d, + 0x72, 0xda, 0x75, 0x09, 0xe4, 0x78, 0xca, 0xff, 0xd8, 0xcf, 0x30, 0x5f, + 0x79, 0x68, 0xeb, 0xf6, 0x6b, 0xa8, 0xc9, 0xd7, 0xdf, 0xad, 0x38, 0x75, + 0xff, 0xff, 0x47, 0x07, 0x03, 0x9d, 0xea, 0x37, 0xa9, 0xed, 0x3e, 0xe7, + 0x52, 0x22, 0x1b, 0xa4, 0x57, 0xf4, 0x73, 0xfd, 0xb0, 0x78, 0xeb, 0xfe, + 0x81, 0xf2, 0xa9, 0xfc, 0x08, 0x3a, 0xff, 0xf4, 0x76, 0x16, 0xde, 0xa7, + 0xb3, 0x16, 0x75, 0xf7, 0xff, 0xa7, 0xd3, 0xaf, 0x3b, 0xb4, 0xd1, 0x68, + 0x5f, 0xf9, 0xd9, 0xda, 0x6b, 0xf2, 0x7c, 0x64, 0xeb, 0xfb, 0xf8, 0x18, + 0xf6, 0x8e, 0xa6, 0xa2, 0x5b, 0x84, 0xff, 0xa1, 0xdf, 0xff, 0xff, 0x27, + 0x3a, 0xe2, 0x91, 0xe4, 0xec, 0x6b, 0xb9, 0xae, 0x63, 0x73, 0xc7, 0x54, + 0x95, 0x0b, 0x04, 0xc5, 0xa7, 0x48, 0x8f, 0xc8, 0x5d, 0xf4, 0xc6, 0xec, + 0x59, 0xd7, 0xff, 0x3e, 0xfb, 0x3a, 0xae, 0x9e, 0x18, 0x59, 0xd5, 0xc3, + 0xdd, 0x71, 0x5b, 0xff, 0xf2, 0x7b, 0x4f, 0xbe, 0xb5, 0x9d, 0x4d, 0x02, + 0x73, 0xaf, 0xff, 0x81, 0x3f, 0x13, 0xd3, 0x83, 0x92, 0xd2, 0xba, 0x1d, + 0x5d, 0x45, 0x58, 0xab, 0x5f, 0xff, 0x03, 0x9c, 0x81, 0xc5, 0x13, 0xbd, + 0xcf, 0xa7, 0x59, 0x52, 0x75, 0x70, 0xf9, 0x00, 0xa1, 0x7f, 0x96, 0x01, + 0xf6, 0x81, 0xc3, 0xab, 0x87, 0xab, 0xb6, 0x45, 0x7f, 0x6c, 0x9b, 0xb9, + 0xfb, 0x9d, 0x7e, 0x16, 0xbe, 0x90, 0xeb, 0xff, 0xfb, 0x83, 0x11, 0xbf, + 0xcd, 0x78, 0x60, 0x3d, 0x8f, 0x1d, 0x72, 0x74, 0xeb, 0xe9, 0x0b, 0xfd, + 0x3a, 0xff, 0x05, 0xff, 0xe7, 0x1f, 0xf3, 0xaf, 0xd9, 0xc6, 0xab, 0xb2, + 0x75, 0x21, 0xef, 0x89, 0xa5, 0x42, 0x66, 0xd8, 0x4a, 0xae, 0xb6, 0xe2, + 0xa0, 0x84, 0x0d, 0xe7, 0x57, 0x43, 0xaf, 0xfd, 0xf7, 0xca, 0x22, 0x91, + 0x83, 0x07, 0x5f, 0xbe, 0xf8, 0x63, 0xf3, 0xab, 0x74, 0x42, 0xf0, 0x77, + 0x61, 0xfd, 0xfa, 0x3d, 0x9d, 0x83, 0xaf, 0xff, 0xff, 0x75, 0x03, 0x89, + 0x3f, 0x62, 0x3e, 0x66, 0xf2, 0xd2, 0x79, 0xc7, 0x0e, 0xbf, 0xf6, 0x6f, + 0x2d, 0x4d, 0xc7, 0xf6, 0x8e, 0xbf, 0xfe, 0xcf, 0x6b, 0x26, 0xec, 0x6c, + 0xce, 0xf6, 0x0e, 0xbf, 0xe1, 0x88, 0x9b, 0x36, 0x27, 0x0e, 0xa9, 0xd3, + 0x63, 0x69, 0x2f, 0xee, 0xc2, 0x81, 0xe5, 0x0b, 0xf7, 0xc9, 0xa4, 0x93, + 0x1d, 0x50, 0xa8, 0x37, 0x23, 0x96, 0x44, 0xcb, 0xff, 0xba, 0x9f, 0x30, + 0x71, 0x38, 0xfb, 0x0e, 0xbf, 0xff, 0xdd, 0x81, 0xcf, 0xf5, 0x81, 0xec, + 0x4e, 0xb0, 0x08, 0x4e, 0xa5, 0x11, 0x49, 0xe4, 0x4b, 0xff, 0xfa, 0x26, + 0xc0, 0xf6, 0x36, 0x77, 0x3c, 0x31, 0x0b, 0x3a, 0xfe, 0xdf, 0x5f, 0x67, + 0x00, 0x9d, 0x7f, 0xd0, 0xde, 0xa4, 0xce, 0xf3, 0x9d, 0x4b, 0x46, 0x1b, + 0xad, 0x7e, 0x63, 0x7f, 0xa5, 0x1c, 0x9e, 0x39, 0x39, 0xd7, 0xfc, 0x80, + 0x19, 0x72, 0x30, 0x27, 0x5f, 0xff, 0xf7, 0x72, 0x4d, 0xea, 0x76, 0x33, + 0x92, 0xf0, 0xc2, 0xf4, 0x75, 0x69, 0x13, 0x5e, 0x36, 0xa8, 0x47, 0x8e, + 0x43, 0x3a, 0xff, 0x71, 0xb3, 0x62, 0x74, 0x07, 0x5f, 0xe5, 0xc3, 0x45, + 0xf7, 0xf1, 0xd7, 0xf7, 0x23, 0xd3, 0xe3, 0x27, 0x5f, 0xff, 0xff, 0x20, + 0x39, 0xdc, 0x9a, 0x67, 0xe4, 0xde, 0xe8, 0x3f, 0xd6, 0x26, 0xc0, 0xc1, + 0xd7, 0xef, 0x75, 0xc5, 0x43, 0xaf, 0xf8, 0x41, 0x38, 0x7b, 0x83, 0x07, + 0x5b, 0x02, 0x8e, 0x0c, 0x84, 0x13, 0x49, 0xef, 0xff, 0x73, 0xf6, 0xfe, + 0x39, 0xed, 0x3b, 0x89, 0xd5, 0x09, 0xfa, 0xe1, 0x9a, 0x19, 0x0c, 0x61, + 0xc0, 0x39, 0xbf, 0xd9, 0xd9, 0x93, 0xa8, 0xb3, 0xaf, 0xf4, 0xb3, 0x9a, + 0x18, 0x9c, 0xeb, 0xdb, 0x79, 0x39, 0xd7, 0xb3, 0xae, 0x75, 0xfa, 0x60, + 0x80, 0x02, 0x75, 0x04, 0xf0, 0x9c, 0x6a, 0xff, 0x63, 0x38, 0xd6, 0xe3, + 0x27, 0x5f, 0xf6, 0xeb, 0xcc, 0x1f, 0x6d, 0xe1, 0xd7, 0x94, 0x90, 0x0e, + 0xbf, 0x76, 0x39, 0x3a, 0xce, 0xbf, 0xc0, 0x71, 0xee, 0x3c, 0xc7, 0x5b, + 0x79, 0x8f, 0x65, 0x92, 0x8a, 0x44, 0x50, 0xbb, 0xb5, 0x62, 0x65, 0xee, + 0x66, 0x30, 0xdb, 0xac, 0x54, 0x91, 0xb9, 0x92, 0x19, 0x3b, 0x0e, 0xa3, + 0x50, 0xbb, 0xd0, 0x75, 0xcf, 0xe3, 0xab, 0x86, 0xab, 0xa2, 0xb7, 0xfd, + 0xcc, 0xee, 0x4f, 0xf1, 0x34, 0x75, 0x61, 0xed, 0x80, 0x86, 0xfe, 0x41, + 0x04, 0xb3, 0x47, 0x5f, 0xfb, 0x3d, 0x1b, 0xfe, 0xfd, 0xea, 0x1d, 0x65, + 0x9d, 0x7f, 0x20, 0x82, 0x59, 0xaf, 0x87, 0x9d, 0xb0, 0xfa, 0x94, 0x46, + 0x07, 0x9e, 0x6c, 0xc2, 0xb6, 0xda, 0x0b, 0x2a, 0x88, 0xa1, 0xde, 0x72, + 0x19, 0x1f, 0x06, 0x15, 0xb9, 0x28, 0xe1, 0x48, 0x5d, 0x36, 0x19, 0x89, + 0x0d, 0xb9, 0x89, 0x57, 0x1b, 0x37, 0x65, 0x71, 0x3c, 0x36, 0x7f, 0x87, + 0x38, 0xc6, 0x43, 0xa9, 0x43, 0x7e, 0x95, 0x2b, 0xb7, 0x0d, 0x5f, 0xb0, + 0xe1, 0xbf, 0xb6, 0x90, 0x23, 0x13, 0x1d, 0x7a, 0x1c, 0x4e, 0xbe, 0xce, + 0xbf, 0x8e, 0xb2, 0xa3, 0x0f, 0xa3, 0xa5, 0xe2, 0x33, 0x7f, 0xff, 0xfb, + 0xae, 0x3e, 0xd4, 0x24, 0xb3, 0x68, 0x7d, 0x1d, 0x85, 0x01, 0x1b, 0x47, + 0x5f, 0x66, 0xbf, 0x43, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x16, 0xb5, 0xfe, + 0x5a, 0x2d, 0xe6, 0xce, 0x9d, 0x7f, 0x66, 0xd6, 0x9c, 0x5a, 0x75, 0xee, + 0x42, 0xce, 0xbf, 0xbb, 0x9a, 0x89, 0xf6, 0x8e, 0xbf, 0xe9, 0x31, 0x9c, + 0x6b, 0xbb, 0x4d, 0x14, 0x1d, 0x61, 0xfa, 0xb9, 0x85, 0xf6, 0x4d, 0x1e, + 0x3a, 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xfe, 0xf6, 0x92, + 0x77, 0xd3, 0x8b, 0xfb, 0xb1, 0x31, 0xd6, 0x61, 0x54, 0xab, 0x0e, 0x0d, + 0xe4, 0xf5, 0x84, 0x28, 0x67, 0x31, 0x97, 0x0b, 0x97, 0x09, 0x0e, 0x90, + 0x09, 0x0f, 0xd3, 0x9b, 0xff, 0xcc, 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, + 0x34, 0x51, 0x77, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xba, 0xaa, 0x1b, + 0xff, 0x29, 0x3e, 0x35, 0xf5, 0x23, 0x86, 0x5c, 0xaf, 0x0e, 0xd6, 0x94, + 0x7f, 0xce, 0x50, 0xea, 0x15, 0x3e, 0x57, 0xbf, 0x71, 0xae, 0xed, 0x34, + 0x44, 0x37, 0xbb, 0x81, 0x3a, 0xfb, 0x36, 0x27, 0x0e, 0xb3, 0x18, 0x7e, + 0x1b, 0x99, 0xab, 0x8d, 0xdb, 0x6c, 0xeb, 0xe8, 0xec, 0x2c, 0xeb, 0xe6, + 0xbb, 0xb4, 0xd1, 0x1b, 0x53, 0x4f, 0x37, 0x84, 0x16, 0x60, 0x28, 0x82, + 0xc6, 0x0b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x53, 0x77, 0xee, 0x35, + 0xdd, 0xa6, 0x8a, 0x82, 0xf6, 0x6e, 0xc9, 0xd6, 0x63, 0x0f, 0x43, 0xa6, + 0x77, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa9, 0xaf, 0xdc, 0x6b, 0xbb, + 0x4d, 0x15, 0x85, 0xf9, 0x19, 0x08, 0x38, 0x75, 0xcb, 0xd1, 0xd7, 0xf2, + 0x6d, 0xbc, 0x26, 0xd9, 0xd7, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x8f, + 0xea, 0x0f, 0xbe, 0x46, 0x17, 0xb2, 0x27, 0x3a, 0xff, 0x66, 0xf2, 0x79, + 0x20, 0x9d, 0x73, 0xf8, 0xeb, 0x31, 0x89, 0xb1, 0x34, 0xcd, 0x65, 0x0f, + 0x08, 0x51, 0x21, 0xf0, 0xde, 0xd9, 0x8d, 0xff, 0xe6, 0x16, 0xf2, 0x63, + 0x38, 0xd7, 0x76, 0x9a, 0x26, 0xfb, 0xff, 0x96, 0xf2, 0x63, 0x38, 0xd7, + 0x76, 0x9a, 0x27, 0xeb, 0xf9, 0xfb, 0x9e, 0x80, 0x9d, 0x70, 0xb4, 0xeb, + 0xed, 0x4c, 0xbd, 0x1d, 0x7f, 0x9b, 0xd4, 0xf6, 0x62, 0xce, 0xbb, 0x63, + 0x4f, 0x18, 0x15, 0x42, 0x23, 0x90, 0x57, 0x44, 0x7e, 0x31, 0xbf, 0xca, + 0xb9, 0x58, 0x1c, 0x9e, 0x37, 0x3a, 0xfc, 0xac, 0xaa, 0x36, 0xf3, 0x73, + 0xaf, 0xe5, 0x61, 0xe7, 0xea, 0x2b, 0x9d, 0x7e, 0x56, 0xd4, 0x53, 0x15, + 0xce, 0xbb, 0x63, 0x4f, 0x18, 0x0d, 0xba, 0x75, 0x2b, 0x29, 0x86, 0xab, + 0x07, 0xca, 0x83, 0x45, 0x5c, 0x6b, 0xe3, 0x10, 0x12, 0xdf, 0x2b, 0x7c, + 0x7c, 0x3a, 0xf9, 0x55, 0x3a, 0xf4, 0x75, 0xff, 0xfc, 0xad, 0x8b, 0xfa, + 0x05, 0xa8, 0xb0, 0x81, 0xf9, 0x23, 0xaf, 0xf9, 0xfa, 0x9b, 0x18, 0x65, + 0x96, 0x4a, 0xbf, 0xdd, 0x7f, 0x79, 0xdd, 0x93, 0xa9, 0x54, 0x8f, 0x45, + 0x5e, 0x4e, 0xad, 0x57, 0x55, 0x71, 0xf5, 0xff, 0xfe, 0x56, 0x55, 0x1a, + 0xe4, 0x27, 0xbb, 0x81, 0x4d, 0x60, 0xfe, 0x75, 0xfc, 0xaf, 0x1c, 0x77, + 0x91, 0xd7, 0xee, 0xa3, 0xfe, 0xab, 0x8e, 0xa5, 0x61, 0x18, 0x6a, 0xb3, + 0x47, 0x8b, 0xac, 0xe7, 0x5f, 0x95, 0x4a, 0xd3, 0xf5, 0x20, 0xeb, 0xff, + 0xe8, 0x88, 0x88, 0x88, 0x88, 0x8d, 0xf4, 0x75, 0xe4, 0xdf, 0x0e, 0xbf, + 0x71, 0x27, 0x75, 0x95, 0x73, 0x2c, 0x95, 0x58, 0x6f, 0xd9, 0x27, 0xb0, + 0x0a, 0x60, 0xd0, 0xd4, 0x23, 0x97, 0xf4, 0x9d, 0x3d, 0xdf, 0x9d, 0xc6, + 0x36, 0x8e, 0xbf, 0xfc, 0x83, 0x8b, 0x8d, 0x6b, 0x25, 0xb7, 0x87, 0x5f, + 0xfe, 0xec, 0x49, 0xf0, 0x29, 0xb3, 0x5f, 0xb4, 0xeb, 0xfd, 0xc0, 0x08, + 0x3c, 0x0f, 0x1d, 0x7b, 0xb0, 0x27, 0x5a, 0x10, 0xf3, 0x7c, 0x67, 0x50, + 0x8b, 0xee, 0xc2, 0x62, 0xf0, 0xa4, 0x1d, 0x7e, 0x8f, 0xab, 0xea, 0x1d, + 0x5c, 0x3c, 0x11, 0x19, 0xbf, 0xa5, 0xaf, 0x60, 0xa8, 0x75, 0xe6, 0x5d, + 0x93, 0xaf, 0xff, 0x7b, 0x8f, 0x38, 0x7b, 0x1a, 0xf0, 0x3a, 0x75, 0xd8, + 0xbe, 0x9f, 0x46, 0x87, 0x6f, 0xce, 0xde, 0xa7, 0x0e, 0xbf, 0xff, 0xfc, + 0x2e, 0xa2, 0x72, 0x25, 0xf3, 0xa8, 0xb0, 0xc7, 0xcd, 0xb0, 0x75, 0x38, + 0x75, 0xf3, 0xc9, 0x37, 0x3a, 0xff, 0xdd, 0x4f, 0x67, 0x38, 0x09, 0xf6, + 0x1d, 0x7f, 0xc9, 0xec, 0xe7, 0x01, 0x3e, 0xc3, 0xaf, 0x68, 0x03, 0xf0, + 0xff, 0x3a, 0x83, 0x41, 0x4e, 0x8b, 0x85, 0xbd, 0x26, 0x17, 0xdd, 0x42, + 0x76, 0xd0, 0x75, 0xff, 0xf4, 0x6f, 0x27, 0x1f, 0xfe, 0x7e, 0x9c, 0x45, + 0x0e, 0xad, 0xb3, 0xe2, 0xda, 0x0f, 0xbe, 0x9d, 0x69, 0x23, 0xaf, 0xa3, + 0xff, 0xab, 0x3a, 0xf8, 0x40, 0xf2, 0x3a, 0x9a, 0x78, 0x9a, 0x24, 0xbf, + 0xdd, 0x85, 0xb1, 0xff, 0xf0, 0x75, 0x42, 0x2f, 0x71, 0x99, 0x08, 0xaf, + 0xe9, 0x93, 0xbe, 0xc6, 0x9d, 0x5c, 0x3d, 0xa7, 0x2d, 0xbf, 0xed, 0xc3, + 0xf6, 0x15, 0xfa, 0x0d, 0x1d, 0x7f, 0xfe, 0x0f, 0x63, 0x89, 0xfc, 0x7d, + 0x89, 0x86, 0x16, 0x75, 0xfe, 0x52, 0x07, 0xda, 0x7e, 0x9d, 0x48, 0x88, + 0x87, 0x56, 0xa8, 0x47, 0x40, 0xc3, 0x1e, 0xff, 0x76, 0x27, 0xe4, 0x60, + 0x4e, 0xbf, 0xfe, 0x1c, 0xd8, 0xd7, 0xe4, 0xef, 0xe7, 0xdf, 0xf3, 0xaa, + 0x11, 0x08, 0xe6, 0x57, 0xf8, 0x5e, 0x7d, 0xe5, 0x1b, 0x47, 0x5f, 0xed, + 0x75, 0xfe, 0xf6, 0x24, 0x75, 0x4e, 0x7d, 0x5b, 0x9b, 0x5e, 0xcc, 0x98, + 0xeb, 0xfe, 0x89, 0x0b, 0xfa, 0x49, 0xb0, 0xeb, 0xdf, 0x63, 0xf3, 0xab, + 0xa7, 0xad, 0xa3, 0x8b, 0x2b, 0x9d, 0x7b, 0xd2, 0xc3, 0xae, 0xd6, 0x1d, + 0x7f, 0xf6, 0xa3, 0x8d, 0xf0, 0xe4, 0xee, 0x27, 0x56, 0x22, 0x9d, 0x08, + 0x9c, 0x4f, 0xf1, 0xbf, 0x0a, 0xdf, 0xc0, 0x98, 0x1e, 0x8e, 0x9d, 0x7f, + 0xf0, 0x63, 0xcf, 0xac, 0xef, 0x51, 0x67, 0x5f, 0xe9, 0xc3, 0x0f, 0xcf, + 0xc0, 0x75, 0xef, 0x24, 0xc7, 0x54, 0x22, 0x4b, 0x10, 0xb4, 0x69, 0x7e, + 0x85, 0x74, 0x65, 0xa7, 0x54, 0x32, 0xba, 0x27, 0x30, 0x91, 0x38, 0x63, + 0x07, 0xc6, 0x8d, 0xc8, 0x52, 0x51, 0xbc, 0xd0, 0xb1, 0xe4, 0x67, 0xeb, + 0x8c, 0x27, 0xb0, 0xaa, 0x78, 0x45, 0xfe, 0x48, 0x31, 0x8c, 0x69, 0x23, + 0xd0, 0xc0, 0xfa, 0x5d, 0x7f, 0xff, 0xca, 0xbd, 0x55, 0x18, 0xad, 0x78, + 0xaa, 0x55, 0xb6, 0x2b, 0xaa, 0xe0, 0x7c, 0xf9, 0xdd, 0xb3, 0xaf, 0x4d, + 0xf5, 0x67, 0x5f, 0xf6, 0x7b, 0x59, 0xee, 0xe7, 0xe7, 0x53, 0x9e, 0xb8, + 0x8f, 0xdc, 0xe2, 0x75, 0x70, 0xda, 0x2c, 0x82, 0xfa, 0x3d, 0x8b, 0x3a, + 0xfd, 0xe8, 0x14, 0xfc, 0xeb, 0xfb, 0x19, 0x7f, 0xd7, 0x87, 0x57, 0xc3, + 0xf3, 0xc2, 0x01, 0x26, 0xbf, 0x72, 0x78, 0xf6, 0x8e, 0xbe, 0x7e, 0x3c, + 0x8e, 0xb7, 0x30, 0xf2, 0x04, 0xa2, 0xf3, 0x2c, 0xb2, 0x75, 0xf4, 0xe2, + 0x90, 0x53, 0x05, 0xfd, 0xff, 0x2b, 0xf5, 0xc6, 0x41, 0x89, 0xce, 0xbb, + 0x79, 0x1d, 0x7f, 0x94, 0x8f, 0x6b, 0xae, 0x03, 0xaf, 0xc9, 0x3e, 0x6f, + 0xe3, 0xae, 0x46, 0x9d, 0x50, 0x88, 0x75, 0x05, 0xd6, 0x67, 0xe2, 0x8b, + 0xf2, 0x8f, 0xad, 0x92, 0x3a, 0xb7, 0x3e, 0x7f, 0x1e, 0xd2, 0xac, 0xaf, + 0xaa, 0x23, 0x1e, 0x0c, 0x25, 0x11, 0xdf, 0xa8, 0xae, 0x60, 0x08, 0xca, + 0x6f, 0xfe, 0xd8, 0xce, 0x68, 0x52, 0x39, 0x93, 0x9d, 0x7f, 0xff, 0xff, + 0xe5, 0x7f, 0x9d, 0xcd, 0xe5, 0xd5, 0xfc, 0x6f, 0x41, 0xef, 0x60, 0xf7, + 0x3d, 0x01, 0xf9, 0xf3, 0xbb, 0x67, 0x5f, 0xf0, 0x70, 0x0a, 0x94, 0xeb, + 0xac, 0xeb, 0xf4, 0x2c, 0x72, 0x63, 0xb0, 0xdd, 0xde, 0xd9, 0x81, 0x3a, + 0xff, 0x29, 0xd4, 0x81, 0x04, 0x1d, 0x5d, 0x3c, 0xe7, 0x1d, 0xa0, 0xa2, + 0x93, 0x50, 0x83, 0xbf, 0xa2, 0x5d, 0x8d, 0x88, 0x75, 0xf9, 0xf8, 0x07, + 0xd1, 0xd7, 0x4b, 0xc7, 0x5f, 0x4d, 0x1e, 0x73, 0xaf, 0x81, 0xfe, 0x0b, + 0x4d, 0xb8, 0x05, 0xad, 0x23, 0xaa, 0x73, 0xc8, 0xe9, 0xc5, 0xff, 0xd1, + 0xdf, 0xa1, 0xf2, 0x64, 0xd0, 0xb3, 0xaf, 0xa3, 0xc0, 0x59, 0xd4, 0x68, + 0x83, 0xaf, 0xe7, 0x9f, 0xf7, 0x10, 0x92, 0xb0, 0x6d, 0xb4, 0xd3, 0xd2, + 0xdb, 0x17, 0xa5, 0xa2, 0x7b, 0xce, 0x77, 0xff, 0xe5, 0xe9, 0xe5, 0xd4, + 0xcf, 0x6b, 0x98, 0x1c, 0x3a, 0xff, 0xa3, 0xc3, 0x9b, 0x07, 0x34, 0x75, + 0x42, 0x2b, 0x70, 0x8f, 0x4a, 0x77, 0xf3, 0xf6, 0x15, 0xc1, 0x23, 0xaa, + 0x4a, 0xb8, 0x9a, 0x5b, 0xc8, 0x52, 0xac, 0x8f, 0xd1, 0xc8, 0x6c, 0x2e, + 0xbf, 0xa4, 0x39, 0xbf, 0xb0, 0xeb, 0xff, 0xf7, 0xdf, 0xff, 0x8d, 0xf2, + 0x70, 0xbb, 0xb5, 0xc2, 0x75, 0x42, 0x21, 0x78, 0x59, 0x7f, 0x9c, 0x7d, + 0x2c, 0xe6, 0x1d, 0x7f, 0x0a, 0x7f, 0xae, 0xa1, 0xd7, 0x70, 0x27, 0x5c, + 0xcb, 0x27, 0x54, 0x8d, 0x73, 0x22, 0xd7, 0xa1, 0x36, 0x14, 0xc1, 0xa2, + 0xa7, 0x45, 0x4e, 0x9f, 0x2e, 0xff, 0x47, 0x5f, 0xc9, 0xd4, 0x51, 0x48, + 0x3a, 0xed, 0x7d, 0x09, 0xe2, 0x78, 0x5e, 0x91, 0x12, 0xdf, 0x59, 0xaf, + 0x32, 0xcb, 0x25, 0x51, 0x4c, 0x17, 0xf7, 0xc8, 0xca, 0x4c, 0x55, 0x34, + 0xde, 0x20, 0xd5, 0xfb, 0x39, 0x1b, 0x30, 0xea, 0x86, 0x40, 0xd4, 0xe8, + 0xb9, 0x1c, 0x4a, 0x4b, 0x0a, 0xe4, 0x3a, 0xd6, 0x45, 0xd8, 0xdb, 0xc5, + 0xff, 0x44, 0x17, 0xdc, 0x90, 0x30, 0xeb, 0xfc, 0x3b, 0xfb, 0xef, 0x5f, + 0xf3, 0xaf, 0x0a, 0x68, 0xeb, 0xe0, 0xb8, 0xfe, 0x75, 0xff, 0xd0, 0x3f, + 0x8c, 0x6f, 0x34, 0x0f, 0xe7, 0x56, 0x22, 0xd5, 0x0d, 0xbf, 0x1a, 0xd1, + 0x0d, 0x90, 0xeb, 0xfe, 0x75, 0x1b, 0xd4, 0x0b, 0xc8, 0xeb, 0xe9, 0xe7, + 0x7d, 0xce, 0xbb, 0xfd, 0x21, 0xf5, 0x88, 0x7f, 0xd3, 0x8b, 0xf4, 0x67, + 0x3a, 0x87, 0x5f, 0xfe, 0x67, 0xfe, 0xe6, 0x4e, 0x99, 0xb2, 0x37, 0x3a, + 0xff, 0xf7, 0xf0, 0xbe, 0x72, 0x27, 0xf3, 0xba, 0x87, 0x5f, 0xe9, 0x67, + 0x71, 0x70, 0xd3, 0xaf, 0x62, 0xd5, 0xce, 0xbf, 0xd9, 0xa1, 0xcf, 0x75, + 0x0e, 0xa0, 0x9e, 0x70, 0x8f, 0x56, 0x27, 0x33, 0x31, 0xe7, 0x49, 0x7f, + 0x4d, 0xf2, 0x5e, 0xc7, 0xfb, 0xfb, 0xd9, 0x30, 0xc2, 0xcf, 0x10, 0x15, + 0xf9, 0xc4, 0x3d, 0x83, 0x44, 0x04, 0xc1, 0xb9, 0xbf, 0xf9, 0x37, 0xd0, + 0x70, 0x60, 0x41, 0x07, 0x5f, 0xfc, 0x06, 0xa9, 0xcc, 0xdf, 0x5f, 0xbf, + 0x8e, 0xbf, 0x44, 0x9f, 0x76, 0x4e, 0xac, 0x45, 0x82, 0x20, 0xf1, 0x1e, + 0xd3, 0x9d, 0x7e, 0xf9, 0x93, 0x22, 0xce, 0xbf, 0xfc, 0x08, 0xf9, 0xb5, + 0xe4, 0xd7, 0x77, 0x76, 0x4e, 0xa9, 0xcf, 0xe7, 0x45, 0x37, 0xfe, 0xc0, + 0xf5, 0xd8, 0x8e, 0xc6, 0xe7, 0x52, 0xa1, 0x1d, 0x7c, 0x84, 0x52, 0xc8, + 0xef, 0xfc, 0x82, 0xa7, 0x05, 0x1a, 0x01, 0x3a, 0xff, 0xfc, 0xfb, 0xef, + 0xa8, 0x1f, 0x7d, 0x9b, 0xa9, 0xed, 0x1d, 0x50, 0x8c, 0xec, 0x39, 0x01, + 0xe5, 0xf2, 0xe3, 0x16, 0x75, 0xff, 0xb1, 0x70, 0xd4, 0xf7, 0x00, 0xb3, + 0xaf, 0x26, 0xfa, 0x3a, 0xd1, 0x23, 0xd9, 0xfc, 0xf6, 0xff, 0x72, 0x6d, + 0x20, 0xf9, 0x0e, 0xbf, 0xdd, 0x4d, 0xff, 0xe3, 0x84, 0xeb, 0xed, 0xff, + 0xe4, 0x15, 0x73, 0x2c, 0x95, 0x50, 0x6e, 0xd9, 0x23, 0xb8, 0x50, 0xa6, + 0x0d, 0x0d, 0xe7, 0xe4, 0xbe, 0x22, 0xd6, 0x50, 0x90, 0xa5, 0x6d, 0x90, + 0xeb, 0x10, 0xd6, 0xc9, 0x48, 0x09, 0x09, 0x4e, 0x43, 0xcf, 0xb1, 0xf3, + 0xb9, 0x70, 0xbc, 0xf8, 0xa0, 0x10, 0xe7, 0xbd, 0x3b, 0xac, 0xeb, 0xde, + 0x46, 0x4f, 0x18, 0x45, 0xf7, 0x80, 0xff, 0x4d, 0x10, 0x3e, 0xe6, 0xa6, + 0x9d, 0x10, 0xc0, 0x45, 0xbc, 0xae, 0x9f, 0x9d, 0x74, 0x00, 0xeb, 0xf0, + 0x07, 0xff, 0xb2, 0x3a, 0xff, 0xf8, 0x73, 0x5f, 0x3e, 0xf6, 0x3f, 0x5b, + 0xcb, 0xe6, 0x1b, 0xfd, 0x0a, 0xd0, 0x11, 0x93, 0xb1, 0x7a, 0xff, 0xdd, + 0x04, 0xf1, 0xf2, 0x3d, 0x01, 0x3a, 0xf3, 0xf2, 0x73, 0xae, 0x65, 0x93, + 0xaf, 0xf7, 0x13, 0x36, 0x7d, 0x93, 0x0d, 0x36, 0x8c, 0x8e, 0x5f, 0xf9, + 0x14, 0xf9, 0xa0, 0x7e, 0xb8, 0x91, 0xd7, 0xfb, 0x59, 0xe7, 0x5e, 0x09, + 0xd4, 0x14, 0xcd, 0x78, 0xe9, 0xd4, 0xff, 0x21, 0x5f, 0xfc, 0x38, 0xa7, + 0x5e, 0x5f, 0x5f, 0x78, 0x3a, 0xa1, 0x10, 0x78, 0x7d, 0x7f, 0xf2, 0xd6, + 0xf2, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x62, 0xff, 0xff, 0xf3, 0xeb, 0x07, + 0x1b, 0xd8, 0xde, 0x5b, 0x79, 0xd6, 0xa6, 0x0b, 0xa8, 0x75, 0x62, 0x31, + 0x80, 0x9f, 0x48, 0xab, 0x9b, 0xb1, 0xee, 0x8c, 0x39, 0xef, 0xf2, 0xfa, + 0xf3, 0x8c, 0x48, 0xab, 0xb4, 0x03, 0xaf, 0xe9, 0x75, 0xdc, 0x60, 0xeb, + 0x43, 0x4f, 0x03, 0x71, 0x6b, 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x15, 0x7b, + 0xb0, 0xb3, 0xaf, 0xfd, 0x13, 0xbf, 0xb9, 0x92, 0xdb, 0xc3, 0xab, 0x11, + 0x1c, 0x86, 0x62, 0x37, 0x7e, 0xec, 0x2c, 0x1b, 0x9d, 0x7d, 0xed, 0x47, + 0xe5, 0x5e, 0x7e, 0x4e, 0x55, 0xf0, 0x05, 0xd4, 0x2a, 0xff, 0x24, 0xf9, + 0xed, 0x47, 0xe5, 0x51, 0x57, 0xf6, 0x36, 0x3b, 0x0b, 0x2a, 0xe6, 0x59, + 0x2a, 0xfe, 0x18, 0x19, 0xd3, 0x85, 0x56, 0x26, 0x14, 0xd2, 0x25, 0x8e, + 0x74, 0x87, 0xf3, 0x31, 0x0a, 0x64, 0xaf, 0xe8, 0xc5, 0xc9, 0xc2, 0x98, + 0x3f, 0x4a, 0x92, 0x7f, 0x53, 0x16, 0xf6, 0x3a, 0x6a, 0x85, 0x6b, 0x5d, + 0x72, 0x79, 0x56, 0x17, 0xf6, 0x0e, 0x90, 0x70, 0xeb, 0xdd, 0x02, 0xce, + 0xae, 0x9e, 0x2e, 0xd1, 0x4d, 0xfe, 0x71, 0xcd, 0x72, 0x34, 0x75, 0xfc, + 0x1c, 0x17, 0xf6, 0x8e, 0xb4, 0x48, 0xf6, 0xf4, 0x61, 0x7e, 0xe6, 0xf2, + 0xcf, 0x1d, 0x7f, 0xff, 0xdd, 0x4e, 0x60, 0x5d, 0x78, 0x3e, 0x18, 0x67, + 0x3d, 0xa3, 0xad, 0x07, 0x5f, 0xbb, 0x1b, 0x03, 0x0d, 0x3f, 0x2f, 0xd8, + 0xeb, 0x88, 0xdb, 0xf4, 0x26, 0xaf, 0xf6, 0xf2, 0xdb, 0x86, 0xe2, 0xce, + 0xbf, 0xff, 0xf7, 0x39, 0x1b, 0xcb, 0x7d, 0x27, 0x1b, 0xdc, 0xfb, 0xc4, + 0x80, 0x9d, 0x50, 0x8a, 0x5c, 0x36, 0xbf, 0xff, 0x35, 0x47, 0xd6, 0x72, + 0x49, 0xd7, 0x1d, 0xe4, 0x75, 0xff, 0x9b, 0x1e, 0xd6, 0x79, 0x37, 0x64, + 0xeb, 0x3e, 0x22, 0x51, 0x45, 0x5a, 0x84, 0xea, 0xbb, 0x0c, 0xd1, 0x85, + 0xad, 0xef, 0x3f, 0xe7, 0x5f, 0xff, 0x9d, 0xe4, 0xfd, 0xf9, 0x93, 0x83, + 0xc0, 0x7f, 0xa6, 0x8b, 0xee, 0xf7, 0xf0, 0x13, 0xaf, 0xfd, 0xa4, 0x1d, + 0xe5, 0xc0, 0x46, 0x8e, 0xa9, 0x91, 0x7f, 0xc6, 0x5f, 0x0e, 0x5f, 0xe8, + 0x9f, 0xb9, 0x34, 0x2b, 0x9d, 0x66, 0x9d, 0x7f, 0xff, 0xbf, 0x4e, 0x29, + 0xd8, 0x5c, 0xd2, 0x41, 0xec, 0x72, 0x0e, 0xb7, 0xb0, 0xfc, 0x74, 0x21, + 0x7d, 0xe1, 0xc9, 0x1d, 0x50, 0x78, 0xe8, 0x4f, 0x7f, 0xe1, 0x49, 0x7b, + 0xb9, 0xc4, 0xd1, 0xd7, 0xf4, 0x48, 0x73, 0x27, 0x3a, 0xff, 0x38, 0x63, + 0xf8, 0x67, 0x47, 0x57, 0x4f, 0x79, 0xca, 0xef, 0xed, 0xb5, 0x6b, 0xf3, + 0xe7, 0x76, 0xcf, 0x10, 0x0d, 0xfe, 0xf7, 0xff, 0x46, 0x5d, 0xc3, 0xc4, + 0x03, 0x79, 0xf9, 0x23, 0xc4, 0x03, 0x58, 0x7d, 0x40, 0x42, 0xb9, 0xe4, + 0x78, 0x80, 0x6f, 0x9c, 0x77, 0x91, 0xe2, 0x01, 0xbf, 0xc8, 0xde, 0xe7, + 0xff, 0xc1, 0xe2, 0x01, 0xbc, 0x82, 0x13, 0xc4, 0x03, 0x41, 0x45, 0xba, + 0xc8, 0xba, 0x5d, 0xb1, 0x02, 0xca, 0x1e, 0x20, 0x1b, 0xdc, 0x8f, 0x1e, + 0x20, 0x1a, 0x3c, 0x40, 0x37, 0xb6, 0xd3, 0xf3, 0xc4, 0x03, 0x74, 0x2c, + 0xf1, 0x00, 0xd0, 0x4f, 0x97, 0x05, 0xd0, 0xb2, 0xf9, 0x16, 0x18, 0x3c, + 0x40, 0x37, 0xbc, 0xed, 0x3c, 0x40, 0x37, 0xfe, 0x17, 0x93, 0x1d, 0x46, + 0xbf, 0x0f, 0x10, 0x0d, 0xff, 0xcf, 0xe0, 0x4e, 0x83, 0xee, 0xbc, 0x8f, + 0x10, 0x0d, 0xce, 0x13, 0xc4, 0x03, 0x7f, 0x85, 0xd9, 0xd6, 0xa3, 0xf3, + 0xc4, 0x03, 0x7e, 0x45, 0x1c, 0x7f, 0x3c, 0x40, 0x37, 0x26, 0x8f, 0x10, + 0x0d, 0x70, 0xf5, 0xbc, 0x69, 0x7f, 0xfb, 0xa9, 0xef, 0x66, 0xbe, 0x71, + 0x21, 0x67, 0x88, 0x06, 0xfd, 0xe1, 0x8d, 0xe4, 0x68, 0x80, 0x6e, 0xfe, + 0x0f, 0x10, 0x0b, 0x06, 0xd2, 0xfc, 0x90, 0xb7, 0x09, 0xe2, 0x01, 0xbe, + 0x03, 0x8b, 0x4f, 0x10, 0x0d, 0xe8, 0xe3, 0x4f, 0x10, 0x0d, 0xff, 0xb3, + 0x7d, 0x06, 0x30, 0x7f, 0xd1, 0xe2, 0x01, 0xbf, 0x01, 0xe5, 0x28, 0x3c, + 0x40, 0x37, 0xe7, 0x6f, 0x63, 0x73, 0xc4, 0x03, 0x58, 0x8b, 0x2e, 0xa5, + 0x80, 0xce, 0xee, 0x7e, 0x78, 0x80, 0x6a, 0x4a, 0xc9, 0x42, 0x45, 0x90, + 0x96, 0x69, 0x12, 0x42, 0x2f, 0xa6, 0x9f, 0x99, 0x68, 0xb7, 0xd0, 0xda, + 0x01, 0x7d, 0xfb, 0x3d, 0xa7, 0xdc, 0xf1, 0x00, 0xdf, 0xe0, 0xc3, 0x66, + 0xe4, 0x78, 0xf1, 0x00, 0x84, 0xda, 0x5e, 0xe4, 0x32, 0x78, 0x80, 0x69, + 0xa7, 0xf3, 0xc5, 0x0b, 0xfc, 0x07, 0x94, 0xa3, 0xea, 0xcf, 0x10, 0x0d, + 0xf2, 0x0c, 0xb4, 0x78, 0x80, 0x6f, 0xe7, 0x9a, 0x59, 0xbc, 0x8f, 0x10, + 0x0d, 0x62, 0x32, 0xfa, 0x45, 0xfa, 0x08, 0x0b, 0x6f, 0xfb, 0xb1, 0xa6, + 0x34, 0x0e, 0x7e, 0x78, 0x80, 0x6c, 0x87, 0x88, 0x06, 0xe7, 0x9c, 0x27, + 0xc9, 0xd4, 0x8b, 0xb9, 0xf9, 0xe2, 0x01, 0xbf, 0x3f, 0xb4, 0x9b, 0x9e, + 0x20, 0x1b, 0xf9, 0x04, 0x12, 0xcd, 0x1e, 0x20, 0x1a, 0x84, 0x48, 0x09, + 0x27, 0x8d, 0x2a, 0x19, 0x4b, 0x01, 0x85, 0xae, 0x43, 0x61, 0x0f, 0xe6, + 0x1e, 0xe4, 0x23, 0x7a, 0x5a, 0xe5, 0xbf, 0x94, 0x0a, 0x56, 0xa5, 0xba, + 0xfa, 0x50, 0x9e, 0xdc, 0x28, 0x7e, 0xc2, 0xfa, 0xf7, 0x91, 0x93, 0xc6, + 0x13, 0x79, 0xdd, 0xa6, 0x88, 0x05, 0x84, 0xc5, 0x77, 0x87, 0x65, 0xf2, + 0x8a, 0xd0, 0x2b, 0x3a, 0xed, 0x93, 0x9d, 0x7e, 0xd8, 0x30, 0x1e, 0x9d, + 0x50, 0x78, 0x28, 0x33, 0x7f, 0xf4, 0x87, 0x1b, 0xd4, 0xff, 0xf0, 0x4c, + 0x75, 0xdf, 0xc1, 0x56, 0x50, 0xab, 0xdd, 0x89, 0xce, 0xb9, 0x96, 0x4a, + 0xa4, 0x3d, 0xb5, 0x71, 0x69, 0x84, 0x59, 0x1c, 0xbc, 0xb4, 0xd1, 0x4c, + 0x1e, 0x05, 0xe4, 0x07, 0x8e, 0xbf, 0xfd, 0xed, 0x62, 0x89, 0xcf, 0xbf, + 0xff, 0x1b, 0x9d, 0x53, 0xb3, 0xa6, 0x24, 0x40, 0x18, 0x4d, 0x36, 0x97, + 0x1c, 0x89, 0xdc, 0x6a, 0x72, 0x0f, 0xe1, 0xc3, 0xe2, 0xdf, 0xa3, 0x77, + 0xff, 0x87, 0xdb, 0x79, 0x34, 0x9f, 0x93, 0x86, 0x0e, 0xbf, 0xbd, 0xf7, + 0x66, 0xc8, 0xd1, 0xd7, 0xfb, 0x37, 0xf7, 0x9e, 0x5a, 0x3a, 0xf0, 0xef, + 0x23, 0xc6, 0x01, 0x58, 0x8d, 0xc4, 0x4d, 0xe1, 0x9b, 0x99, 0xdf, 0xa6, + 0x94, 0x72, 0x73, 0xaf, 0xa1, 0x48, 0x59, 0xd5, 0xc3, 0xca, 0x59, 0x4d, + 0xff, 0xa5, 0xaf, 0x83, 0x8b, 0x8e, 0x28, 0x75, 0xfd, 0x28, 0xe7, 0xff, + 0x56, 0x75, 0xff, 0xdb, 0x07, 0x35, 0xec, 0x19, 0x66, 0x8e, 0xbe, 0x5c, + 0x03, 0xc7, 0x56, 0x1f, 0x23, 0xa1, 0xdd, 0xd7, 0xc4, 0x5a, 0x0c, 0x25, + 0x2f, 0xfa, 0x1b, 0x0b, 0x45, 0xfe, 0x87, 0x57, 0x0f, 0xa3, 0x68, 0xc6, + 0xfe, 0xfa, 0xcf, 0x13, 0x3a, 0x55, 0xff, 0xdf, 0x8a, 0x66, 0xfe, 0x9a, + 0x4f, 0xc3, 0xaf, 0xa6, 0xeb, 0xcc, 0x75, 0xf3, 0x5f, 0x93, 0x9d, 0x7e, + 0xc9, 0xa5, 0x1b, 0x9d, 0x7b, 0xa9, 0x31, 0xd7, 0x86, 0x24, 0x55, 0xff, + 0x87, 0xf4, 0xda, 0xda, 0x04, 0xa1, 0x5c, 0xea, 0xc3, 0xe1, 0x71, 0xaa, + 0xdd, 0x34, 0xfe, 0x22, 0xf4, 0x8c, 0x48, 0xbc, 0x51, 0xb4, 0xfb, 0x50, + 0xad, 0xf3, 0x08, 0x92, 0x35, 0xce, 0x92, 0xbc, 0x6f, 0xd7, 0xf6, 0xfa, + 0xe7, 0x23, 0xc7, 0x5f, 0xd2, 0xd2, 0x9c, 0x76, 0x9d, 0x78, 0x7d, 0xa3, + 0xaf, 0xda, 0x00, 0x81, 0xa7, 0x54, 0x1f, 0x82, 0x17, 0x00, 0x6e, 0xff, + 0xee, 0xb3, 0x1c, 0xd6, 0x32, 0xfc, 0x50, 0xeb, 0xf6, 0x04, 0x38, 0xb3, + 0xaf, 0xff, 0x7b, 0x76, 0xa7, 0x76, 0xe3, 0xdd, 0xfb, 0xa3, 0xae, 0x54, + 0xe8, 0xeb, 0xe1, 0x4d, 0xe4, 0x75, 0xff, 0x26, 0xfd, 0xc0, 0xf1, 0xda, + 0x75, 0x41, 0xec, 0xf0, 0x86, 0xff, 0xbb, 0x1c, 0x86, 0xa0, 0xb4, 0xeb, + 0xef, 0x28, 0xfa, 0xe1, 0xeb, 0xed, 0x10, 0xd4, 0x93, 0xc3, 0xe2, 0x32, + 0xc9, 0x80, 0xa0, 0xcc, 0x32, 0xaf, 0xdb, 0x40, 0x5e, 0x04, 0xeb, 0xff, + 0x77, 0x36, 0x9c, 0x54, 0xcd, 0xfc, 0x75, 0xff, 0x63, 0x7a, 0x81, 0xe8, + 0x14, 0x3a, 0xf7, 0xb1, 0xa7, 0x52, 0xcf, 0x53, 0x47, 0x37, 0xa4, 0xbf, + 0xce, 0xa5, 0x11, 0xa9, 0xfc, 0x25, 0x7c, 0x45, 0x7f, 0xca, 0x3f, 0xc8, + 0x58, 0xa2, 0x87, 0x5f, 0xf9, 0xf4, 0xb8, 0x4e, 0x71, 0x19, 0x3a, 0xda, + 0x50, 0xfd, 0xfa, 0x75, 0x7f, 0xd9, 0xef, 0x22, 0x9e, 0xc6, 0x9d, 0x7f, + 0x83, 0x1b, 0xeb, 0x37, 0xf1, 0xd7, 0xfd, 0x1e, 0x46, 0xa0, 0x63, 0xc7, + 0x5b, 0x41, 0x45, 0x16, 0x1c, 0x70, 0xd2, 0xb7, 0x4c, 0x03, 0xd0, 0xcb, + 0xbf, 0xef, 0x24, 0xf1, 0xbf, 0xfc, 0x83, 0xaf, 0x6b, 0xd8, 0x75, 0xd9, + 0xaf, 0x87, 0xab, 0xf4, 0xea, 0xff, 0xec, 0xf2, 0x6f, 0x21, 0x85, 0x52, + 0xaf, 0xdb, 0x3a, 0xfd, 0x9e, 0xfd, 0xfc, 0x75, 0x48, 0xfd, 0xf6, 0xd4, + 0x2f, 0xff, 0xd1, 0xd7, 0xc1, 0x8e, 0x28, 0x10, 0x3f, 0x24, 0x75, 0x49, + 0x32, 0x0f, 0x42, 0xa3, 0x68, 0x96, 0xa1, 0x73, 0x57, 0x14, 0x52, 0x1f, + 0xcf, 0x1d, 0x70, 0x23, 0x9f, 0xbe, 0xea, 0x3c, 0x8e, 0xbf, 0xd8, 0x32, + 0xcd, 0x7d, 0x59, 0xd7, 0xe5, 0xeb, 0xf7, 0x73, 0xab, 0xc7, 0xb5, 0xf4, + 0xce, 0xff, 0xb9, 0x83, 0xf3, 0xb9, 0xbb, 0x27, 0x5f, 0xf4, 0x84, 0x1f, + 0xfc, 0x6a, 0xff, 0x3a, 0xa7, 0x4c, 0x5a, 0x4f, 0x58, 0x49, 0xb9, 0xdd, + 0xff, 0x0c, 0x66, 0xfe, 0xce, 0x41, 0xd5, 0x07, 0xea, 0xe7, 0xf7, 0xe7, + 0xd8, 0x10, 0xc1, 0xd7, 0x6b, 0x47, 0x5e, 0x65, 0x96, 0x4e, 0xbb, 0xf7, + 0x29, 0x82, 0xfe, 0xb8, 0x7b, 0x7a, 0x35, 0xbf, 0xf6, 0x68, 0x5d, 0x49, + 0x85, 0x26, 0x3a, 0xfe, 0xfe, 0x25, 0xdf, 0xba, 0x3a, 0xf3, 0xff, 0x85, + 0x54, 0x93, 0x2e, 0x5c, 0x20, 0xfa, 0x45, 0xf9, 0xf6, 0xd9, 0x85, 0xf4, + 0x05, 0x02, 0x75, 0xf8, 0x3c, 0x40, 0x4e, 0x75, 0xfe, 0x67, 0x07, 0x36, + 0x27, 0x0e, 0xbf, 0x87, 0x37, 0xff, 0xec, 0x8e, 0xa9, 0x91, 0x16, 0x25, + 0x1e, 0x33, 0xb9, 0xd6, 0x75, 0xfe, 0xcd, 0x98, 0xc3, 0x2c, 0xb2, 0x55, + 0xfa, 0x68, 0xce, 0xe8, 0xea, 0x13, 0xdf, 0xfa, 0x71, 0x7f, 0x95, 0x30, + 0x06, 0xf5, 0x38, 0x75, 0xe5, 0xbf, 0x8e, 0xa9, 0x91, 0xd1, 0xd7, 0x40, + 0x11, 0xec, 0x36, 0xbf, 0x87, 0x63, 0xad, 0x16, 0x75, 0xfb, 0x26, 0x94, + 0x48, 0xeb, 0xfa, 0x70, 0xc6, 0x08, 0x4e, 0xa8, 0x55, 0xaf, 0x25, 0x44, + 0x85, 0x5b, 0xc6, 0x31, 0xa4, 0x0f, 0x16, 0xfd, 0x27, 0xbc, 0xff, 0xa1, + 0xd7, 0xfc, 0x11, 0x06, 0xb2, 0x7c, 0x9c, 0xeb, 0xd1, 0xc1, 0x3a, 0xff, + 0x60, 0x45, 0xf4, 0x81, 0x3a, 0xdd, 0x3a, 0xf0, 0x1e, 0x71, 0x3c, 0x0d, + 0x18, 0x59, 0x38, 0x88, 0xdf, 0x2d, 0x52, 0xd3, 0x09, 0x71, 0xb5, 0x4c, + 0x31, 0xaf, 0xff, 0x60, 0x5d, 0x79, 0xbc, 0xb3, 0xfc, 0x09, 0xd7, 0x75, + 0xce, 0xba, 0x6d, 0x1d, 0x7e, 0xcd, 0x88, 0x21, 0xc3, 0x59, 0xf4, 0x56, + 0xfd, 0xdc, 0xdf, 0xd0, 0x75, 0xfb, 0x69, 0xe7, 0xfb, 0x23, 0xab, 0xe2, + 0x61, 0x0c, 0x3a, 0xe1, 0xf8, 0x09, 0xef, 0x83, 0x9d, 0x73, 0xaf, 0xfe, + 0x8c, 0x19, 0x77, 0x04, 0x61, 0x93, 0xab, 0x88, 0xa0, 0x14, 0x0f, 0x10, + 0x5f, 0xee, 0x6b, 0xb8, 0x29, 0xa3, 0xa9, 0x0f, 0x81, 0xcb, 0xef, 0xfb, + 0x03, 0x83, 0x02, 0x08, 0x3a, 0xe8, 0x64, 0xea, 0x9d, 0xd9, 0x9f, 0x4a, + 0x5e, 0x88, 0x65, 0xca, 0xe3, 0xe2, 0x90, 0x80, 0x6c, 0xaa, 0xcd, 0xce, + 0x52, 0x1b, 0x73, 0x18, 0xf2, 0x9f, 0x0c, 0xb8, 0xe0, 0x3b, 0x38, 0x00, + 0xea, 0x9f, 0xc2, 0x78, 0x67, 0xb1, 0x75, 0x1f, 0x2f, 0xa7, 0x09, 0x41, + 0x1b, 0xce, 0xc9, 0x48, 0x3f, 0x48, 0x36, 0x8d, 0x2f, 0xfb, 0x38, 0x31, + 0xe9, 0x67, 0x4e, 0xbf, 0x87, 0xfc, 0x0b, 0xc8, 0xeb, 0xff, 0xf0, 0x3d, + 0xa6, 0xf5, 0x06, 0x37, 0xd2, 0x2e, 0x0e, 0xbf, 0xcd, 0x1c, 0x94, 0x9f, + 0x47, 0x5f, 0xce, 0xce, 0x7f, 0xf7, 0xc7, 0x5f, 0x9e, 0x5f, 0x02, 0x87, + 0x5e, 0x94, 0x7e, 0x75, 0xfb, 0xec, 0xd2, 0x85, 0x72, 0xaa, 0x13, 0x88, + 0xc3, 0x65, 0x0b, 0x11, 0x53, 0x86, 0x3d, 0x30, 0xf1, 0x47, 0xd1, 0xcb, + 0x34, 0xeb, 0xff, 0x94, 0x10, 0x3f, 0xdc, 0xd2, 0x40, 0x9d, 0x7b, 0x6d, + 0x02, 0x75, 0x70, 0xf8, 0x56, 0x87, 0x7f, 0xf6, 0xfe, 0x02, 0xfb, 0x08, + 0x2e, 0x13, 0xaf, 0x94, 0xe3, 0xb2, 0x75, 0xbe, 0x9a, 0x20, 0x5b, 0x78, + 0xd4, 0x0a, 0x57, 0x8d, 0xe3, 0x23, 0xf5, 0x88, 0x81, 0x45, 0xfb, 0xff, + 0x26, 0xdf, 0x53, 0xeb, 0x1f, 0xff, 0x05, 0x5f, 0xf0, 0xfb, 0x40, 0xdf, + 0xc8, 0xc9, 0xd7, 0xf8, 0x0f, 0xac, 0xc1, 0x50, 0xea, 0x83, 0xeb, 0xe9, + 0xd5, 0xff, 0xe4, 0x53, 0xe0, 0xba, 0x9f, 0x35, 0xff, 0xf0, 0x75, 0xfe, + 0x7e, 0xef, 0xa8, 0x1f, 0x1d, 0x5a, 0x44, 0x17, 0x94, 0x2f, 0xf9, 0xbd, + 0x49, 0xa5, 0x03, 0x23, 0xaf, 0xa5, 0xdc, 0x9c, 0xeb, 0xfe, 0x8d, 0xd6, + 0xfe, 0xcd, 0xfc, 0x75, 0x6e, 0x7b, 0x62, 0x45, 0x7f, 0xd0, 0xdf, 0x03, + 0xbc, 0x86, 0x4e, 0xbb, 0x8e, 0x75, 0xff, 0xfd, 0x1c, 0xff, 0x36, 0x26, + 0xb5, 0x82, 0xd7, 0x1f, 0xce, 0xae, 0x1f, 0x87, 0x45, 0x6f, 0xfc, 0xfb, + 0xeb, 0x3c, 0x8b, 0x79, 0x1d, 0x6f, 0x1d, 0x5f, 0x9e, 0x6f, 0xd3, 0xdb, + 0xff, 0xff, 0x81, 0xae, 0xbc, 0xb5, 0x24, 0xf7, 0xde, 0x47, 0x63, 0xda, + 0x7d, 0xce, 0xbf, 0x46, 0x0f, 0xb6, 0xce, 0xbf, 0x93, 0x7f, 0xf8, 0xe1, + 0x3a, 0xcb, 0x3a, 0x96, 0x7c, 0xdd, 0x28, 0x12, 0xeb, 0xd2, 0x00, 0x4e, + 0xb9, 0xf7, 0xf8, 0x79, 0x4e, 0x5d, 0x5c, 0x4d, 0x4f, 0x51, 0x92, 0x5f, + 0xff, 0xd8, 0x33, 0xeb, 0x51, 0xfe, 0x75, 0x38, 0xec, 0xf8, 0xea, 0x0a, + 0xe4, 0x86, 0xf0, 0xa3, 0x98, 0x8f, 0x90, 0x93, 0x59, 0x17, 0x61, 0x53, + 0xfb, 0x7f, 0xa3, 0x78, 0x64, 0xaa, 0xa1, 0x77, 0x69, 0x27, 0x50, 0x2f, + 0xff, 0xfb, 0x93, 0xe2, 0x4c, 0xef, 0x2d, 0x42, 0xc3, 0xd8, 0x16, 0x9d, + 0x7c, 0x1e, 0x82, 0x73, 0xaf, 0xf0, 0x5e, 0x59, 0x38, 0x04, 0xeb, 0x4f, + 0x07, 0xab, 0x84, 0x77, 0x2a, 0x70, 0xea, 0xc3, 0xc0, 0x72, 0x7b, 0xfb, + 0xdb, 0x60, 0xee, 0x34, 0xeb, 0xfd, 0xc8, 0xf2, 0x7f, 0x12, 0x3a, 0xf4, + 0xe3, 0x23, 0xa9, 0x50, 0xc9, 0x16, 0x87, 0x14, 0x22, 0x5c, 0x31, 0x3b, + 0x3b, 0xf6, 0xe5, 0x83, 0x0f, 0xad, 0x10, 0x78, 0xc0, 0x06, 0x57, 0xfe, + 0x54, 0x7d, 0x85, 0xb7, 0xaf, 0xbf, 0xe7, 0x5f, 0xe9, 0x4d, 0x82, 0xfd, + 0xc3, 0xaf, 0xf6, 0xc7, 0x98, 0x30, 0x33, 0x9d, 0x7d, 0x00, 0x54, 0xa1, + 0xd7, 0xbd, 0xe8, 0x3a, 0xff, 0x27, 0x22, 0x77, 0xe3, 0x4e, 0xb7, 0xb8, + 0x7e, 0x2e, 0x49, 0xe1, 0xbb, 0xff, 0xdc, 0x68, 0xe6, 0xc1, 0xc8, 0xe4, + 0x68, 0xeb, 0xfc, 0xf3, 0x77, 0x17, 0x9a, 0x3a, 0xb0, 0xfe, 0xb6, 0x24, + 0x5f, 0xc8, 0xa7, 0xb3, 0x16, 0x75, 0xfb, 0x02, 0x9c, 0xd1, 0xd7, 0xbd, + 0xed, 0xce, 0xbf, 0xfb, 0x76, 0xa7, 0x7e, 0x6d, 0x67, 0x51, 0x67, 0x57, + 0xe7, 0xcd, 0xe1, 0xdb, 0x81, 0xc3, 0xab, 0x46, 0xe7, 0x6c, 0x8e, 0xd1, + 0x3a, 0x3a, 0x59, 0x86, 0x2d, 0x42, 0xab, 0xbc, 0x85, 0x32, 0x42, 0xbb, + 0xa4, 0x7e, 0x8c, 0x56, 0xff, 0xc2, 0x9f, 0x77, 0xcd, 0x9b, 0xc7, 0xd3, + 0xaf, 0xff, 0x26, 0x70, 0x30, 0xce, 0x76, 0x37, 0xd1, 0xd7, 0xdf, 0x63, + 0x9f, 0x9d, 0x73, 0xf0, 0xeb, 0xfb, 0xc9, 0x3a, 0xe1, 0xa7, 0x50, 0x4f, + 0x0b, 0xa2, 0xb7, 0x66, 0xd1, 0xd7, 0xdf, 0xfd, 0x19, 0x1d, 0x77, 0xee, + 0x26, 0xf3, 0xc3, 0x15, 0x08, 0x8a, 0x02, 0xf5, 0xdb, 0xcc, 0x75, 0xfb, + 0xef, 0xbf, 0x5e, 0x1d, 0x4b, 0x3c, 0x2f, 0xc6, 0x2f, 0x36, 0x34, 0x75, + 0xff, 0x49, 0xf9, 0xe1, 0x85, 0xe8, 0xeb, 0xfd, 0x01, 0x8e, 0x02, 0x3f, + 0x3a, 0xe5, 0xea, 0x63, 0xe9, 0x59, 0xbd, 0xff, 0xa1, 0xc7, 0x3d, 0xe4, + 0x67, 0xc7, 0x54, 0x26, 0x25, 0x84, 0x69, 0x08, 0x40, 0x17, 0xd2, 0xa9, + 0x7a, 0xfa, 0x11, 0xa5, 0x2b, 0xb3, 0x16, 0x5a, 0x89, 0x32, 0x4e, 0xa1, + 0xe1, 0xe8, 0xdd, 0xaf, 0xe8, 0x06, 0xe9, 0xbe, 0xd1, 0xd7, 0xec, 0x67, + 0x37, 0xf1, 0xd6, 0xe7, 0xc3, 0xd9, 0x43, 0x1b, 0xff, 0xda, 0xc1, 0x03, + 0x7b, 0x8b, 0x99, 0xda, 0x75, 0xfe, 0x15, 0x3b, 0x0b, 0x58, 0x9d, 0x7f, + 0x2b, 0xa4, 0x6d, 0x03, 0xc7, 0x5f, 0xa2, 0x6c, 0xc6, 0x9d, 0x58, 0x88, + 0xa4, 0x32, 0xe9, 0x95, 0xff, 0xbb, 0x93, 0x24, 0xc0, 0xda, 0x06, 0x8e, + 0xbc, 0x9c, 0x50, 0xea, 0x43, 0xdf, 0x14, 0x3b, 0xf4, 0x6d, 0x76, 0x26, + 0x3a, 0xa4, 0x79, 0x5a, 0x20, 0xbf, 0xf8, 0x13, 0x27, 0x63, 0x79, 0x44, + 0xd0, 0x75, 0xf8, 0x2e, 0x31, 0xd3, 0xaf, 0xe9, 0x46, 0xfe, 0xce, 0x9d, + 0x7f, 0xfb, 0xda, 0x4f, 0xe2, 0x5a, 0xcc, 0xdf, 0xc7, 0x54, 0xc7, 0xef, + 0xa2, 0xdb, 0x27, 0x51, 0x7e, 0xcc, 0x27, 0x2f, 0xff, 0xdc, 0x07, 0x39, + 0x03, 0x8a, 0x27, 0x7b, 0x9f, 0x4e, 0xbf, 0x85, 0xd0, 0x30, 0x27, 0x5f, + 0x4f, 0x1b, 0x50, 0x75, 0xed, 0x80, 0xe9, 0xd7, 0xff, 0x22, 0xd3, 0x5d, + 0x84, 0xe0, 0x15, 0xce, 0xa8, 0x44, 0x3a, 0x12, 0x38, 0xf5, 0xfc, 0x3a, + 0x4d, 0x90, 0x13, 0xaf, 0x0a, 0x28, 0x75, 0xfd, 0xe4, 0xe2, 0x78, 0x07, + 0x5a, 0x16, 0x78, 0xff, 0x46, 0xef, 0xe0, 0x7d, 0xee, 0x6f, 0xa3, 0xaf, + 0xff, 0xff, 0xdc, 0x8f, 0x0b, 0xb5, 0x35, 0x32, 0x71, 0xb1, 0xaf, 0x46, + 0xf1, 0xf7, 0x34, 0x75, 0xfe, 0xee, 0x6f, 0x1c, 0x45, 0x9d, 0x7f, 0xff, + 0xff, 0xed, 0x6b, 0x3d, 0xd7, 0x5e, 0xb9, 0xc4, 0xdf, 0xce, 0xea, 0x66, + 0x4c, 0x0f, 0x43, 0x3b, 0xc1, 0xd5, 0x09, 0xa8, 0x86, 0x10, 0x6e, 0x65, + 0x7d, 0xfb, 0xef, 0xa3, 0xae, 0x65, 0x93, 0xab, 0x46, 0xed, 0x92, 0x3b, + 0xf2, 0x75, 0xf3, 0xa5, 0x30, 0x68, 0xaf, 0xf8, 0x1e, 0x81, 0x6a, 0xb7, + 0xfa, 0xce, 0xbd, 0xd8, 0xfc, 0xea, 0x43, 0xda, 0x73, 0xeb, 0xfd, 0xd8, + 0xf0, 0x16, 0x0f, 0x1d, 0x50, 0xbf, 0xd9, 0x22, 0x90, 0xc3, 0x4f, 0x78, + 0x6b, 0xab, 0x91, 0x4d, 0x18, 0x27, 0x0b, 0x96, 0xad, 0xd8, 0x58, 0x39, + 0x6f, 0xee, 0x8a, 0x92, 0x91, 0x8e, 0x07, 0x50, 0x91, 0xf4, 0x24, 0x36, + 0x88, 0x2f, 0xd3, 0x44, 0xdd, 0x83, 0xae, 0xfb, 0x07, 0x5e, 0x65, 0x96, + 0x4a, 0xbe, 0x97, 0xb1, 0xa5, 0x30, 0x5f, 0xdf, 0xb0, 0x29, 0xfe, 0x8f, + 0x77, 0xf5, 0x70, 0xf9, 0x44, 0xc6, 0xa1, 0x1c, 0x9c, 0x28, 0x78, 0x4d, + 0xdd, 0xed, 0x1d, 0x7f, 0xdf, 0x3d, 0xd8, 0xf6, 0xba, 0x87, 0x5b, 0x47, + 0x5f, 0xef, 0x6f, 0x2e, 0xc0, 0xce, 0x75, 0xff, 0xb3, 0x79, 0x26, 0x08, + 0xe0, 0x4e, 0xbf, 0x4e, 0xb0, 0x6f, 0xe3, 0xaa, 0x11, 0xf3, 0xb8, 0xb7, + 0x0e, 0x84, 0x43, 0x46, 0x9e, 0x3b, 0xbf, 0xe1, 0x86, 0x74, 0x83, 0xbc, + 0x8e, 0xba, 0x1a, 0x75, 0x09, 0xe6, 0xec, 0x38, 0xbe, 0x9f, 0xec, 0x2b, + 0x9d, 0x7f, 0xb4, 0x11, 0x86, 0x70, 0x4e, 0xae, 0x1e, 0xc7, 0x89, 0xea, + 0x13, 0x40, 0x48, 0x51, 0xbb, 0xdd, 0xfc, 0x3b, 0xea, 0x6c, 0xf1, 0xd7, + 0xf2, 0x78, 0x5f, 0xfd, 0x1d, 0x7f, 0xfb, 0xd3, 0x67, 0x31, 0xd7, 0x1d, + 0x40, 0x9d, 0x7f, 0x01, 0x79, 0xdd, 0xdc, 0xea, 0x51, 0x14, 0x22, 0x59, + 0xa4, 0x8b, 0xff, 0xc8, 0x11, 0x7d, 0xc7, 0x3d, 0x89, 0xf9, 0xd7, 0xf4, + 0x7b, 0xb2, 0xd0, 0x0e, 0xbf, 0x75, 0xf9, 0x9c, 0x3a, 0xe0, 0x39, 0xd4, + 0xd3, 0x76, 0x24, 0xd7, 0xf7, 0x21, 0x24, 0xfa, 0x3a, 0xd1, 0x39, 0xe5, + 0x89, 0x05, 0xfa, 0x75, 0x74, 0xcd, 0xce, 0xbf, 0x26, 0xa2, 0x75, 0x9e, + 0xcf, 0xdb, 0xf4, 0x3f, 0x3f, 0x01, 0xec, 0xfd, 0xb9, 0xe4, 0x7b, 0x3f, + 0x6f, 0x81, 0x2c, 0xd1, 0xec, 0xfd, 0xa0, 0x9e, 0x80, 0x91, 0x5f, 0xa3, + 0x35, 0x82, 0x7b, 0x3f, 0x68, 0xf6, 0x7e, 0xdc, 0xfe, 0x3d, 0x9f, 0xab, + 0x2d, 0xed, 0x21, 0x3f, 0x90, 0x24, 0x5f, 0x66, 0xda, 0x7e, 0x7b, 0x3f, + 0x68, 0xf6, 0x7e, 0xdd, 0xfc, 0x1e, 0xcf, 0xdb, 0xfe, 0xcf, 0xdf, 0x99, + 0xb3, 0x02, 0x7b, 0x3f, 0x6f, 0xec, 0xea, 0x68, 0x13, 0x9e, 0xcf, 0xda, + 0xfd, 0x14, 0x62, 0x47, 0xa4, 0x6b, 0xee, 0x4f, 0x1e, 0x3d, 0x9f, 0xb4, + 0x7b, 0x3f, 0x70, 0xd7, 0xdc, 0xcb, 0x27, 0xb3, 0xf6, 0xa4, 0xac, 0x38, + 0x26, 0x99, 0x08, 0x4d, 0xe1, 0x35, 0xc2, 0x75, 0x98, 0xea, 0x17, 0x5e, + 0x5f, 0x64, 0x9a, 0xf4, 0xa1, 0x42, 0xd9, 0xfa, 0x61, 0x12, 0x17, 0xfb, + 0x59, 0x29, 0x47, 0xb7, 0x3a, 0xb0, 0xfc, 0x34, 0x7b, 0x7f, 0xec, 0x68, + 0x73, 0x8c, 0xbf, 0x66, 0x3a, 0xe9, 0x4e, 0x55, 0xf4, 0xce, 0xfc, 0x3a, + 0xa7, 0x44, 0xc6, 0xe4, 0x22, 0x7f, 0xb4, 0x2f, 0x5c, 0x5d, 0x12, 0x79, + 0xcd, 0x1b, 0xfc, 0xbd, 0x0e, 0x7b, 0x3f, 0x3a, 0xff, 0x9b, 0x1f, 0x84, + 0x0f, 0xc9, 0x1d, 0x7f, 0xe7, 0x79, 0xf1, 0x6e, 0x3b, 0xc8, 0xeb, 0xf3, + 0x22, 0xea, 0x6b, 0x0f, 0xda, 0x63, 0x9a, 0x84, 0x74, 0x3c, 0x2a, 0x2f, + 0xc3, 0xee, 0xe4, 0xe7, 0x5c, 0x16, 0x4e, 0xa8, 0x37, 0xd8, 0x4f, 0x7f, + 0xfe, 0x97, 0x23, 0x63, 0xcd, 0x01, 0xec, 0x2d, 0xe6, 0x3a, 0xff, 0x6d, + 0x3e, 0x93, 0x53, 0x61, 0xd5, 0xba, 0x23, 0x38, 0xaf, 0x50, 0xcc, 0x19, + 0x94, 0xa6, 0xcc, 0x33, 0x48, 0x67, 0xab, 0x98, 0x71, 0x1f, 0xb0, 0xb3, + 0x79, 0xd3, 0x91, 0x8c, 0x57, 0x4c, 0x80, 0x85, 0x5d, 0xff, 0xff, 0x27, + 0x5f, 0xb1, 0x26, 0x33, 0xf8, 0x96, 0x83, 0xd8, 0xe1, 0xd7, 0xfe, 0x52, + 0x37, 0x18, 0xef, 0x40, 0xd3, 0xaf, 0xff, 0x07, 0x91, 0x83, 0x92, 0x4e, + 0xe6, 0xc3, 0xaf, 0xe1, 0x75, 0x3a, 0xf2, 0x3a, 0xf3, 0x2c, 0xb2, 0x55, + 0xef, 0xb1, 0xf9, 0x4c, 0x17, 0xf7, 0xfc, 0xf2, 0xfb, 0xcc, 0xd8, 0xfc, + 0x3a, 0xff, 0xfd, 0xdc, 0x97, 0xd1, 0x1c, 0x9e, 0x69, 0x47, 0x27, 0x3a, + 0x85, 0x12, 0x7e, 0x3b, 0xbf, 0xef, 0x38, 0xe6, 0xb9, 0x1a, 0x3a, 0xfa, + 0x51, 0xfe, 0xe7, 0x5f, 0xdf, 0xc0, 0xe6, 0xfe, 0x3a, 0xe7, 0xff, 0xe1, + 0xe8, 0x7d, 0x23, 0xa7, 0x45, 0xc0, 0xc2, 0x1a, 0xf6, 0xc8, 0xe1, 0xd5, + 0x25, 0x62, 0xc1, 0x66, 0xc3, 0xf5, 0xa4, 0x7e, 0x96, 0x30, 0xc1, 0xf4, + 0x36, 0xb6, 0x13, 0x5c, 0x93, 0x9d, 0x7f, 0x85, 0xa1, 0x4d, 0x90, 0x13, + 0xa8, 0x27, 0x92, 0x01, 0x6b, 0x7e, 0x75, 0xff, 0x64, 0x2b, 0xfc, 0xeb, + 0xe7, 0x0e, 0xbf, 0xdf, 0xed, 0xa2, 0xc2, 0x1c, 0x3a, 0xff, 0xbd, 0xdc, + 0xd7, 0xcf, 0x24, 0xe7, 0x54, 0x1f, 0x8a, 0x1b, 0x5f, 0xf0, 0xa0, 0x15, + 0x3a, 0xdb, 0x8f, 0x1d, 0x52, 0x4c, 0x6e, 0x61, 0x1e, 0xc2, 0xb0, 0x48, + 0x2f, 0x32, 0xcb, 0x25, 0x88, 0x41, 0x7c, 0xd7, 0x76, 0x96, 0x21, 0x03, + 0x06, 0xb6, 0xf9, 0xf9, 0x8c, 0x9d, 0x5c, 0x3e, 0x0d, 0x87, 0xf7, 0x99, + 0x65, 0x92, 0xc4, 0x1e, 0xa2, 0xc4, 0x1e, 0x60, 0xd6, 0xde, 0x65, 0x96, + 0x4e, 0xbd, 0xa8, 0x50, 0xa6, 0x0b, 0xfb, 0x2f, 0x11, 0x8a, 0xd5, 0x1f, + 0x24, 0x5f, 0xfd, 0xd8, 0x92, 0x7b, 0x3a, 0xd8, 0x59, 0xd5, 0x07, 0xef, + 0xb0, 0xd6, 0xff, 0xf6, 0x75, 0x39, 0xd7, 0xcd, 0x23, 0xce, 0x75, 0xf4, + 0x7a, 0x16, 0x75, 0x2c, 0xf9, 0xfc, 0x8f, 0x7f, 0x32, 0xe1, 0x03, 0xfd, + 0x3a, 0xf8, 0x52, 0x14, 0x3a, 0xf7, 0xd8, 0xfc, 0xea, 0x9c, 0xdf, 0x2c, + 0x82, 0xfc, 0xd8, 0xec, 0x2c, 0xab, 0xf0, 0xb8, 0x8e, 0x15, 0x76, 0x34, + 0xab, 0x99, 0x64, 0xaa, 0xc3, 0xf6, 0xd1, 0x37, 0x88, 0xd9, 0x15, 0xbf, + 0xc3, 0xf6, 0x3f, 0xee, 0x6d, 0x14, 0xc1, 0xbc, 0xbf, 0xfd, 0x38, 0x78, + 0xed, 0x1c, 0xd9, 0xc4, 0xd1, 0xd5, 0x09, 0xfb, 0x61, 0x12, 0x36, 0xbc, + 0x35, 0x00, 0x91, 0x7f, 0xf4, 0x7f, 0xac, 0xc0, 0xb8, 0xba, 0x87, 0x5f, + 0xff, 0x4b, 0x4c, 0xc7, 0x3b, 0x09, 0xd8, 0x14, 0x3a, 0xff, 0xfb, 0x43, + 0x9b, 0xfe, 0xfa, 0x7e, 0x26, 0xff, 0x9d, 0x5b, 0xa2, 0x79, 0x94, 0xda, + 0xea, 0x60, 0xaf, 0x0e, 0x0b, 0xfb, 0x5f, 0x42, 0x01, 0x91, 0xd7, 0xf2, + 0x34, 0x38, 0xff, 0x9d, 0x7f, 0xff, 0xe8, 0x9d, 0x8d, 0x7b, 0x5b, 0xfc, + 0x0e, 0x06, 0x1f, 0x98, 0x3f, 0x9d, 0x7e, 0x5e, 0x99, 0x7d, 0xce, 0xb6, + 0x82, 0x89, 0x9f, 0xae, 0x17, 0xf6, 0x4d, 0x24, 0xe6, 0x8e, 0xa8, 0x64, + 0xaa, 0x86, 0x18, 0xf9, 0x19, 0xea, 0x4a, 0x0c, 0xe4, 0xa8, 0x07, 0x8d, + 0x45, 0x52, 0x50, 0x25, 0xfa, 0x86, 0x2f, 0x8a, 0xef, 0x32, 0xcb, 0x25, + 0x5f, 0x7e, 0xe2, 0x12, 0x98, 0x2f, 0xef, 0xba, 0x8f, 0x23, 0xaf, 0xb9, + 0xc4, 0x59, 0xd7, 0xb5, 0x1e, 0x3a, 0xf0, 0xfb, 0x48, 0x6f, 0x26, 0x21, + 0xbd, 0xf1, 0x4d, 0xb3, 0xaf, 0x79, 0xc2, 0x75, 0x70, 0xde, 0xe8, 0x8a, + 0xfe, 0x6c, 0x7e, 0x9c, 0x50, 0xeb, 0xfb, 0xee, 0x73, 0x32, 0x63, 0xaf, + 0xcf, 0xdf, 0x81, 0x83, 0xaa, 0x49, 0xd0, 0x84, 0xc7, 0x17, 0x11, 0xbc, + 0x48, 0x74, 0x5d, 0xe2, 0xeb, 0xf3, 0xf3, 0x99, 0xb9, 0xd7, 0xff, 0xbd, + 0xd4, 0x7f, 0xf3, 0x81, 0x81, 0x91, 0xd7, 0xff, 0xb7, 0xf9, 0xbf, 0xf0, + 0x2d, 0x79, 0xc5, 0xce, 0xa8, 0x45, 0xe6, 0x13, 0x8a, 0x45, 0xfa, 0x35, + 0xf4, 0x64, 0x75, 0xff, 0xff, 0xce, 0x9e, 0x4e, 0xb5, 0x3e, 0x49, 0x3a, + 0xe3, 0xe9, 0x67, 0x30, 0xeb, 0xdd, 0xcd, 0xa3, 0xaf, 0xde, 0xd7, 0xdd, + 0x7c, 0xea, 0x23, 0x5d, 0xbe, 0xfe, 0x67, 0x5d, 0x76, 0xc1, 0xd7, 0xff, + 0xff, 0x22, 0x9b, 0xcb, 0xd8, 0x3e, 0xd7, 0xcd, 0x6b, 0x39, 0x82, 0xf2, + 0x3a, 0xff, 0xe6, 0x02, 0x30, 0x06, 0xe2, 0x89, 0xc3, 0xae, 0xc6, 0x4e, + 0xb6, 0x41, 0xed, 0x69, 0x12, 0xff, 0x07, 0xb1, 0x33, 0xbe, 0xe7, 0x5e, + 0xef, 0xfb, 0x0e, 0xae, 0x1e, 0x96, 0xd1, 0x9d, 0x49, 0x13, 0xae, 0xf1, + 0x7f, 0xf6, 0x73, 0xf5, 0xa6, 0xbe, 0xea, 0x30, 0xeb, 0xce, 0xaf, 0xa3, + 0xaa, 0x47, 0xc6, 0xe8, 0xb7, 0x83, 0x8b, 0x3a, 0xfb, 0xff, 0x67, 0xe7, + 0x52, 0x1b, 0xee, 0x0d, 0xdf, 0xf3, 0x7a, 0x31, 0xba, 0x47, 0x4e, 0xa8, + 0x5d, 0x16, 0x94, 0x63, 0xc1, 0x2d, 0xc8, 0x5a, 0xa2, 0x27, 0x0b, 0x5e, + 0x36, 0xa1, 0x84, 0x28, 0x17, 0xfe, 0x90, 0x5f, 0xf9, 0xd0, 0x20, 0xf6, + 0xa7, 0xc6, 0x4e, 0xbf, 0x6b, 0x14, 0x8d, 0x1d, 0x7f, 0x2b, 0xe9, 0x07, + 0x79, 0x1d, 0x7f, 0xe7, 0xe6, 0xda, 0x77, 0x1f, 0x7f, 0xce, 0xbf, 0xff, + 0x27, 0xa1, 0x79, 0xbf, 0xa1, 0x7f, 0x78, 0xff, 0x9d, 0x7c, 0x82, 0xe1, + 0x3a, 0xff, 0xb5, 0x1c, 0xf4, 0x30, 0x14, 0x3a, 0xa4, 0x8a, 0xe0, 0xab, + 0xe8, 0x7e, 0xff, 0xf6, 0x93, 0x91, 0x2e, 0xc4, 0xc2, 0x05, 0x0e, 0xb9, + 0xbb, 0x67, 0x5f, 0xca, 0x7a, 0x3b, 0x1a, 0x3a, 0xfe, 0xea, 0x6f, 0xa7, + 0xdc, 0xea, 0x91, 0xfa, 0x20, 0xcf, 0xe5, 0xb7, 0xfe, 0x17, 0x9b, 0xaf, + 0xce, 0x20, 0x4e, 0xbc, 0x14, 0x13, 0xaf, 0xe8, 0xf2, 0xa1, 0xe3, 0x73, + 0xab, 0xe1, 0xe5, 0x20, 0xd5, 0x49, 0x58, 0x6e, 0x13, 0xb4, 0xc1, 0x21, + 0xdf, 0x31, 0x87, 0x21, 0x7c, 0xb2, 0xf6, 0x61, 0x0f, 0x7e, 0x45, 0xaa, + 0xca, 0xbd, 0x5b, 0x3a, 0xfb, 0xec, 0x33, 0xa3, 0xae, 0xff, 0xc7, 0x5f, + 0x73, 0x99, 0xa3, 0xae, 0xc9, 0x8e, 0xb4, 0xbe, 0x1f, 0x94, 0xe4, 0x8e, + 0x2f, 0xf4, 0x86, 0xfc, 0x9e, 0x71, 0xc3, 0xaf, 0xdc, 0x0e, 0x60, 0x9d, + 0x7f, 0xf2, 0xba, 0x67, 0x63, 0x66, 0xbb, 0x1b, 0x9d, 0x7f, 0x6f, 0xc0, + 0x6f, 0xe9, 0x1d, 0x4e, 0x89, 0xdd, 0x12, 0x81, 0x22, 0xff, 0xb0, 0x79, + 0x9a, 0xc4, 0xe9, 0xd7, 0xff, 0xd2, 0xf0, 0xe3, 0xf8, 0x73, 0xde, 0xc6, + 0x4e, 0xbd, 0x3e, 0x6c, 0x3a, 0xff, 0xf7, 0xb5, 0x93, 0x76, 0x36, 0x67, + 0x7b, 0x07, 0x5f, 0xdd, 0x0a, 0x6c, 0x80, 0x9d, 0x58, 0x7f, 0x2e, 0x97, + 0x7d, 0x9e, 0x4d, 0x1d, 0x7f, 0x2b, 0x13, 0x0a, 0xb7, 0x38, 0x0e, 0xad, + 0x1e, 0xcf, 0x88, 0x2a, 0x4a, 0xa9, 0x03, 0x0c, 0x16, 0x97, 0xee, 0x6b, + 0xc4, 0xd1, 0x84, 0xbf, 0x9e, 0x6f, 0x33, 0x9d, 0x3a, 0xff, 0x69, 0x14, + 0xeb, 0x8a, 0x1d, 0x7c, 0x9a, 0xc0, 0xb9, 0xe6, 0xf8, 0x72, 0xff, 0xce, + 0xaf, 0xf8, 0x34, 0x83, 0xbc, 0x8e, 0xbf, 0xff, 0xbd, 0x9d, 0x48, 0xf2, + 0x7f, 0x12, 0x61, 0x96, 0x59, 0x2a, 0xff, 0x74, 0x0e, 0xb0, 0xba, 0xce, + 0xa1, 0x44, 0x87, 0x97, 0xaf, 0x83, 0x98, 0xa1, 0x57, 0xcf, 0xfb, 0xf8, + 0xeb, 0xfe, 0xe3, 0xb7, 0xe7, 0x63, 0xe8, 0x9d, 0x78, 0x11, 0xc3, 0xae, + 0xf6, 0x82, 0x7a, 0xd3, 0x1d, 0xde, 0x90, 0x80, 0xd1, 0x0c, 0xde, 0xec, + 0x4e, 0x75, 0xe6, 0x59, 0x64, 0xab, 0xd8, 0x2d, 0x29, 0x82, 0xfe, 0xff, + 0xd9, 0x3e, 0x05, 0xe4, 0x31, 0x39, 0xd5, 0xf9, 0xf3, 0x89, 0x55, 0xf3, + 0x8a, 0xb5, 0x55, 0x1d, 0x72, 0xb5, 0x56, 0xa7, 0x5f, 0xb3, 0xde, 0x04, + 0xe7, 0x5a, 0x4a, 0xd4, 0xf2, 0x84, 0x8a, 0xf3, 0xab, 0xc1, 0xd7, 0xec, + 0x0f, 0x5d, 0x5c, 0xeb, 0xf0, 0xe0, 0x61, 0x67, 0x54, 0x2a, 0xe1, 0x9c, + 0x88, 0x24, 0x38, 0xef, 0xb9, 0x7c, 0xc5, 0x1c, 0x85, 0x17, 0x48, 0x9d, + 0xd0, 0x05, 0xbb, 0x07, 0x59, 0x29, 0xbf, 0xd0, 0xbc, 0x4e, 0x4d, 0x23, + 0xaf, 0x79, 0x20, 0xeb, 0xb0, 0x4e, 0xa4, 0x35, 0xc0, 0x1a, 0xbf, 0xff, + 0x75, 0xf9, 0xac, 0x41, 0x7f, 0x69, 0x98, 0x13, 0xaf, 0xc1, 0x4e, 0x47, + 0x8e, 0xbb, 0x7f, 0xce, 0xbf, 0x97, 0x1a, 0xfd, 0x1a, 0x75, 0xed, 0x42, + 0x9f, 0x9e, 0x2e, 0x86, 0x2f, 0xf0, 0x33, 0x9f, 0xfe, 0x82, 0x75, 0xff, + 0xb1, 0x68, 0x1e, 0x60, 0x5d, 0x67, 0x5f, 0x62, 0xfe, 0x84, 0xea, 0xe9, + 0xef, 0x89, 0xe5, 0xff, 0xe4, 0x0f, 0x7e, 0xeb, 0x38, 0xd7, 0x76, 0x9a, + 0x20, 0xcb, 0xe0, 0x77, 0x1a, 0x75, 0x48, 0xfe, 0x36, 0xd5, 0xef, 0x74, + 0x0a, 0xe7, 0x5f, 0xfe, 0xe3, 0xec, 0xc1, 0x6f, 0x53, 0xff, 0xbe, 0x3a, + 0xa1, 0x12, 0x2a, 0x92, 0x50, 0x0f, 0xd6, 0xea, 0x89, 0x3a, 0x6b, 0xa8, + 0x49, 0x7a, 0x32, 0xab, 0xfd, 0xfa, 0x77, 0xb9, 0xfb, 0x9d, 0x7f, 0xff, + 0xcb, 0xcf, 0x79, 0xf8, 0x31, 0xbc, 0xbe, 0xf3, 0xf5, 0xa6, 0x8e, 0xbf, + 0xe5, 0xa3, 0x38, 0x21, 0xec, 0x1d, 0x77, 0x40, 0x75, 0xff, 0xfa, 0x48, + 0x21, 0xee, 0x6f, 0xf5, 0xc7, 0xc2, 0x13, 0xaf, 0x23, 0x2a, 0xe7, 0x5f, + 0xec, 0xd9, 0xaf, 0x7a, 0x16, 0x75, 0x70, 0xf4, 0xfa, 0x3f, 0x50, 0x9c, + 0x06, 0x34, 0xa1, 0xbc, 0xc2, 0xda, 0x85, 0x45, 0xfe, 0xdb, 0xcd, 0x6d, + 0xe7, 0x20, 0xea, 0x92, 0xec, 0x20, 0x48, 0x31, 0x49, 0x25, 0x47, 0xfe, + 0x97, 0xa8, 0xec, 0xfc, 0x9d, 0x7f, 0xb5, 0xac, 0x1f, 0xf6, 0xf0, 0xeb, + 0xe1, 0x4d, 0xa8, 0x3a, 0xd3, 0x1d, 0x7f, 0x6b, 0x07, 0xfd, 0xbc, 0x3a, + 0xdb, 0x3e, 0x22, 0x5f, 0x0d, 0x7f, 0x22, 0xd0, 0x8d, 0xff, 0x03, 0xdf, + 0x81, 0x71, 0x9e, 0x3a, 0xff, 0xf0, 0xcf, 0xf2, 0x64, 0x1c, 0x0e, 0x0a, + 0x87, 0x5f, 0xc9, 0xbe, 0xd7, 0x63, 0xc7, 0x5e, 0xfb, 0x90, 0x75, 0x42, + 0x25, 0xd5, 0xd2, 0xdc, 0xc2, 0xff, 0xff, 0xce, 0x1c, 0x17, 0xf6, 0xb3, + 0x9f, 0xff, 0x19, 0xbf, 0xb4, 0x87, 0x5e, 0x8e, 0x4c, 0x75, 0x7c, 0x6d, + 0x5d, 0x22, 0x5a, 0x64, 0xf0, 0x82, 0x0c, 0x2a, 0x72, 0x57, 0x53, 0x61, + 0x7b, 0xb9, 0xba, 0x4b, 0xb3, 0xec, 0x2b, 0xde, 0x77, 0x93, 0xf8, 0xc2, + 0x85, 0x1c, 0x10, 0xd0, 0x64, 0xc7, 0x6d, 0xae, 0xf6, 0xf3, 0xec, 0x3a, + 0xfe, 0xf8, 0xde, 0xc6, 0xfb, 0x47, 0x5e, 0xf9, 0xfb, 0x27, 0x56, 0xe7, + 0xa7, 0xe3, 0x3b, 0xfb, 0x19, 0xcc, 0x15, 0x0e, 0xbe, 0x5b, 0xe6, 0x8e, + 0xa4, 0x3c, 0xc7, 0x2c, 0xbf, 0xfe, 0x6c, 0x6b, 0x50, 0xbc, 0xf2, 0x6b, + 0xae, 0x75, 0xfe, 0x11, 0x89, 0x2e, 0x10, 0xeb, 0xfd, 0xe4, 0xd8, 0x9e, + 0x94, 0x15, 0x65, 0x9d, 0x7f, 0x60, 0xa9, 0xc8, 0x61, 0x0f, 0x0f, 0xe9, + 0x9d, 0x62, 0x60, 0xa8, 0x9b, 0xa7, 0x2b, 0xee, 0x03, 0x79, 0x1d, 0x7f, + 0x86, 0x43, 0x8b, 0x86, 0x9d, 0x79, 0x61, 0xc3, 0xaa, 0x0f, 0xbb, 0x08, + 0xdc, 0xc2, 0xf6, 0xd8, 0x3c, 0x75, 0xff, 0xef, 0x42, 0xd0, 0x38, 0x2a, + 0x76, 0x16, 0x75, 0x34, 0xf9, 0xfc, 0x3f, 0x7f, 0xfc, 0x9e, 0xec, 0x6a, + 0x3b, 0x09, 0x3c, 0x28, 0x75, 0xfb, 0xde, 0xd3, 0xfe, 0x75, 0xfa, 0x17, + 0xec, 0x69, 0xd7, 0x24, 0xe7, 0x54, 0x22, 0xc9, 0x13, 0xba, 0x51, 0xe2, + 0x6b, 0xf3, 0x28, 0x1d, 0xa4, 0x3a, 0xff, 0xbb, 0x12, 0x41, 0xc5, 0xc1, + 0xd7, 0xfd, 0x9e, 0xee, 0x2c, 0x5f, 0xc7, 0x5f, 0xdb, 0x13, 0x9b, 0xc2, + 0xb9, 0xd6, 0x10, 0x9f, 0x46, 0x1b, 0x5f, 0x97, 0x0d, 0x9c, 0x27, 0x5f, + 0x4a, 0x16, 0xe7, 0x5f, 0xb9, 0xfa, 0xd3, 0x47, 0x5d, 0xed, 0x61, 0xf8, + 0x39, 0x47, 0xd2, 0x0a, 0x84, 0x68, 0x82, 0x12, 0xd6, 0xd1, 0xd7, 0xf4, + 0x4f, 0x82, 0x8a, 0x1d, 0x5c, 0x37, 0x9a, 0x10, 0xbf, 0xfa, 0x05, 0xfb, + 0x1f, 0xb1, 0xcd, 0x68, 0xaa, 0x9d, 0x51, 0xb0, 0x63, 0x6e, 0xc6, 0x35, + 0x90, 0xdf, 0xe7, 0x0e, 0xb5, 0x1c, 0x91, 0xd7, 0x02, 0x73, 0xaf, 0xf6, + 0xf2, 0xdf, 0x49, 0xe8, 0x3a, 0xf2, 0x6f, 0xa3, 0xab, 0x0f, 0x41, 0x0d, + 0x29, 0x11, 0x0f, 0xd6, 0x7b, 0xb1, 0xa7, 0x5e, 0xe6, 0x68, 0xef, 0x16, + 0xb7, 0xff, 0xc1, 0xf8, 0xe9, 0x9a, 0x89, 0xf0, 0x51, 0x43, 0xaf, 0xf7, + 0x17, 0x1b, 0xf9, 0xda, 0x75, 0x62, 0x20, 0x91, 0x3e, 0xf9, 0x17, 0x13, + 0x1d, 0x7d, 0x93, 0x82, 0x47, 0x54, 0xc7, 0x86, 0xc9, 0x0d, 0xf0, 0x02, + 0x18, 0x3a, 0xa0, 0xf1, 0x5c, 0x92, 0xec, 0x64, 0xea, 0x2a, 0xfe, 0xd7, + 0xd8, 0xe4, 0x2c, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, 0x91, 0xf0, 0x20, + 0x57, 0xe5, 0xc0, 0x0a, 0xdb, 0x0a, 0xda, 0x0a, 0xbb, 0xb8, 0x55, 0xfc, + 0xef, 0xe9, 0xa1, 0x65, 0x7c, 0x2d, 0x6c, 0xa9, 0x2a, 0x8a, 0xa2, 0xaa, + 0x45, 0xa2, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0x54, 0x55, 0x4e, + 0x6f, 0x02, 0x14, 0x81, 0x5f, 0x85, 0x68, 0x2b, 0x60, 0x55, 0x15, 0x45, + 0x54, 0x8b, 0x4d, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, 0x54, 0x8d, 0x47, + 0xe1, 0x5e, 0x0a, 0xda, 0x0a, 0xa2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa9, 0xcd, + 0x42, 0x81, 0x5c, 0x0a, 0xe8, 0x55, 0x94, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, + 0x2a, 0x82, 0x6a, 0x37, 0x0a, 0xfc, 0x28, 0x01, 0x54, 0x55, 0x15, 0x45, + 0x5f, 0xbb, 0x1f, 0xeb, 0x0a, 0xa2, 0xaa, 0x47, 0x9e, 0xd0, 0xae, 0x85, + 0x38, 0x57, 0xe4, 0xf6, 0x69, 0x54, 0x55, 0x15, 0x45, 0x51, 0x55, 0x23, + 0x51, 0xb8, 0x52, 0x05, 0x6c, 0x0a, 0xa2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa9, + 0x1a, 0x80, 0x85, 0x74, 0x28, 0x42, 0xad, 0xd2, 0xa8, 0xaa, 0x2a, 0xd2, + 0x2a, 0x8a, 0xdc, 0xb0, 0xa2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa9, 0xcf, 0x9a, + 0x41, 0x4a, 0x0d, 0x34, 0x6a, 0x60, 0xaf, 0xc2, 0xbc, 0x15, 0x6c, 0x2a, + 0x8a, 0xa2, 0xad, 0x22, 0xa8, 0xad, 0xcb, 0x0a, 0x2a, 0x8a, 0xa8, 0x3d, + 0x29, 0x05, 0x20, 0xd7, 0x06, 0x96, 0x15, 0x45, 0x51, 0x54, 0x55, 0x15, + 0x45, 0x54, 0x1b, 0x2d, 0xc2, 0xb8, 0x14, 0xb0, 0xa1, 0x0a, 0xa2, 0xa8, + 0xaa, 0x2a, 0xb8, 0x5f, 0x68, 0x2b, 0xc1, 0x54, 0x55, 0x15, 0x45, 0x52, + 0xcb, 0xe1, 0x0a, 0xf0, 0x55, 0x96, 0x55, 0x15, 0x45, 0x57, 0xe5, 0xa0, + 0x02, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x0d, 0x44, 0xc1, 0x5d, 0x0a, + 0x00, 0x55, 0x42, 0xfd, 0x4c, 0xee, 0x32, 0x3d, 0x09, 0x46, 0x2d, 0xb5, + 0xb3, 0x74, 0x84, 0x67, 0x57, 0x3d, 0x98, 0xe7, 0x90, 0x8c, 0x5a, 0x4f, + 0x4e, 0x1d, 0x97, 0xf3, 0xa1, 0x76, 0xd3, 0x3f, 0x98, 0x40, 0xf3, 0xb1, + 0x95, 0x94, 0xbd, 0xb2, 0xcf, 0xa4, 0x9b, 0x49, 0x37, 0xe9, 0x0c, 0x66, + 0x8a, 0x61, 0x35, 0x6b, 0xc9, 0x0b, 0x2a, 0xf9, 0x1a, 0xfc, 0x3a, 0xf2, + 0x07, 0x0e, 0xb3, 0x1b, 0xa2, 0x37, 0x87, 0x3d, 0x1a, 0xf1, 0x05, 0xa3, + 0x63, 0x29, 0x1f, 0xed, 0x28, 0x0a, 0xff, 0x75, 0x19, 0x0f, 0x22, 0x73, + 0xaf, 0x26, 0xc5, 0x49, 0xd5, 0xba, 0x23, 0xa6, 0x39, 0xf1, 0xa5, 0xfb, + 0x32, 0x67, 0xfa, 0x75, 0xdf, 0xc1, 0xd7, 0xf7, 0x1c, 0x7e, 0xc7, 0xe7, + 0x5c, 0xfc, 0x3a, 0xc8, 0x73, 0x4b, 0x5b, 0x34, 0xeb, 0x2c, 0xeb, 0xb6, + 0xd8, 0x44, 0x4b, 0xf0, 0x5b, 0xa8, 0x6e, 0x3d, 0xf4, 0x42, 0xff, 0xbb, + 0x0b, 0xc9, 0xa0, 0x67, 0x3a, 0xff, 0xef, 0x8e, 0xd0, 0xf6, 0x3f, 0xc1, + 0xfc, 0xeb, 0xbf, 0x83, 0xab, 0x0f, 0x73, 0xf4, 0x6a, 0xc4, 0xc4, 0x3f, + 0x5a, 0x04, 0x25, 0x2f, 0xfe, 0x11, 0x89, 0xc7, 0x13, 0x64, 0x6d, 0x9d, + 0x7a, 0x37, 0xd1, 0xd4, 0xe7, 0xc3, 0xa4, 0x5b, 0xcf, 0xc8, 0x3a, 0xfc, + 0x9b, 0x6e, 0x3f, 0x9d, 0x52, 0x3c, 0x35, 0x8d, 0x5f, 0xf7, 0xd7, 0x0e, + 0xb1, 0x70, 0xae, 0x75, 0xec, 0xdd, 0x93, 0xaf, 0x6f, 0xfe, 0x70, 0xf6, + 0x44, 0xf2, 0xfb, 0x66, 0x72, 0x47, 0x5e, 0x0b, 0x89, 0xd4, 0x86, 0xf5, + 0xc8, 0xef, 0xff, 0xa3, 0xe3, 0xf3, 0x8f, 0xfc, 0x30, 0xcb, 0x2c, 0x9d, + 0x50, 0x9b, 0x03, 0xbd, 0xe9, 0xc4, 0x03, 0xf4, 0xa8, 0x6e, 0x2f, 0x61, + 0xce, 0x76, 0xf9, 0x46, 0x4a, 0x18, 0x4e, 0xe4, 0x24, 0xdb, 0x0d, 0x4d, + 0xce, 0xd2, 0x53, 0x02, 0xba, 0x2c, 0xd0, 0xb9, 0xe1, 0xba, 0xe1, 0x59, + 0xd8, 0x54, 0xbd, 0x2b, 0xd7, 0xf3, 0x21, 0x8f, 0x3f, 0x50, 0x97, 0xf4, + 0x78, 0x97, 0xc8, 0x2d, 0x83, 0xaf, 0xe6, 0x5f, 0x9c, 0x7d, 0xce, 0xbf, + 0xff, 0x6b, 0x9c, 0x49, 0xb5, 0xc8, 0xf2, 0x35, 0x02, 0x75, 0x2d, 0x14, + 0x42, 0x3e, 0xc9, 0x75, 0xf2, 0xfd, 0x1a, 0x3a, 0xff, 0x7a, 0x00, 0xde, + 0xa7, 0x0e, 0xbf, 0xb1, 0xbd, 0x8d, 0xe4, 0x75, 0xfc, 0xbd, 0x22, 0x9e, + 0x64, 0xeb, 0xf4, 0x6f, 0xd8, 0x91, 0xd4, 0x28, 0xb5, 0xf1, 0x97, 0xd2, + 0xdd, 0xa2, 0xfb, 0xb7, 0xf1, 0xd7, 0xef, 0x38, 0x83, 0x0e, 0xbf, 0xda, + 0xc5, 0xa7, 0xba, 0xe7, 0x5a, 0x30, 0xfb, 0x44, 0x5f, 0xc4, 0xb7, 0xd2, + 0xf8, 0xb4, 0x3a, 0xf6, 0xd7, 0x20, 0xeb, 0xfd, 0xc4, 0x98, 0x73, 0x63, + 0x9d, 0x76, 0xfa, 0xf8, 0x7e, 0x90, 0x47, 0xc1, 0xeb, 0xfe, 0x18, 0x79, + 0xfb, 0x1c, 0xfc, 0xeb, 0x9f, 0x61, 0xd7, 0xf4, 0x85, 0x25, 0xdc, 0x3a, + 0xfd, 0x3a, 0x72, 0x24, 0x75, 0x4c, 0x7d, 0x3c, 0x17, 0x12, 0xbb, 0xec, + 0x0a, 0x28, 0x75, 0xff, 0xe7, 0x4f, 0x47, 0xb5, 0xd7, 0x4e, 0x80, 0xeb, + 0xe1, 0x10, 0x48, 0xeb, 0xff, 0x76, 0x39, 0xf8, 0xe3, 0x2f, 0xf9, 0xd7, + 0xb3, 0x26, 0x3a, 0xd9, 0xd3, 0xda, 0xfc, 0xfe, 0xfe, 0x07, 0x00, 0xb7, + 0x13, 0xaf, 0x97, 0x19, 0x39, 0xd7, 0xec, 0xd8, 0x31, 0xb9, 0xd4, 0x87, + 0x93, 0xa2, 0x1b, 0xe8, 0x1f, 0x34, 0xeb, 0x40, 0x55, 0x48, 0x64, 0x28, + 0x78, 0x5f, 0xd2, 0x17, 0x47, 0x17, 0xad, 0x14, 0x79, 0xd7, 0x6c, 0x86, + 0xfe, 0xd6, 0x2d, 0x3b, 0x07, 0x5e, 0xde, 0x5a, 0x3a, 0xb7, 0x3c, 0x8e, + 0x15, 0xde, 0xd7, 0xec, 0x9d, 0x50, 0x78, 0x38, 0x47, 0x7c, 0x07, 0xe4, + 0x8e, 0xbe, 0x80, 0x2a, 0x74, 0x55, 0xfa, 0x4c, 0x32, 0xcb, 0x27, 0x50, + 0x9e, 0x88, 0x09, 0x6f, 0x9f, 0xcb, 0xf1, 0xd4, 0x14, 0x5a, 0x63, 0x97, + 0xe4, 0x35, 0x0b, 0xe7, 0xd8, 0x60, 0x90, 0xd6, 0x5c, 0x2b, 0x9e, 0x14, + 0xdf, 0xca, 0xcd, 0x18, 0xc4, 0xc1, 0x0d, 0x4b, 0xca, 0xca, 0xaf, 0x54, + 0x1d, 0x7a, 0x42, 0xe7, 0x5b, 0x75, 0x64, 0xf1, 0x60, 0xae, 0xfe, 0x8e, + 0x4f, 0x1c, 0x9c, 0xeb, 0xf0, 0x3f, 0xc1, 0x69, 0xd7, 0xb9, 0x13, 0x1d, + 0x7c, 0x82, 0xf3, 0x1d, 0x7f, 0xbd, 0x9f, 0x62, 0x64, 0xd1, 0xd5, 0x24, + 0x62, 0xf0, 0xb9, 0x64, 0xfd, 0x1c, 0xd8, 0x41, 0x7f, 0xd0, 0x9d, 0x85, + 0xcf, 0x8c, 0x9d, 0x7f, 0x47, 0x52, 0x77, 0x13, 0xaf, 0xfa, 0x71, 0xc9, + 0x77, 0x3f, 0xd1, 0xd7, 0xfe, 0xc1, 0xde, 0x5a, 0xe0, 0x23, 0xf3, 0xaf, + 0xd9, 0xed, 0x62, 0x87, 0x52, 0x1f, 0x32, 0xcf, 0xef, 0x06, 0x36, 0x1d, + 0x7f, 0xfd, 0x82, 0x30, 0xc8, 0x46, 0x37, 0x92, 0x09, 0xd7, 0xff, 0x9f, + 0xe4, 0xd2, 0x8e, 0x4f, 0xf1, 0x9c, 0xe9, 0xd4, 0x14, 0x5c, 0xf4, 0x74, + 0x53, 0x2f, 0xf9, 0x7d, 0xcf, 0x60, 0x39, 0x39, 0xd7, 0xfd, 0x1e, 0xce, + 0x35, 0xdd, 0xa6, 0x8b, 0xe2, 0xfd, 0x9c, 0x8d, 0xe4, 0x75, 0xee, 0xc2, + 0xda, 0x7d, 0x5e, 0x43, 0xbf, 0xff, 0x0b, 0x7e, 0x76, 0x13, 0x88, 0xb4, + 0xdb, 0x85, 0x9d, 0x79, 0xf9, 0x39, 0xa2, 0xff, 0xa8, 0x45, 0x9e, 0x19, + 0xb5, 0x5e, 0xff, 0xff, 0x75, 0xf4, 0x91, 0xaf, 0x9e, 0xee, 0x2f, 0x1a, + 0xfc, 0x3a, 0xe8, 0xda, 0x3a, 0xfb, 0x5a, 0x75, 0x9d, 0x5d, 0x44, 0xcf, + 0xec, 0x1e, 0x18, 0xbf, 0xff, 0xa4, 0xe1, 0x6f, 0x50, 0x73, 0x63, 0xcb, + 0x48, 0x13, 0xaf, 0xfa, 0x17, 0xf0, 0x39, 0x9f, 0xe8, 0xeb, 0xfe, 0x4c, + 0x10, 0xa8, 0x99, 0xc3, 0xa9, 0x0f, 0xc3, 0x68, 0xea, 0xfe, 0x7e, 0x6f, + 0x2c, 0xf1, 0xd7, 0xfe, 0xf6, 0x93, 0x9e, 0x10, 0x3c, 0x8e, 0xbf, 0xfc, + 0xb8, 0xdb, 0xc0, 0x0e, 0x66, 0xc8, 0xdc, 0xeb, 0xff, 0x46, 0x73, 0x39, + 0xfa, 0xd3, 0x47, 0x5e, 0x7d, 0xf6, 0x8e, 0xbf, 0x9f, 0xda, 0x8c, 0x9c, + 0xea, 0x84, 0xcf, 0xb0, 0xb5, 0x0f, 0x45, 0x33, 0x61, 0xeb, 0x23, 0xf7, + 0xfc, 0x08, 0x5e, 0xb1, 0x70, 0xae, 0x75, 0xff, 0xda, 0xc1, 0xf6, 0xbe, + 0xec, 0x8c, 0xdc, 0xeb, 0xfe, 0x67, 0xec, 0xfa, 0xc5, 0xc2, 0xb9, 0xd7, + 0x93, 0xa8, 0x75, 0xf4, 0xb8, 0x19, 0x1d, 0x7c, 0xbf, 0x24, 0xe7, 0x56, + 0x1e, 0x22, 0x11, 0x5f, 0xfd, 0xb3, 0xca, 0x40, 0xcb, 0x3a, 0x8b, 0x3a, + 0xe9, 0xfc, 0x75, 0xfe, 0xd9, 0xd7, 0x94, 0x60, 0x9d, 0x50, 0x79, 0x38, + 0x2f, 0x7f, 0x63, 0x3f, 0x7a, 0xfe, 0x3a, 0xff, 0xfd, 0xef, 0xb2, 0x8d, + 0x88, 0x3f, 0xf1, 0x21, 0x78, 0x55, 0xf7, 0x7e, 0xef, 0xe3, 0xaf, 0xd8, + 0xbc, 0x4d, 0x87, 0x5e, 0x9e, 0x65, 0x73, 0xaa, 0x74, 0x79, 0xe1, 0x7b, + 0x55, 0xd0, 0x94, 0x04, 0xf7, 0x7b, 0x0e, 0xbf, 0x71, 0x27, 0x75, 0x9a, + 0x61, 0x3b, 0xef, 0x02, 0x1c, 0xd3, 0x09, 0xdd, 0xfc, 0x1a, 0x81, 0x3b, + 0xfc, 0x2e, 0xa7, 0xa3, 0x9f, 0x9a, 0x81, 0x3b, 0xfd, 0xac, 0xea, 0x68, + 0x13, 0x9a, 0x61, 0x3b, 0xb0, 0x26, 0x98, 0x4e, 0xe6, 0x59, 0x3c, 0xc2, + 0x75, 0x89, 0xa5, 0xee, 0x68, 0x85, 0xab, 0x23, 0xd2, 0x06, 0xc4, 0x06, + 0x48, 0xad, 0xe2, 0xcc, 0x26, 0x60, 0xf9, 0xec, 0x9b, 0xa7, 0xee, 0xcc, + 0x78, 0xf5, 0x0b, 0x99, 0xe8, 0x7f, 0xd5, 0xe7, 0x20, 0x18, 0x47, 0x6a, + 0x31, 0x3f, 0x4a, 0x40, 0xbc, 0x3f, 0xac, 0xeb, 0xfe, 0x80, 0x78, 0x53, + 0x67, 0xd5, 0x9d, 0x78, 0x73, 0x58, 0x7a, 0xfc, 0x1c, 0xbc, 0x1f, 0xe6, + 0x3a, 0xa1, 0x99, 0xc9, 0x3c, 0x27, 0xc3, 0x0d, 0xac, 0x2f, 0x6c, 0x6a, + 0xc9, 0x0c, 0x79, 0x8c, 0x79, 0x0c, 0xae, 0xc6, 0xc4, 0x2a, 0xfa, 0x3a, + 0xf4, 0xe8, 0xb6, 0xc8, 0x66, 0x7d, 0x31, 0xbf, 0x07, 0x38, 0x8a, 0x1d, + 0x7f, 0x76, 0x3e, 0x8e, 0xff, 0x9d, 0x7e, 0xf6, 0x4c, 0x8b, 0x3a, 0xfd, + 0x1b, 0xff, 0xfc, 0x1d, 0x50, 0x7a, 0x02, 0x4f, 0x7e, 0x8d, 0x90, 0x3e, + 0x3a, 0xfc, 0x9b, 0x3c, 0x93, 0x9d, 0x7e, 0x79, 0x7b, 0x1a, 0x75, 0xf8, + 0x73, 0xee, 0x4c, 0x75, 0xff, 0xec, 0xff, 0x5d, 0x4f, 0x9b, 0xca, 0x32, + 0x73, 0xaf, 0xfb, 0xae, 0xbe, 0xa4, 0x6f, 0x23, 0xaf, 0xef, 0xa3, 0x2d, + 0xb7, 0x9c, 0xea, 0x92, 0x2d, 0xd1, 0x37, 0xf3, 0x8a, 0x9d, 0x3a, 0x50, + 0x90, 0x34, 0x9f, 0x85, 0x22, 0x4d, 0xe8, 0x6f, 0xdf, 0xfb, 0x1f, 0xb3, + 0x20, 0xf7, 0x37, 0x3a, 0xfe, 0xfe, 0x69, 0x47, 0xb4, 0x75, 0xff, 0xff, + 0xfb, 0x3b, 0x83, 0xfe, 0x0f, 0xbb, 0x9d, 0x8c, 0x99, 0x39, 0x37, 0x53, + 0x7f, 0x1d, 0x7c, 0x31, 0x8c, 0x9d, 0x7d, 0x1b, 0xe9, 0xce, 0xa8, 0x6c, + 0x97, 0x67, 0x4c, 0x09, 0xc6, 0x53, 0x43, 0xd2, 0x1e, 0x4a, 0xe4, 0xef, + 0x28, 0x94, 0x57, 0x7c, 0x7a, 0x02, 0xfd, 0x90, 0x82, 0xfa, 0x41, 0x7f, + 0xfc, 0x83, 0x8b, 0x8f, 0xa2, 0x09, 0x0e, 0x2c, 0xeb, 0xfe, 0x0a, 0x60, + 0x82, 0x59, 0xa3, 0xaf, 0xfb, 0xa9, 0x2e, 0xbc, 0x91, 0x67, 0x5f, 0xfb, + 0x48, 0x3b, 0xcb, 0xc9, 0xa4, 0x3a, 0xb0, 0xfd, 0x3c, 0x6f, 0x7e, 0xd2, + 0xe0, 0x30, 0x75, 0x49, 0x33, 0xec, 0x4d, 0x5c, 0x2a, 0xbc, 0x43, 0x7c, + 0x31, 0xc9, 0x1d, 0x7f, 0xdd, 0x89, 0x20, 0x88, 0x37, 0x3a, 0xff, 0xa3, + 0x3d, 0xf7, 0xff, 0xe3, 0x73, 0xad, 0xc8, 0x44, 0x9e, 0x10, 0x2c, 0xde, + 0xff, 0xff, 0xf7, 0x5d, 0x3d, 0x20, 0x0f, 0xb5, 0xd7, 0x97, 0xd1, 0x86, + 0xf2, 0x24, 0x75, 0xff, 0xb5, 0xf7, 0xc8, 0x20, 0x96, 0x68, 0xea, 0x57, + 0x45, 0xb7, 0x5d, 0xef, 0xff, 0xec, 0xdf, 0x34, 0xe3, 0xd4, 0x8f, 0x74, + 0x0e, 0xb3, 0xaa, 0x13, 0x68, 0x78, 0x75, 0x09, 0x35, 0xfc, 0x20, 0x5a, + 0x76, 0x0e, 0xbf, 0xff, 0x38, 0xf9, 0xdf, 0xa3, 0x1e, 0xd3, 0x39, 0xd3, + 0xaf, 0xfd, 0x3b, 0x8e, 0xbd, 0xd4, 0x8d, 0x1d, 0x7f, 0xd1, 0xfe, 0x82, + 0x07, 0xe4, 0x8e, 0xbd, 0xcd, 0x68, 0xf1, 0x01, 0xdf, 0x35, 0xdd, 0xa6, + 0x88, 0x0d, 0x83, 0x53, 0x7f, 0x72, 0x3b, 0x1f, 0x32, 0x48, 0xa0, 0xe3, + 0x15, 0x3a, 0x64, 0x7f, 0x61, 0xbb, 0x5f, 0xa7, 0x3f, 0xe8, 0xdd, 0x6f, + 0x6c, 0x8e, 0x9d, 0x58, 0xa8, 0x49, 0x23, 0xca, 0xfa, 0x57, 0x7b, 0xae, + 0xae, 0x75, 0xf4, 0x7f, 0xb7, 0x87, 0x57, 0xe7, 0x85, 0xe1, 0xeb, 0xe1, + 0xf7, 0xe0, 0x3a, 0xfc, 0xb5, 0x65, 0x59, 0x56, 0x55, 0x83, 0xaf, 0xff, + 0xe9, 0x66, 0x93, 0x9c, 0x45, 0xfd, 0xf7, 0x71, 0x9f, 0x1d, 0x58, 0x8b, + 0xb4, 0x22, 0x73, 0xcb, 0xff, 0xcc, 0xe0, 0xfb, 0x06, 0x59, 0xaf, 0xab, + 0x3a, 0xff, 0xf4, 0xb3, 0x79, 0x7d, 0x8f, 0xd8, 0x65, 0x96, 0x4a, 0xbf, + 0x2d, 0x9c, 0x4d, 0x87, 0x5e, 0x96, 0x0c, 0xc7, 0xf7, 0xf5, 0x4a, 0xa1, + 0x1f, 0x4f, 0x0c, 0x5a, 0x85, 0x45, 0x7d, 0x86, 0xf0, 0xc6, 0x4f, 0x7f, + 0xc8, 0x32, 0xd2, 0xb5, 0x56, 0x15, 0x95, 0x60, 0xeb, 0xe9, 0xb5, 0x93, + 0x1d, 0x7e, 0xfe, 0x3d, 0x8a, 0xe7, 0x5f, 0xe8, 0xce, 0x35, 0xdd, 0xa6, + 0x88, 0x26, 0xff, 0xa3, 0xd9, 0xc6, 0xbb, 0xb4, 0xd1, 0x7c, 0xde, 0x1c, + 0xd0, 0x51, 0x00, 0xd3, 0xda, 0x14, 0x6e, 0xec, 0x85, 0x55, 0xff, 0xd1, + 0xd4, 0x53, 0x39, 0x3a, 0xc1, 0xb9, 0xd5, 0x89, 0xb7, 0xa4, 0x60, 0x1d, + 0x29, 0xbf, 0xc0, 0xee, 0xdf, 0x51, 0xbd, 0x3a, 0xff, 0xd3, 0xbe, 0xfb, + 0x79, 0xe1, 0x7d, 0x87, 0x5f, 0xff, 0x67, 0xa0, 0x7d, 0xac, 0xc5, 0x14, + 0x79, 0x1d, 0x7f, 0xec, 0x0c, 0x4a, 0x3b, 0x9f, 0xb9, 0xd7, 0xf3, 0xc8, + 0x12, 0x70, 0x9d, 0x79, 0x96, 0x59, 0x2a, 0xfd, 0xdc, 0x6b, 0xf0, 0xa6, + 0x0b, 0xfb, 0xff, 0xfd, 0x37, 0x23, 0x67, 0xc5, 0x1f, 0xe7, 0xd9, 0xb5, + 0xf3, 0x37, 0xf1, 0xd5, 0xe4, 0x52, 0xfd, 0x36, 0xbf, 0xfc, 0x9c, 0x4f, + 0x03, 0x3c, 0xeb, 0xc1, 0x3a, 0xa7, 0x54, 0x50, 0xd4, 0x35, 0xa7, 0x7e, + 0x78, 0x30, 0xf0, 0xf1, 0x2d, 0xff, 0x97, 0x1b, 0xe8, 0x72, 0x7f, 0xb2, + 0x3a, 0xff, 0xff, 0x27, 0x5c, 0x77, 0x97, 0xd9, 0x40, 0xc9, 0xd7, 0x81, + 0x3a, 0xff, 0xf6, 0x67, 0x43, 0xd8, 0xd6, 0x75, 0x3f, 0x3a, 0xff, 0x29, + 0xf2, 0x69, 0x47, 0x34, 0x75, 0x4e, 0x99, 0x04, 0x90, 0x42, 0xc0, 0x89, + 0x17, 0xf2, 0xbe, 0x4b, 0xb1, 0xc3, 0xaf, 0xf7, 0xa1, 0x3a, 0xa4, 0x6e, + 0x75, 0xff, 0xed, 0xc7, 0xe3, 0x7a, 0x9f, 0xff, 0x1c, 0x91, 0xd5, 0x08, + 0xb0, 0x42, 0xff, 0xa6, 0x77, 0xca, 0xfa, 0x96, 0xc3, 0xaf, 0xff, 0x44, + 0xff, 0x7b, 0x1b, 0xfb, 0x27, 0x10, 0x9d, 0x4e, 0x7e, 0x82, 0x4f, 0x7f, + 0xa3, 0x07, 0xca, 0x86, 0x5a, 0x75, 0xfe, 0xee, 0x6c, 0xf9, 0xa9, 0x34, + 0xeb, 0x03, 0x47, 0xdb, 0xe3, 0x6b, 0xfc, 0xe3, 0xf3, 0xef, 0x3a, 0xe7, + 0x5f, 0xb3, 0x8f, 0xbb, 0x27, 0x5f, 0xff, 0xe9, 0xf1, 0x91, 0xc0, 0xf1, + 0x01, 0x38, 0x7b, 0x03, 0x39, 0xd5, 0x3a, 0x22, 0xb4, 0x51, 0x79, 0x96, + 0x59, 0x2a, 0xff, 0x7d, 0xfe, 0x07, 0x37, 0xf1, 0x4c, 0x17, 0xf7, 0xff, + 0xf2, 0xa7, 0xe3, 0x7a, 0x81, 0x0e, 0x33, 0xf3, 0xda, 0xc9, 0xce, 0xae, + 0xa2, 0xa8, 0x08, 0xb4, 0x89, 0x88, 0x3c, 0x3b, 0x6a, 0x76, 0x50, 0x5c, + 0xa3, 0xbc, 0x09, 0xaa, 0x4a, 0x5e, 0xe4, 0x6f, 0xeb, 0x87, 0x77, 0x61, + 0x48, 0x30, 0x8d, 0xd1, 0x47, 0xa3, 0xcf, 0xbf, 0xf6, 0x20, 0xce, 0xe3, + 0xec, 0x59, 0xd7, 0xfe, 0xea, 0x32, 0x1e, 0xe7, 0xb6, 0xf0, 0xeb, 0xd8, + 0x3f, 0x9d, 0x7d, 0x9e, 0x9a, 0x47, 0x5f, 0xfd, 0xb4, 0x31, 0xb5, 0xa7, + 0x1f, 0xbf, 0xe8, 0xea, 0xe9, 0xf6, 0xb9, 0x15, 0xff, 0xb3, 0xd1, 0xcd, + 0x76, 0x07, 0xc7, 0x88, 0x22, 0xff, 0x46, 0x71, 0xae, 0xed, 0x34, 0x41, + 0x0c, 0x1e, 0x4d, 0xfc, 0xfd, 0xe7, 0x11, 0x93, 0xaf, 0xe5, 0x70, 0xb2, + 0xe3, 0x23, 0xa8, 0x4f, 0x74, 0x05, 0xb7, 0xff, 0xe8, 0x0c, 0xd2, 0x41, + 0xf4, 0x7f, 0x30, 0xa4, 0xc7, 0x52, 0x8a, 0x85, 0x7b, 0x08, 0x8f, 0xda, + 0x86, 0x15, 0x9b, 0x08, 0x6f, 0xee, 0xe7, 0xbc, 0x8b, 0x3a, 0xfe, 0xf7, + 0xdc, 0xeb, 0xee, 0x75, 0x6e, 0x7b, 0x62, 0x59, 0x7f, 0xfb, 0x5a, 0x17, + 0xf3, 0xaf, 0xec, 0x4f, 0x87, 0x54, 0x1f, 0x60, 0x08, 0xaf, 0xec, 0x6f, + 0xdd, 0x9d, 0xc3, 0xae, 0x85, 0x0e, 0xbc, 0x14, 0x13, 0xaf, 0x08, 0x27, + 0x3a, 0xfd, 0xd7, 0x96, 0x09, 0xd7, 0xf2, 0x78, 0x73, 0xa8, 0x75, 0xd9, + 0xdf, 0x87, 0x9f, 0x04, 0xb7, 0x3b, 0x3f, 0x11, 0x93, 0x82, 0xdd, 0x1a, + 0xf3, 0x5d, 0x49, 0x36, 0x4c, 0x21, 0x18, 0x7c, 0xdf, 0xff, 0xde, 0xee, + 0x6b, 0x59, 0x80, 0xe4, 0xf8, 0x01, 0xf1, 0xd7, 0xfd, 0xd8, 0xe7, 0x86, + 0x33, 0x73, 0xaf, 0xff, 0xf9, 0x27, 0x89, 0x6b, 0x9c, 0x4d, 0xe6, 0x93, + 0xf1, 0x79, 0xb9, 0xd7, 0xbb, 0x82, 0x14, 0x50, 0x74, 0xde, 0x91, 0x32, + 0xdf, 0x43, 0xea, 0xff, 0xcd, 0xec, 0x67, 0x25, 0xa0, 0x2c, 0xeb, 0x93, + 0x47, 0x5f, 0xf6, 0x4e, 0xfe, 0xff, 0xe8, 0xc8, 0xeb, 0xfb, 0xea, 0xf4, + 0xcb, 0xee, 0x75, 0x42, 0x39, 0xf0, 0xa1, 0x43, 0xee, 0x0a, 0xf8, 0xee, + 0xf7, 0x33, 0xa7, 0x5e, 0xd2, 0x2c, 0xeb, 0x47, 0x0d, 0xb7, 0x86, 0xef, + 0x92, 0x64, 0x64, 0xeb, 0xff, 0x96, 0xfb, 0xfd, 0xf2, 0x72, 0x00, 0xa9, + 0x3a, 0xff, 0xfc, 0x09, 0xc6, 0x33, 0xac, 0x47, 0xb3, 0xa0, 0xe1, 0xd7, + 0xde, 0xd7, 0xdd, 0x05, 0x18, 0x38, 0x45, 0xf5, 0x2a, 0xfd, 0xa5, 0xe7, + 0xb4, 0x75, 0xf9, 0xe4, 0x29, 0x07, 0x5f, 0xd0, 0xe3, 0xec, 0x13, 0xaa, + 0x49, 0xd3, 0x64, 0x39, 0xd1, 0x2d, 0x64, 0xe2, 0x49, 0x7f, 0x37, 0xa9, + 0xb6, 0x8a, 0x1d, 0x7f, 0xf9, 0x3f, 0x8d, 0x2e, 0x13, 0x9c, 0x46, 0x4e, + 0xbe, 0x57, 0xee, 0x4e, 0x75, 0xfe, 0x80, 0xe7, 0x93, 0xa0, 0x3a, 0xcb, + 0x83, 0xd6, 0x09, 0x2d, 0xff, 0xff, 0x96, 0xe3, 0xfc, 0x93, 0x40, 0x5f, + 0x52, 0x3d, 0xd0, 0x3a, 0xce, 0xbf, 0xfe, 0x10, 0x7a, 0x49, 0xff, 0x5d, + 0x3c, 0xeb, 0x3a, 0xef, 0x8a, 0xe7, 0x5f, 0xff, 0x9d, 0x3c, 0x81, 0xc0, + 0xe7, 0x91, 0x69, 0xc3, 0xaf, 0x71, 0xf5, 0x88, 0xba, 0xe2, 0x77, 0x46, + 0xee, 0x4f, 0x3a, 0x6c, 0xa0, 0x8c, 0x96, 0xe9, 0x41, 0xd7, 0xff, 0xa7, + 0x0f, 0x63, 0xb9, 0xbf, 0xf9, 0xed, 0x1d, 0x4e, 0x7c, 0x20, 0x15, 0xa0, + 0xab, 0x11, 0xc3, 0x04, 0x84, 0xfb, 0xc7, 0x18, 0x30, 0x95, 0xbf, 0xb9, + 0x13, 0xa0, 0xf8, 0xeb, 0xc1, 0xfa, 0xb3, 0xaf, 0xc3, 0x01, 0xc9, 0x8e, + 0xbe, 0xd0, 0x38, 0xa1, 0xd7, 0xe8, 0xef, 0xa2, 0x47, 0x5f, 0x04, 0x1e, + 0xd4, 0x1f, 0x7e, 0xe4, 0xdf, 0x91, 0xdf, 0xbf, 0xc5, 0xc7, 0x4e, 0xbc, + 0xa9, 0xee, 0x1d, 0x41, 0x4d, 0x1f, 0x0b, 0x12, 0x11, 0xa2, 0x90, 0x02, + 0x7b, 0xdc, 0xfb, 0xa3, 0xae, 0x85, 0x68, 0x75, 0xff, 0x9c, 0x5b, 0x9c, + 0x6b, 0xbb, 0x4d, 0x10, 0x8d, 0xd2, 0x9c, 0xea, 0x84, 0x4c, 0x7e, 0x3c, + 0x01, 0xbd, 0x89, 0x17, 0xff, 0xff, 0xbb, 0x80, 0xe2, 0x9d, 0x4d, 0xe3, + 0xc0, 0xe8, 0xe6, 0xfe, 0x03, 0xe8, 0xeb, 0xff, 0xb3, 0x7f, 0xbe, 0x41, + 0x04, 0xb3, 0x47, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x67, 0x17, + 0x0c, 0x0c, 0xf1, 0xc0, 0xe0, 0xe7, 0xb4, 0x8d, 0xc1, 0xfb, 0x3e, 0x72, + 0x34, 0x2e, 0xa6, 0xb1, 0x3f, 0xfc, 0x1f, 0x8b, 0x86, 0x06, 0x78, 0xe1, + 0xd5, 0x09, 0xa7, 0xe2, 0x2d, 0xff, 0xde, 0x71, 0x9f, 0x79, 0x0c, 0x66, + 0x8e, 0xbf, 0xf7, 0xdc, 0xeb, 0xad, 0x86, 0x59, 0x64, 0xeb, 0xff, 0xf6, + 0x37, 0xb0, 0x21, 0x14, 0x9f, 0x05, 0x14, 0x3a, 0xe7, 0x79, 0xd1, 0x2d, + 0x24, 0x4b, 0xff, 0xfa, 0x61, 0x8f, 0xf4, 0xde, 0xa7, 0x26, 0x18, 0xff, + 0x47, 0x5f, 0xfd, 0xee, 0xa6, 0xce, 0xbc, 0xb9, 0x0a, 0x1d, 0x7f, 0x03, + 0xc8, 0x01, 0x50, 0xeb, 0xfb, 0x19, 0xc1, 0x07, 0xe7, 0x5f, 0xa5, 0x9e, + 0x8f, 0xce, 0xba, 0x17, 0x39, 0xea, 0x6e, 0x5b, 0x7f, 0xff, 0xf7, 0xeb, + 0x79, 0x75, 0xd3, 0xc8, 0x1c, 0x0e, 0x79, 0x16, 0x9c, 0x3a, 0xb4, 0x89, + 0xe0, 0x17, 0xdf, 0xa7, 0x5c, 0x06, 0x0e, 0xa9, 0x2e, 0x7e, 0x86, 0x3c, + 0x8d, 0xc8, 0xa6, 0x86, 0xcf, 0x0b, 0xba, 0xbb, 0xa4, 0x6f, 0x46, 0x3f, + 0xf4, 0x8e, 0xff, 0x46, 0xb5, 0x13, 0xe3, 0x27, 0x5f, 0xee, 0xe2, 0xf3, + 0xa0, 0x13, 0xa8, 0x27, 0xc9, 0xe3, 0x3a, 0xc4, 0xc7, 0x1e, 0x1f, 0x57, + 0x99, 0x65, 0x92, 0xaf, 0xfb, 0x3f, 0x7e, 0x66, 0xcc, 0x09, 0x4c, 0x17, + 0xf7, 0x32, 0xc9, 0x57, 0x99, 0x65, 0x92, 0xaf, 0xe7, 0x9c, 0x3d, 0x8d, + 0x14, 0xc1, 0x7f, 0x42, 0x8b, 0xd6, 0x52, 0x76, 0xcd, 0xef, 0xcd, 0x40, + 0xfd, 0x59, 0x4c, 0x1b, 0x3b, 0xcc, 0xb2, 0xc9, 0x57, 0xb5, 0x1c, 0x29, + 0x82, 0xfe, 0xf9, 0xc7, 0x7f, 0x1d, 0x6f, 0xd1, 0x14, 0xbe, 0x59, 0x64, + 0xae, 0xfe, 0x08, 0xc4, 0x9d, 0xa7, 0x5f, 0xb4, 0x09, 0xf6, 0xc4, 0xeb, + 0xf0, 0x53, 0x64, 0x04, 0xeb, 0xec, 0x1c, 0x57, 0x3a, 0xb8, 0x79, 0x4b, + 0x28, 0xa4, 0x44, 0xbf, 0xd7, 0x5b, 0xff, 0xba, 0xf2, 0x17, 0x52, 0x61, + 0x49, 0x8e, 0xbf, 0xfb, 0x39, 0x3c, 0x6f, 0xa4, 0x1c, 0xfc, 0xeb, 0xfb, + 0xb9, 0xb3, 0x3d, 0xa3, 0xa9, 0xa8, 0xb6, 0xfd, 0x13, 0xc8, 0x95, 0xc4, + 0xf3, 0x7b, 0x0c, 0x21, 0x86, 0xd5, 0xd3, 0xf8, 0xea, 0x85, 0x4a, 0xb9, + 0x28, 0x10, 0x4e, 0xaf, 0x6e, 0xad, 0x55, 0x83, 0xaf, 0xff, 0x62, 0xbb, + 0x8f, 0xf8, 0xd8, 0xec, 0x2c, 0xeb, 0xed, 0x75, 0x26, 0x2a, 0xff, 0x9f, + 0x7f, 0x64, 0xc0, 0xe2, 0x87, 0x59, 0xa8, 0x7b, 0xa0, 0x22, 0xbf, 0xc3, + 0x9b, 0xcb, 0x48, 0xa1, 0xd7, 0xce, 0xfc, 0x50, 0xea, 0xf8, 0x7a, 0x93, + 0x99, 0xdf, 0xf6, 0x63, 0x7f, 0x8c, 0xde, 0x47, 0x5f, 0x43, 0xaf, 0x61, + 0x57, 0xff, 0x75, 0x1f, 0xff, 0xe3, 0xf8, 0xee, 0x8e, 0xbf, 0xbb, 0x8b, + 0x5b, 0xc8, 0xeb, 0xcc, 0xb2, 0xc9, 0x57, 0xf8, 0x7d, 0xd4, 0x81, 0x9c, + 0xa6, 0x0b, 0xfb, 0xd1, 0xfe, 0x49, 0x11, 0x98, 0x97, 0x5e, 0x4c, 0x13, + 0xec, 0x34, 0x6d, 0x8d, 0x4d, 0x45, 0x71, 0x93, 0x5f, 0xe8, 0xfb, 0xce, + 0x27, 0xb4, 0x75, 0x42, 0xb5, 0xb9, 0x14, 0x6f, 0x0a, 0x74, 0x7b, 0x98, + 0x97, 0xb1, 0xc4, 0x89, 0x7d, 0xfb, 0xfc, 0x4e, 0xa8, 0x75, 0xff, 0xf6, + 0x36, 0x05, 0xfd, 0xa0, 0x81, 0xf9, 0x23, 0xab, 0x73, 0xf5, 0x59, 0x45, + 0xe6, 0xc6, 0x8e, 0xbf, 0xfb, 0xec, 0xb3, 0xaf, 0xd4, 0xe7, 0x20, 0xea, + 0xc3, 0xdf, 0xfc, 0x6e, 0xfd, 0x1e, 0xd6, 0xcc, 0x3a, 0xfc, 0x0e, 0x29, + 0xd4, 0x3a, 0xa1, 0x1e, 0x83, 0x08, 0x2f, 0x11, 0x6d, 0x94, 0x5f, 0xff, + 0x26, 0xcc, 0x10, 0x8b, 0xb3, 0x82, 0xea, 0x1d, 0x7f, 0xff, 0xc1, 0xea, + 0x33, 0x9b, 0x48, 0xb7, 0xf6, 0x81, 0x2c, 0xdf, 0xc7, 0x56, 0x22, 0xe1, + 0xd3, 0xaf, 0xfa, 0x66, 0xf5, 0x17, 0x1c, 0x50, 0xeb, 0xf4, 0xff, 0x01, + 0x13, 0x1d, 0x69, 0x1d, 0x7b, 0xe8, 0xcc, 0x75, 0x48, 0xd7, 0x7e, 0x21, + 0x58, 0x8b, 0x57, 0x3a, 0xd2, 0xcd, 0x43, 0xb3, 0x78, 0x9e, 0x51, 0xec, + 0xa5, 0x22, 0x86, 0x55, 0x2e, 0x52, 0x91, 0x94, 0x85, 0xb3, 0x4e, 0xd2, + 0x52, 0xb4, 0xd2, 0xa1, 0x39, 0x29, 0x21, 0x72, 0x89, 0x7b, 0x2d, 0x79, + 0xe3, 0x9f, 0xfe, 0x1c, 0xa3, 0x3c, 0xb1, 0xa9, 0xc3, 0x0f, 0x4b, 0x91, + 0x04, 0x7b, 0x2c, 0xc3, 0xef, 0xec, 0x35, 0xaf, 0x6c, 0x81, 0x3a, 0xff, + 0xfb, 0x05, 0x8f, 0x28, 0x9b, 0xeb, 0xb9, 0xfb, 0x9d, 0x52, 0x3e, 0xd0, + 0x8e, 0x5f, 0xe7, 0x16, 0xe7, 0xba, 0x87, 0x56, 0xe7, 0xa4, 0xb2, 0x2b, + 0x2b, 0x43, 0xaf, 0xfc, 0xe3, 0xff, 0xc0, 0x81, 0xf9, 0x23, 0xaf, 0x90, + 0x67, 0x83, 0xa9, 0x5c, 0xf8, 0x38, 0x81, 0x4a, 0xbd, 0x13, 0x78, 0xed, + 0x7a, 0x06, 0x73, 0xaf, 0x93, 0xa8, 0xb3, 0xad, 0xd4, 0x37, 0x73, 0x0d, + 0xdf, 0xd0, 0xd8, 0xd7, 0x90, 0xeb, 0xfe, 0x8f, 0x75, 0xff, 0x7d, 0xf4, + 0x75, 0x04, 0xf9, 0x04, 0xae, 0xff, 0xdc, 0xff, 0xe7, 0x51, 0xa0, 0xe7, + 0xe7, 0x5e, 0x98, 0x1c, 0x3a, 0xff, 0xce, 0x9c, 0xcd, 0xd8, 0x65, 0x96, + 0x4e, 0xa8, 0x45, 0x13, 0xa1, 0xe8, 0x76, 0xff, 0xf8, 0x62, 0x5f, 0x3e, + 0xf9, 0x04, 0x12, 0xcd, 0x1d, 0x58, 0x9e, 0x6b, 0x61, 0x17, 0xd8, 0x61, + 0xfe, 0x5d, 0x7f, 0xa0, 0x64, 0x39, 0x9f, 0x9d, 0x7f, 0x67, 0x34, 0x31, + 0x39, 0xd7, 0xf3, 0xfb, 0xae, 0x3f, 0x9d, 0x7f, 0xe7, 0xf6, 0x4c, 0xf0, + 0x31, 0x31, 0xd6, 0x4e, 0x1f, 0x47, 0x4b, 0x2e, 0x6b, 0x4d, 0x18, 0x25, + 0x49, 0x1b, 0xcd, 0x84, 0xa7, 0xe4, 0xf7, 0x60, 0x9d, 0x7f, 0xfb, 0xd0, + 0x2d, 0xcf, 0x75, 0x39, 0xfb, 0x4e, 0xa0, 0x9e, 0xee, 0x0a, 0x5f, 0xe8, + 0x5e, 0xb4, 0xe3, 0x39, 0xd7, 0xda, 0xc1, 0xf1, 0xd7, 0xb6, 0xa3, 0x87, + 0x53, 0x9b, 0xe0, 0x10, 0x5e, 0xf3, 0xab, 0x9d, 0x7f, 0xbd, 0xd4, 0x63, + 0xf7, 0x43, 0xa8, 0x29, 0x81, 0x74, 0x84, 0x5c, 0x3c, 0x40, 0x01, 0xeb, + 0xee, 0xa3, 0xc8, 0xeb, 0xc1, 0x79, 0x1d, 0x70, 0x3f, 0x83, 0x77, 0x84, + 0x17, 0xfc, 0xdc, 0xf4, 0x6c, 0x41, 0xfc, 0xeb, 0xff, 0xf8, 0x11, 0xed, + 0x60, 0xfc, 0xe4, 0x20, 0x45, 0xe4, 0x75, 0xf9, 0xbd, 0xdd, 0xd5, 0xce, + 0xbf, 0xf9, 0x02, 0x20, 0xf6, 0xa0, 0x63, 0x47, 0x52, 0x23, 0xf8, 0x4e, + 0x40, 0xb3, 0xb0, 0xae, 0xff, 0xef, 0xdf, 0x99, 0xb3, 0x03, 0xc1, 0x64, + 0xeb, 0xff, 0xf8, 0x73, 0x40, 0xf9, 0x9d, 0x71, 0xc9, 0xa5, 0x1b, 0x9d, + 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x81, 0xaf, 0xe7, 0x9f, 0xf7, 0x10, 0x92, + 0xb0, 0x7d, 0xec, 0xd0, 0x30, 0xfb, 0xb6, 0xcc, 0xef, 0x75, 0xe5, 0xf1, + 0x1f, 0xc3, 0x0c, 0x9a, 0x5a, 0x6f, 0xde, 0x8d, 0x12, 0xff, 0x87, 0xff, + 0x24, 0xeb, 0x86, 0x9d, 0x7e, 0x0a, 0xb6, 0xe1, 0x56, 0xce, 0xa8, 0x54, + 0x9f, 0x91, 0xdd, 0xa1, 0x53, 0x9c, 0xdf, 0xec, 0xdf, 0xc1, 0xcc, 0x50, + 0xeb, 0xfb, 0x3d, 0x02, 0x9f, 0x9d, 0x79, 0xf9, 0x39, 0xa3, 0x05, 0xbf, + 0xf3, 0xf3, 0x07, 0xfd, 0x7b, 0x5b, 0x9d, 0x7f, 0xff, 0xff, 0x67, 0xba, + 0xe2, 0xa7, 0xcd, 0x71, 0xdf, 0xdb, 0x30, 0x3f, 0x31, 0x6e, 0x3b, 0xc8, + 0xf1, 0x05, 0xdf, 0xf9, 0xdd, 0x46, 0xb8, 0x7e, 0x28, 0xc9, 0xe2, 0x0b, + 0xbf, 0xfb, 0xa9, 0xd4, 0x81, 0xf7, 0xc5, 0x19, 0x3c, 0x41, 0x77, 0xfa, + 0x10, 0x7d, 0xf1, 0x46, 0x4f, 0x10, 0x5d, 0xfc, 0xbc, 0x0f, 0xc5, 0x19, + 0x3c, 0x41, 0x77, 0xff, 0xfc, 0xe2, 0x28, 0xbf, 0x9a, 0x6f, 0x53, 0x88, + 0xa4, 0xf8, 0xc9, 0xe2, 0x0b, 0xbb, 0x7f, 0x81, 0x4e, 0x5d, 0xa9, 0xfc, + 0x53, 0x74, 0x21, 0x3e, 0xa8, 0x55, 0x91, 0xd3, 0xf1, 0x94, 0x63, 0x7f, + 0x92, 0x14, 0xd7, 0xb5, 0xb9, 0xd7, 0xcf, 0xcf, 0xdc, 0xeb, 0xff, 0xba, + 0x9d, 0x48, 0x1f, 0x7c, 0x51, 0x93, 0xc4, 0x17, 0x7f, 0xd3, 0x69, 0xa9, + 0x3f, 0xc5, 0x19, 0x3c, 0x41, 0x77, 0xef, 0x6a, 0x17, 0xf1, 0xa8, 0x9f, + 0xfa, 0xa7, 0x7f, 0xfb, 0xe3, 0x7a, 0x8d, 0x8f, 0x6b, 0xe2, 0x8c, 0x9e, + 0x20, 0xbb, 0xff, 0xff, 0x84, 0x51, 0x7f, 0x01, 0x9f, 0x34, 0xde, 0xa7, + 0x11, 0x49, 0xf1, 0x93, 0xc4, 0x17, 0x58, 0x99, 0x26, 0xe8, 0x8e, 0xbb, + 0x7f, 0xdd, 0x4e, 0x22, 0x93, 0xe3, 0x27, 0x88, 0x2e, 0xff, 0xf9, 0xdf, + 0x79, 0x6b, 0xa8, 0x10, 0xc7, 0x20, 0xab, 0xff, 0x64, 0xa4, 0x0d, 0x70, + 0x67, 0xdb, 0x3c, 0x41, 0x74, 0xd4, 0x72, 0x71, 0x1f, 0x49, 0xd7, 0xfe, + 0x6a, 0x73, 0xcf, 0xfe, 0xbe, 0x32, 0x78, 0x82, 0xef, 0xee, 0xa7, 0x7a, + 0x9f, 0x9a, 0x00, 0xbb, 0xf6, 0x7f, 0xf1, 0x46, 0x4f, 0x10, 0x5d, 0xd9, + 0xe6, 0x9f, 0x9f, 0x4e, 0xab, 0x74, 0x77, 0xea, 0x18, 0x57, 0xf2, 0xf0, + 0x3f, 0x14, 0x64, 0xf1, 0x05, 0xdf, 0xf9, 0xbd, 0x4e, 0x22, 0x93, 0xe3, + 0x27, 0x88, 0x2e, 0xec, 0xf8, 0xe8, 0x8b, 0xd1, 0xf5, 0xfe, 0x02, 0x2d, + 0xc7, 0x79, 0x1e, 0x20, 0xbb, 0xff, 0x62, 0x6c, 0xc1, 0xc0, 0xbc, 0x8f, + 0x10, 0x5a, 0xcd, 0xfd, 0x05, 0x77, 0xf7, 0x86, 0xff, 0x9a, 0x0c, 0x7c, + 0x9a, 0x8c, 0x53, 0xd1, 0x8f, 0x82, 0x16, 0x8c, 0xb7, 0x5d, 0xfc, 0x1a, + 0x20, 0xb6, 0x11, 0x19, 0x73, 0xb4, 0xeb, 0x69, 0xac, 0x9c, 0x5f, 0xe9, + 0x2f, 0x5e, 0x36, 0xba, 0x5b, 0x47, 0x5e, 0x89, 0x6d, 0x1d, 0x50, 0x6d, + 0xc4, 0x66, 0xa7, 0x65, 0x5e, 0x84, 0xcf, 0xfa, 0x4f, 0x80, 0xbd, 0xdf, + 0xfd, 0x92, 0x1c, 0xf7, 0x53, 0x37, 0xf1, 0xd7, 0xe8, 0xf6, 0xba, 0x87, + 0x5f, 0xfb, 0x53, 0x48, 0x01, 0x9a, 0x40, 0x09, 0xd5, 0x23, 0xe8, 0xf1, + 0x35, 0xff, 0xd1, 0xbc, 0xbe, 0xaf, 0x5e, 0x8d, 0xd9, 0x3a, 0xfd, 0x2d, + 0xad, 0xa0, 0x4e, 0x75, 0xba, 0x87, 0xf0, 0xe9, 0x37, 0xee, 0x46, 0xf2, + 0xd1, 0xd5, 0x23, 0xce, 0xe1, 0x35, 0xff, 0xdf, 0x83, 0x5b, 0x79, 0xcf, + 0xd6, 0x9a, 0x3a, 0xff, 0x7e, 0x0f, 0x0c, 0x7b, 0x47, 0x57, 0xe7, 0xf9, + 0xa4, 0x9a, 0x84, 0xea, 0x72, 0x1d, 0x0f, 0x09, 0xeb, 0xf9, 0xe5, 0x1b, + 0x1f, 0xa7, 0x5f, 0x6f, 0xa8, 0xdc, 0xeb, 0xcb, 0x89, 0x1d, 0x7e, 0xc0, + 0xf4, 0x0c, 0x9d, 0x5f, 0x0f, 0x99, 0xc8, 0xc4, 0x6e, 0xf0, 0x5f, 0xc7, + 0x57, 0x0f, 0x29, 0xcb, 0xef, 0x26, 0xde, 0x1d, 0x79, 0xf9, 0xf9, 0xd6, + 0xde, 0x0d, 0xcf, 0x87, 0x6f, 0x99, 0xce, 0xb9, 0xd7, 0xca, 0x71, 0x19, + 0x3a, 0xfd, 0x3b, 0xf6, 0x15, 0xce, 0xa5, 0x60, 0xf3, 0x70, 0x8e, 0xa1, + 0x3f, 0x24, 0x86, 0xeb, 0xad, 0x7e, 0x4e, 0x2d, 0xd7, 0xff, 0x84, 0x62, + 0x75, 0xf5, 0x39, 0xc7, 0x91, 0xd7, 0xfa, 0x79, 0xe0, 0x77, 0xcf, 0x1d, + 0x58, 0x7f, 0x88, 0x91, 0x7f, 0xf7, 0x04, 0x1b, 0xf8, 0x72, 0x77, 0x13, + 0xaf, 0x3f, 0x27, 0x3a, 0xef, 0xe0, 0xeb, 0xe4, 0x85, 0xe1, 0xd4, 0x75, + 0xfc, 0xea, 0x7a, 0x39, 0xf9, 0xd4, 0x13, 0x70, 0x21, 0x57, 0xff, 0xfa, + 0x10, 0x23, 0x00, 0x6f, 0xb1, 0xa1, 0x86, 0xfd, 0x59, 0xd7, 0x7f, 0x07, + 0x5d, 0x0a, 0x1d, 0x7f, 0xd9, 0xed, 0x42, 0xfe, 0xe4, 0xc7, 0x5f, 0xed, + 0x67, 0x53, 0x40, 0x9c, 0xeb, 0x99, 0x64, 0xab, 0xfe, 0x1c, 0xd8, 0xf2, + 0xd2, 0x04, 0xea, 0x6a, 0x7e, 0x48, 0x39, 0xc1, 0x65, 0xab, 0xf4, 0x83, + 0xf6, 0x05, 0x48, 0xb0, 0x8b, 0x68, 0xe9, 0x93, 0x3f, 0xa3, 0x17, 0x99, + 0x65, 0x92, 0xac, 0xb2, 0x98, 0x2f, 0xef, 0xa6, 0x77, 0xe1, 0x4c, 0x23, + 0x7b, 0xec, 0x2f, 0xaa, 0x75, 0x6b, 0x6f, 0x2c, 0x4e, 0xfe, 0xf4, 0x67, + 0x72, 0x73, 0xae, 0xc5, 0x9d, 0x5b, 0x9e, 0x0e, 0x8b, 0x2a, 0x1b, 0xe7, + 0x19, 0x42, 0xfb, 0x25, 0x18, 0x28, 0x91, 0xbc, 0x61, 0xc9, 0x1c, 0xaf, + 0x21, 0x0b, 0xd9, 0x6f, 0x2f, 0x4a, 0xfe, 0xfd, 0x2c, 0x65, 0x29, 0xea, + 0x51, 0x57, 0xa1, 0x92, 0x09, 0x6f, 0x7b, 0x1b, 0x6f, 0xec, 0xff, 0xf4, + 0xe4, 0x8e, 0xb9, 0xb8, 0x75, 0x04, 0xf0, 0xdc, 0xba, 0xec, 0x64, 0xeb, + 0xa3, 0xc7, 0x54, 0xe6, 0xad, 0xa2, 0xd6, 0x59, 0xd5, 0x86, 0xcb, 0xc4, + 0x57, 0xfa, 0x48, 0x38, 0xb0, 0x74, 0xeb, 0xff, 0x67, 0xb5, 0xd4, 0x5b, + 0xe7, 0x0e, 0xa8, 0x3e, 0xd1, 0x31, 0xbe, 0xf9, 0xe8, 0xd8, 0x75, 0xf6, + 0x2f, 0x3c, 0x75, 0xef, 0x3a, 0x87, 0x5f, 0xff, 0xfc, 0xd7, 0x98, 0x12, + 0x03, 0x7e, 0x75, 0x3d, 0xe8, 0xde, 0x27, 0x8d, 0x1d, 0x7f, 0xff, 0xca, + 0xe2, 0xef, 0xb2, 0x25, 0xd8, 0xe4, 0xf1, 0xed, 0x3c, 0x8e, 0xbc, 0x9b, + 0xcc, 0x75, 0xfb, 0x32, 0x70, 0x68, 0xeb, 0xee, 0x0a, 0x7e, 0x75, 0xf2, + 0x35, 0xf8, 0x75, 0xd1, 0xf9, 0xd7, 0xc0, 0x9c, 0x0c, 0x74, 0xdb, 0x7d, + 0x20, 0xa4, 0x44, 0xa7, 0x55, 0xef, 0xfb, 0xaf, 0xae, 0xa4, 0xee, 0x27, + 0x5f, 0x3c, 0xff, 0x64, 0x75, 0x2a, 0x95, 0xe0, 0x43, 0xf4, 0xa1, 0x1b, + 0x84, 0x1b, 0x92, 0xa1, 0x07, 0x07, 0x1d, 0xdb, 0xf6, 0x9d, 0x0e, 0xfa, + 0x17, 0x7f, 0x48, 0xb6, 0x8d, 0xef, 0xe1, 0x00, 0x56, 0xf2, 0x3a, 0xf2, + 0x4e, 0x03, 0xaf, 0xd1, 0xfa, 0x6f, 0x87, 0x5c, 0xbd, 0x87, 0x58, 0x30, + 0x6f, 0xc4, 0x9e, 0xff, 0xf4, 0x86, 0x3e, 0x2c, 0x61, 0x4f, 0x24, 0xe7, + 0x5f, 0x9d, 0x79, 0xd5, 0x9d, 0x5b, 0x9f, 0x8f, 0x92, 0xef, 0x7b, 0x90, + 0x75, 0xfe, 0xd7, 0xb6, 0x60, 0xe0, 0x4e, 0xa8, 0x4e, 0x3a, 0x45, 0x98, + 0xb6, 0x90, 0x96, 0x59, 0x1b, 0x8d, 0xde, 0x7f, 0x9f, 0x4e, 0xbe, 0x5a, + 0xe1, 0x67, 0x5f, 0xff, 0x0c, 0xbe, 0x60, 0x53, 0x5b, 0xf8, 0x0f, 0xa3, + 0xaf, 0xf7, 0xd1, 0x7f, 0x4a, 0x14, 0x3a, 0xfb, 0x33, 0x79, 0x1d, 0x7b, + 0x49, 0x31, 0xd6, 0x50, 0x4d, 0xee, 0x88, 0x6f, 0xfe, 0x79, 0xc6, 0x37, + 0x40, 0x8c, 0x4e, 0x75, 0x70, 0xfa, 0x84, 0x9e, 0xfd, 0xf3, 0xb1, 0xc9, + 0x1d, 0x5f, 0x13, 0xb6, 0x81, 0xfc, 0x21, 0x6a, 0x8b, 0xc3, 0x6d, 0x92, + 0x1b, 0xcb, 0xd4, 0x1d, 0x7f, 0x4f, 0x34, 0x95, 0x5c, 0x9c, 0xeb, 0xe5, + 0xe3, 0xf4, 0xeb, 0xa5, 0x39, 0xd7, 0xba, 0x14, 0x3a, 0xfd, 0xdc, 0x49, + 0x68, 0xeb, 0xff, 0xee, 0xc7, 0xd6, 0x3c, 0x2f, 0xfe, 0xb5, 0x1f, 0x95, + 0x7e, 0xe3, 0x5d, 0xda, 0x78, 0x81, 0x2f, 0x6a, 0x37, 0x3a, 0xdf, 0xe1, + 0xe7, 0xee, 0x67, 0x7b, 0xc9, 0x39, 0xd7, 0xa7, 0x71, 0x3a, 0xa4, 0x99, + 0x40, 0x49, 0xb9, 0x0a, 0x25, 0x94, 0xf8, 0x72, 0xfe, 0x16, 0xba, 0x9d, + 0x43, 0xae, 0xda, 0x91, 0xd7, 0xde, 0x9d, 0xc4, 0xeb, 0xc2, 0xea, 0x1d, + 0x79, 0x44, 0xf1, 0xd7, 0xb4, 0xfe, 0x3a, 0x94, 0x36, 0xfb, 0x8e, 0x5d, + 0xf3, 0xa7, 0x5f, 0xcb, 0xf2, 0x04, 0x10, 0x75, 0xe5, 0xf9, 0xa7, 0x5b, + 0xd0, 0x79, 0x18, 0x59, 0x53, 0xa6, 0x6b, 0x83, 0x2d, 0x21, 0xea, 0x97, + 0xe4, 0x62, 0xc1, 0x77, 0x00, 0x75, 0xfe, 0x17, 0x67, 0x5a, 0x8f, 0xce, + 0xbd, 0xb6, 0xea, 0x1d, 0x7f, 0xd0, 0xb9, 0x64, 0xf8, 0x05, 0x49, 0xd7, + 0xcf, 0xe5, 0x4c, 0xe7, 0x56, 0x22, 0x05, 0x07, 0xdc, 0xf2, 0xf3, 0x2c, + 0xb2, 0x7a, 0xbe, 0xaf, 0x38, 0x84, 0xb5, 0x7d, 0x58, 0x35, 0x97, 0xec, + 0x90, 0x21, 0x43, 0xaa, 0x13, 0x83, 0x08, 0xb7, 0x21, 0x69, 0xfa, 0xcf, + 0x8e, 0x6f, 0xff, 0xd8, 0x28, 0xa3, 0x1a, 0xf7, 0x40, 0xf2, 0x94, 0x1d, + 0x53, 0xa2, 0x95, 0x45, 0x0b, 0xec, 0x0b, 0xc8, 0xeb, 0xf3, 0x88, 0xa2, + 0xce, 0xbf, 0xee, 0xa7, 0x31, 0x17, 0x0a, 0xe7, 0x5f, 0x91, 0x6e, 0x38, + 0x75, 0x7c, 0x5e, 0xc1, 0x56, 0x46, 0xe0, 0xd6, 0x44, 0x01, 0x17, 0xc8, + 0xd0, 0xd4, 0x50, 0x48, 0xd8, 0x5e, 0x54, 0x07, 0xe4, 0xa2, 0x40, 0x02, + 0x4d, 0xb3, 0x9b, 0xf2, 0x7a, 0x3d, 0xa2, 0xaf, 0x9b, 0x1e, 0xd1, 0x57, + 0x32, 0xc9, 0x55, 0x23, 0xdf, 0xc2, 0x66, 0x48, 0x6e, 0xc6, 0x4a, 0x60, + 0xd7, 0xdf, 0xff, 0x7a, 0x1b, 0x98, 0x3e, 0xea, 0x40, 0xce, 0x75, 0x1d, + 0x58, 0x7a, 0xda, 0x4c, 0xaf, 0xd1, 0x3c, 0xcb, 0xed, 0xff, 0xfe, 0x8d, + 0x88, 0x3f, 0xfc, 0xf6, 0xb1, 0xbd, 0x71, 0xf6, 0x8e, 0xbf, 0x4b, 0xa0, + 0x8e, 0x1d, 0x7f, 0xf3, 0xaf, 0x91, 0xb1, 0x36, 0x08, 0x34, 0x75, 0x6e, + 0x7d, 0xbd, 0x27, 0xbf, 0x60, 0x17, 0x1a, 0x3a, 0x8e, 0xbb, 0x26, 0xe1, + 0xb0, 0xd1, 0x35, 0xff, 0x20, 0x15, 0x3d, 0x8f, 0xa3, 0x39, 0xd7, 0xfd, + 0x13, 0xc6, 0xfe, 0x1c, 0x9c, 0xea, 0xc4, 0x52, 0x34, 0xb5, 0x0f, 0xaf, + 0xce, 0xb1, 0x8d, 0xce, 0xa9, 0x93, 0x4b, 0xe4, 0x3d, 0xfa, 0x5d, 0x7d, + 0x9d, 0xc9, 0xce, 0xbd, 0x27, 0xe1, 0xd7, 0xe9, 0x67, 0xb0, 0x25, 0x5f, + 0x40, 0x8c, 0x1d, 0x53, 0x1e, 0xff, 0x86, 0xfe, 0x93, 0x5f, 0x7f, 0xa5, + 0xf0, 0xea, 0x51, 0x1a, 0xa9, 0x08, 0x0f, 0x19, 0x5f, 0xf0, 0xe7, 0x73, + 0xe7, 0x72, 0x73, 0xaf, 0xe0, 0x2a, 0x53, 0x9c, 0xc3, 0xaf, 0xbc, 0xa6, + 0x74, 0xeb, 0x68, 0xeb, 0x93, 0xf3, 0xae, 0xea, 0x1d, 0x70, 0x35, 0xf0, + 0xd5, 0xcc, 0x2d, 0x4e, 0x7d, 0x7f, 0x9d, 0xdd, 0xfc, 0x1d, 0x77, 0xf0, + 0x75, 0xf8, 0x12, 0xc1, 0x61, 0x0d, 0x67, 0xe2, 0xd5, 0x09, 0x8c, 0xff, + 0x08, 0xd1, 0x4e, 0xbf, 0xfe, 0xc1, 0x7d, 0xf4, 0xa2, 0x8f, 0xf1, 0xab, + 0xfc, 0xeb, 0xff, 0xbd, 0xdc, 0x5f, 0xd8, 0xff, 0x37, 0xf1, 0xd7, 0xfb, + 0x76, 0xa7, 0x3e, 0xc0, 0x4e, 0xbe, 0xfd, 0x6f, 0x2f, 0x88, 0xd0, 0xd2, + 0xa7, 0x91, 0xef, 0xef, 0xd7, 0xf7, 0x5f, 0x67, 0x3a, 0xec, 0xdc, 0xea, + 0xdc, 0xf2, 0xb6, 0xcd, 0x2f, 0xbf, 0xe2, 0x70, 0xea, 0x84, 0x6e, 0x3c, + 0x25, 0x19, 0x26, 0xbe, 0xd0, 0x37, 0xf1, 0xd7, 0x63, 0x27, 0x5f, 0xf4, + 0x6f, 0x9f, 0xc6, 0xcc, 0x9c, 0xea, 0xe1, 0xe8, 0xfe, 0x2d, 0x7f, 0xe9, + 0xa2, 0x7d, 0x73, 0x1b, 0x13, 0x9d, 0x7f, 0x62, 0xf0, 0x28, 0xc9, 0xd7, + 0x2e, 0x0e, 0xa5, 0x9e, 0x0b, 0x96, 0x5f, 0xc3, 0x93, 0x75, 0x3c, 0x75, + 0xf6, 0x67, 0x74, 0x75, 0x62, 0x3b, 0x9e, 0x10, 0x3e, 0x21, 0xda, 0x2c, + 0xbc, 0xcb, 0x2c, 0x95, 0x7e, 0xc5, 0x04, 0x1a, 0x29, 0x82, 0xfe, 0xfd, + 0x8c, 0x32, 0xcb, 0x27, 0x54, 0x1f, 0x17, 0x8d, 0xef, 0xfb, 0x5c, 0x80, + 0x78, 0x53, 0x61, 0xd7, 0xfe, 0x1c, 0xd3, 0x7a, 0x8d, 0x81, 0x3a, 0xff, + 0xff, 0x28, 0xcb, 0xf1, 0x46, 0x35, 0x92, 0x10, 0x3e, 0xb0, 0x4e, 0xa8, + 0x46, 0xb6, 0x1c, 0xa1, 0xdd, 0xf3, 0x2e, 0x32, 0x3a, 0xff, 0xbd, 0x1b, + 0xfe, 0xfd, 0xea, 0x1d, 0x6e, 0x9d, 0x58, 0x79, 0x2d, 0x39, 0xbc, 0xcb, + 0x2c, 0x95, 0x7f, 0x23, 0xa9, 0xd4, 0xf1, 0x4c, 0x17, 0xf7, 0xde, 0xd3, + 0xf0, 0xeb, 0xdd, 0x80, 0x9d, 0x48, 0x6f, 0x1c, 0x86, 0xfd, 0x9f, 0xe6, + 0x4c, 0x75, 0xb5, 0xf1, 0x1f, 0xdc, 0x40, 0xeb, 0xc0, 0x8f, 0xdc, 0x09, + 0x05, 0x3a, 0xcc, 0x8d, 0xa2, 0xfc, 0xa9, 0xec, 0x4e, 0x03, 0xab, 0xaa, + 0x8e, 0x86, 0x3d, 0x90, 0x1a, 0xde, 0x8d, 0x90, 0x75, 0x21, 0xe9, 0x89, + 0xbd, 0xe1, 0x8d, 0x87, 0x5c, 0xa9, 0x43, 0xae, 0x4e, 0x9d, 0x67, 0x9c, + 0xd7, 0x70, 0x66, 0xfb, 0xda, 0x02, 0xb9, 0xd7, 0xfa, 0x06, 0x42, 0x91, + 0xb9, 0xd5, 0x0c, 0xdc, 0xb9, 0x12, 0xe4, 0xa1, 0xb5, 0x23, 0x0c, 0x69, + 0xaa, 0x1c, 0xf2, 0x34, 0x9e, 0xc7, 0xc2, 0xe6, 0x9f, 0xba, 0x0c, 0x62, + 0x3a, 0x86, 0x27, 0xa5, 0xc2, 0x6c, 0x20, 0xdb, 0x4a, 0xfa, 0x4f, 0xb4, + 0x4b, 0x72, 0xb0, 0x87, 0x5f, 0xfa, 0x26, 0xf6, 0xd6, 0xa2, 0x60, 0x70, + 0xeb, 0xff, 0xb1, 0x3b, 0x01, 0xe8, 0x23, 0x7d, 0x1d, 0x78, 0x2a, 0x7e, + 0x75, 0xf9, 0x7c, 0xe3, 0xf8, 0xea, 0xf8, 0x78, 0xb0, 0x3d, 0x7f, 0xf9, + 0xb3, 0x3b, 0x7b, 0x12, 0xf0, 0xe2, 0xce, 0xbf, 0xfe, 0x45, 0xef, 0x2d, + 0x7c, 0xc1, 0x1c, 0x4f, 0xce, 0xbc, 0x9d, 0x01, 0xd4, 0xac, 0xa7, 0x79, + 0x21, 0xae, 0x21, 0xf6, 0x11, 0x0e, 0x47, 0xe4, 0x9d, 0x8a, 0x16, 0x61, + 0x58, 0x8d, 0x8a, 0x5d, 0x51, 0x0b, 0x95, 0x6e, 0x34, 0x85, 0x53, 0x62, + 0xb4, 0x8c, 0x65, 0x57, 0xc6, 0x2c, 0xad, 0x4e, 0x95, 0x60, 0xf8, 0xa6, + 0x00, 0x4f, 0x3a, 0x11, 0x2a, 0x44, 0x98, 0x69, 0x21, 0x99, 0x6d, 0x1d, + 0x14, 0x96, 0x1c, 0xda, 0x4c, 0x46, 0xf3, 0xeb, 0xe9, 0x48, 0xce, 0x9a, + 0x9c, 0x11, 0xca, 0x69, 0x4a, 0xe7, 0xe2, 0x3b, 0x5b, 0x0a, 0xbd, 0x73, + 0x9d, 0xfd, 0x24, 0xc1, 0x53, 0x0d, 0x61, 0xac, 0xd3, 0xf5, 0x6d, 0x5f, + 0x7d, 0x68, 0x2f, 0x41, 0x3a, 0x37, 0xb2, 0x52, 0x9b, 0x32, 0x83, 0xf6, + 0xe7, 0xc7, 0xbe, 0xd3, 0xf1, 0xb6, 0xa5, 0x6c, 0x53, 0x11, 0xb2, 0xea, + 0xcb, 0x36, 0x2e, 0x7b, 0xf3, 0x1f, 0xaf, 0x3c, 0x75, 0xfe, 0x63, 0x38, + 0xd7, 0x76, 0x9a, 0x2e, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x5d, + 0x77, 0xff, 0x30, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x1a, 0x88, + 0xda, 0xc3, 0x25, 0x0b, 0xb0, 0x94, 0xa9, 0x08, 0xf6, 0x94, 0x24, 0x74, + 0x2a, 0xee, 0x2f, 0x9b, 0x31, 0x67, 0xe7, 0x7a, 0x29, 0xf1, 0xfe, 0xd1, + 0xfd, 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0xab, + 0xfe, 0x55, 0xdd, 0x45, 0x77, 0x8d, 0xf6, 0x8e, 0xbf, 0x71, 0xae, 0xed, + 0x34, 0x46, 0xf7, 0xfe, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xfd, + 0xfd, 0x1e, 0xfb, 0xd7, 0xf1, 0xd7, 0xfb, 0x3e, 0xf1, 0x4e, 0x83, 0x47, + 0x59, 0x85, 0x6a, 0x99, 0x2e, 0x22, 0x2c, 0xcf, 0xa9, 0x42, 0x5d, 0x7f, + 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0xae, 0xe4, 0xda, 0x3a, 0xf9, 0x16, + 0xfb, 0x0e, 0xa5, 0x0d, 0xd7, 0x86, 0x2f, 0x0e, 0xd3, 0x27, 0x5f, 0xcf, + 0xd9, 0x86, 0x02, 0x75, 0xff, 0xde, 0xec, 0x68, 0x5c, 0x0a, 0x94, 0xe1, + 0xd7, 0xa2, 0x58, 0x75, 0x05, 0x11, 0x9b, 0x96, 0x4c, 0x8d, 0x7f, 0xca, + 0x60, 0xe6, 0xfe, 0x75, 0x9d, 0x70, 0x50, 0xeb, 0xfb, 0x38, 0xd7, 0x76, + 0x9a, 0x24, 0x0a, 0xf8, 0x79, 0xac, 0x0a, 0xdf, 0xb4, 0xe2, 0xfb, 0x9d, + 0x70, 0x20, 0xea, 0x91, 0xf0, 0x6e, 0x4b, 0xc2, 0x6b, 0xfd, 0x28, 0xe4, + 0xf1, 0xc9, 0xce, 0xbf, 0xdc, 0x9d, 0x70, 0x32, 0xd1, 0xd5, 0x07, 0xcf, + 0x86, 0x97, 0xd9, 0x3b, 0x84, 0xeb, 0xff, 0xd9, 0x37, 0x5d, 0x7e, 0xec, + 0x78, 0x0b, 0x3a, 0xa7, 0x56, 0x0c, 0x12, 0x2c, 0x85, 0x5a, 0x86, 0x4f, + 0x0e, 0x51, 0x84, 0xbf, 0x88, 0x3e, 0x90, 0xdf, 0xfc, 0x39, 0x3b, 0x1b, + 0x70, 0x23, 0x9e, 0x3a, 0x98, 0x46, 0x47, 0x21, 0x07, 0x7f, 0x98, 0xce, + 0x35, 0xdd, 0xa6, 0x8b, 0x22, 0xff, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, + 0xbd, 0xff, 0xec, 0xfb, 0x13, 0xb1, 0x93, 0x78, 0x30, 0x27, 0x5f, 0xe6, + 0x33, 0x8d, 0x77, 0x69, 0xa2, 0xe4, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x5d, + 0x97, 0xfe, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x14, 0x75, 0x98, 0xc3, + 0xfd, 0x59, 0x9d, 0xf0, 0xc4, 0x96, 0x75, 0xa4, 0x75, 0xfb, 0x8d, 0x77, + 0x69, 0xa2, 0x95, 0xbf, 0xe6, 0xf5, 0x26, 0xec, 0x4f, 0x87, 0x5f, 0xfe, + 0xec, 0x4f, 0x1d, 0x4d, 0x8e, 0x1e, 0xa1, 0xcc, 0x1b, 0x9b, 0xa4, 0xc6, + 0x23, 0x1e, 0x66, 0xca, 0xdd, 0x30, 0x77, 0x86, 0xbd, 0xff, 0x9d, 0x3d, + 0x20, 0x05, 0xc7, 0xf3, 0xac, 0xc0, 0x53, 0x8d, 0x5c, 0x64, 0xfd, 0x29, + 0xa9, 0xd9, 0x37, 0x72, 0x8d, 0xf3, 0x75, 0x64, 0x9c, 0x47, 0x59, 0x4f, + 0xe7, 0xe2, 0x7f, 0xa4, 0xcf, 0x42, 0xf3, 0x64, 0x76, 0xb7, 0xfd, 0x26, + 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x38, 0xbf, 0xe4, 0x63, 0x38, 0xd7, 0x76, + 0x9a, 0x2b, 0x5b, 0x30, 0xe8, 0x89, 0xf2, 0x2d, 0xff, 0xe6, 0x16, 0xf2, + 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0xbb, 0xc0, 0xe7, 0xe7, 0x5d, 0x9b, + 0x9d, 0x7f, 0x83, 0x8b, 0x5c, 0x26, 0x8e, 0xbd, 0xb0, 0x12, 0x3a, 0x9a, + 0x88, 0x2d, 0xc7, 0x50, 0x5b, 0x61, 0x8d, 0xee, 0x86, 0x47, 0x5f, 0xf6, + 0x6e, 0x39, 0xff, 0xef, 0x23, 0xae, 0x5b, 0x4e, 0xa8, 0x3c, 0xf9, 0x1c, + 0xdf, 0x0c, 0x6f, 0x23, 0xaf, 0xff, 0xcf, 0xbf, 0xe1, 0xeb, 0xcb, 0x34, + 0x20, 0x7f, 0xa7, 0x53, 0x4f, 0xe3, 0xa4, 0x37, 0xf2, 0x70, 0x53, 0xda, + 0x3a, 0xfd, 0xc7, 0x1c, 0x83, 0xa8, 0xd1, 0x0d, 0xf4, 0xf3, 0xdc, 0xae, + 0xe8, 0x13, 0xaf, 0xe4, 0x10, 0xe2, 0x04, 0xea, 0x83, 0x7d, 0x21, 0x4b, + 0xec, 0x9a, 0x58, 0x75, 0xff, 0x9e, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, + 0xc1, 0x7e, 0xff, 0x4e, 0x3f, 0x9d, 0x7f, 0x81, 0xbf, 0x12, 0x17, 0x87, + 0x5f, 0xf4, 0x4f, 0xe1, 0x80, 0x7b, 0x47, 0x5b, 0xdd, 0x3e, 0xad, 0xb3, + 0x2b, 0xed, 0xda, 0x8a, 0x1d, 0x58, 0x79, 0xde, 0x2b, 0xbf, 0xda, 0x4e, + 0xa2, 0xf1, 0x43, 0xaf, 0xff, 0x3c, 0xfd, 0x48, 0x1c, 0x99, 0x38, 0x87, + 0x57, 0x8f, 0xe5, 0x93, 0x2b, 0x9b, 0x87, 0x5c, 0x0f, 0xca, 0xa4, 0x35, + 0x9c, 0x15, 0xbf, 0xd8, 0x11, 0xcf, 0x77, 0x0e, 0xbf, 0xa7, 0xfb, 0xb6, + 0xe3, 0xf9, 0xd7, 0xf6, 0x7b, 0xd1, 0xcd, 0x1d, 0x7f, 0x38, 0xff, 0x3f, + 0xfe, 0x3a, 0xa1, 0x11, 0xc2, 0x67, 0xb6, 0x59, 0x66, 0x21, 0x76, 0x26, + 0x73, 0xf0, 0xb5, 0xe4, 0x26, 0x5a, 0xe3, 0xbb, 0x97, 0x08, 0x16, 0x42, + 0xe9, 0x43, 0x0e, 0x0d, 0x42, 0x6b, 0xc9, 0xfb, 0x08, 0x3e, 0xc2, 0xfa, + 0xf2, 0xc1, 0xc2, 0xaf, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x26, + 0x3b, 0xe8, 0xe4, 0x6d, 0x1d, 0x66, 0x11, 0x11, 0x2b, 0x1c, 0xea, 0x55, + 0xf4, 0x4f, 0x1c, 0x3a, 0xfd, 0x91, 0x32, 0x2c, 0xea, 0x43, 0xc7, 0xe1, + 0x0d, 0xfe, 0xec, 0x72, 0x7f, 0xa0, 0xfc, 0xeb, 0x9f, 0x47, 0x5f, 0x7c, + 0xf6, 0x74, 0xeb, 0x47, 0x4d, 0xc6, 0x85, 0x6f, 0x40, 0xce, 0x75, 0xff, + 0xff, 0xf4, 0xb5, 0xdc, 0x03, 0x3a, 0xee, 0x37, 0x35, 0xf3, 0x37, 0x96, + 0x90, 0x50, 0xeb, 0xce, 0xed, 0x34, 0x56, 0x37, 0xcf, 0xf6, 0x14, 0x3a, + 0x9a, 0x79, 0x5c, 0x27, 0xbf, 0xf6, 0xde, 0x78, 0x70, 0x10, 0x3e, 0x3a, + 0x94, 0x4d, 0xa9, 0xa4, 0xdb, 0x8d, 0xf2, 0x19, 0x3e, 0x22, 0xbf, 0xf8, + 0x7c, 0xa0, 0x20, 0x71, 0xb1, 0xc3, 0xaf, 0xf7, 0x27, 0xf6, 0x9f, 0x76, + 0x9d, 0x50, 0x7e, 0xee, 0x85, 0x7f, 0x46, 0xd7, 0xb3, 0x79, 0x8e, 0xbf, + 0x81, 0xb6, 0xde, 0xa2, 0xa4, 0xeb, 0xfb, 0x35, 0xbc, 0xa3, 0xa7, 0x5d, + 0x1b, 0x0e, 0xb0, 0x7a, 0x78, 0x82, 0x5b, 0x7f, 0xd1, 0xbc, 0xa6, 0x93, + 0xf2, 0x73, 0xaa, 0x11, 0xb5, 0x8f, 0x08, 0x4f, 0x7a, 0x25, 0xe3, 0xaf, + 0xfd, 0x81, 0xe2, 0x02, 0x7f, 0xf5, 0x23, 0xaf, 0x96, 0xfb, 0xf8, 0xeb, + 0xff, 0xa7, 0x8f, 0x7c, 0xfa, 0xdf, 0xbb, 0x5f, 0x74, 0x75, 0xff, 0x72, + 0x34, 0xfc, 0x18, 0x91, 0xd5, 0xc4, 0x43, 0xec, 0x51, 0xbd, 0x27, 0x9c, + 0xeb, 0xdf, 0x27, 0x59, 0xd7, 0x07, 0xc7, 0x52, 0xa9, 0x31, 0xfc, 0x85, + 0x4e, 0xe4, 0xa8, 0x38, 0x23, 0xf7, 0xfe, 0x17, 0x0f, 0x63, 0x67, 0x5c, + 0x4e, 0xbf, 0xff, 0xf0, 0x27, 0xc6, 0xfc, 0x10, 0x6d, 0x7c, 0xcd, 0xe5, + 0x80, 0x1f, 0xf4, 0x75, 0xff, 0x3e, 0xe3, 0x81, 0xeb, 0xb2, 0x75, 0x05, + 0x1d, 0x42, 0x7b, 0xa7, 0x5b, 0xfa, 0x79, 0xa4, 0xaa, 0xe4, 0xe7, 0x5f, + 0x08, 0xe7, 0x8e, 0xa5, 0x64, 0xf5, 0x20, 0xd6, 0xfe, 0x9f, 0xee, 0xdb, + 0x8f, 0xe7, 0x5f, 0xfd, 0x37, 0x5d, 0x7e, 0xec, 0x78, 0x0b, 0x3a, 0xff, + 0x92, 0x49, 0xd0, 0x2d, 0x68, 0x75, 0x42, 0x2b, 0xf0, 0xcf, 0xc8, 0xb7, + 0xba, 0x8c, 0x43, 0x21, 0x5e, 0x44, 0x39, 0x1e, 0xcb, 0x61, 0x93, 0xc2, + 0x0e, 0xc6, 0x16, 0xe5, 0xa2, 0x37, 0xa8, 0xd7, 0xfd, 0x19, 0xe6, 0xdc, + 0x20, 0xfe, 0xc3, 0x56, 0xe9, 0x09, 0xd7, 0xf7, 0x39, 0x01, 0xc5, 0x9d, + 0x77, 0xdf, 0xce, 0xbd, 0xd4, 0x59, 0xd6, 0x98, 0xea, 0x73, 0x58, 0x01, + 0xbb, 0xf3, 0x8c, 0xe0, 0xd1, 0xd7, 0xfd, 0x01, 0xee, 0x07, 0x8e, 0xd3, + 0xa9, 0x11, 0xdf, 0xf9, 0x60, 0xa2, 0xe8, 0x83, 0xc4, 0xf7, 0xb5, 0xf7, + 0x47, 0x5f, 0x6f, 0x3c, 0x28, 0x75, 0x04, 0xf0, 0x80, 0x3d, 0x77, 0xa0, + 0xeb, 0xf2, 0xf0, 0x62, 0x47, 0x5f, 0x03, 0xd9, 0xa3, 0xaf, 0xa3, 0x8e, + 0x27, 0x5f, 0xe7, 0xe4, 0xbf, 0x4d, 0xf4, 0x75, 0xf6, 0xb5, 0x1f, 0x9d, + 0x50, 0x8b, 0xb4, 0x25, 0xe9, 0x08, 0x07, 0xd9, 0x34, 0xbe, 0x97, 0xe0, + 0x91, 0xd7, 0xdc, 0xfb, 0x1f, 0x9d, 0x50, 0x78, 0xe8, 0x47, 0x7f, 0x92, + 0x77, 0x5f, 0xff, 0xc1, 0xd7, 0xfc, 0x8d, 0xee, 0x4c, 0x30, 0x13, 0xaf, + 0xa5, 0xec, 0xfa, 0x75, 0xe6, 0xc7, 0xe7, 0x5e, 0xe4, 0x2c, 0xea, 0x73, + 0xda, 0x01, 0x1b, 0x23, 0x97, 0xe8, 0x9f, 0xee, 0x4c, 0x75, 0xe8, 0x19, + 0x1d, 0x53, 0x26, 0xb1, 0xc2, 0x0e, 0x9a, 0x0c, 0x24, 0x74, 0x5f, 0xe2, + 0xab, 0xff, 0x46, 0x6b, 0xe4, 0x20, 0x7e, 0xc8, 0xeb, 0xf9, 0x19, 0xd4, + 0xf8, 0xc9, 0xd4, 0x27, 0xdf, 0xe4, 0x0b, 0xf4, 0x07, 0xd8, 0xd3, 0xaf, + 0xbb, 0x02, 0xd3, 0xaa, 0x47, 0xcf, 0xa2, 0x1f, 0x13, 0x5f, 0x38, 0xbc, + 0xc7, 0x5f, 0x93, 0xc3, 0x92, 0x3a, 0xfa, 0x19, 0x89, 0x8e, 0xbb, 0xea, + 0xce, 0xbf, 0xe0, 0x7c, 0xf0, 0xbf, 0xf8, 0x27, 0x54, 0xe8, 0xb8, 0x50, + 0x81, 0x09, 0x7a, 0x44, 0x23, 0x17, 0xfa, 0x19, 0x08, 0x1f, 0x92, 0x3a, + 0xfe, 0x4e, 0x6f, 0xa8, 0x91, 0xd6, 0xd8, 0x75, 0x70, 0xfc, 0xba, 0x67, + 0xb4, 0x5b, 0x78, 0x51, 0x43, 0xaf, 0xb0, 0x29, 0xb0, 0xeb, 0xa1, 0x78, + 0x6f, 0x5c, 0x6e, 0xda, 0x3a, 0x90, 0xdd, 0x39, 0x55, 0xdf, 0xc1, 0x57, + 0x32, 0xc9, 0x54, 0x86, 0xb9, 0x91, 0x6b, 0xfc, 0xf2, 0x1c, 0xf7, 0x50, + 0xa6, 0x0d, 0x0d, 0xe7, 0xdf, 0x47, 0x5f, 0x7d, 0xeb, 0xf8, 0xea, 0x09, + 0xbf, 0xf0, 0xe5, 0xe8, 0x19, 0x8e, 0xb8, 0x60, 0xeb, 0x4c, 0x75, 0x4c, + 0x78, 0x1c, 0x1b, 0x71, 0x4b, 0xff, 0x94, 0x41, 0x6e, 0xa1, 0x6f, 0xbf, + 0x8e, 0xbd, 0xfe, 0x6d, 0x1d, 0x4a, 0x1f, 0x1f, 0x11, 0x2f, 0x97, 0xa0, + 0x2c, 0xeb, 0x28, 0x75, 0xb6, 0xce, 0xbb, 0x8a, 0x1d, 0x50, 0x7b, 0xa8, + 0x44, 0x01, 0x1f, 0xa2, 0x77, 0xff, 0xdd, 0xc9, 0x6a, 0x3d, 0x2c, 0x57, + 0x71, 0xfc, 0xeb, 0xff, 0x49, 0x3d, 0xdc, 0xdf, 0xc0, 0x83, 0xae, 0xcd, + 0x1d, 0x50, 0x7a, 0x72, 0x3e, 0xad, 0x23, 0x17, 0xd0, 0xa4, 0xbf, 0x24, + 0x2e, 0x16, 0x75, 0xb0, 0xea, 0x43, 0xdc, 0xd1, 0x46, 0xd9, 0x2d, 0x42, + 0xb0, 0x1c, 0x61, 0x48, 0x49, 0x76, 0x10, 0x0f, 0x1a, 0xed, 0xed, 0x44, + 0xc7, 0x51, 0xd6, 0x59, 0xd5, 0xe2, 0xeb, 0x60, 0x55, 0xfb, 0xf4, 0xe2, + 0x28, 0x75, 0xce, 0xa1, 0xd5, 0x32, 0x25, 0xba, 0x6d, 0xf9, 0x10, 0x94, + 0x5d, 0xe8, 0x3a, 0xfd, 0x1d, 0xcd, 0x8e, 0x75, 0x39, 0xbc, 0xfc, 0x56, + 0xfe, 0x4f, 0x67, 0x5d, 0x43, 0xaf, 0xee, 0x81, 0xe7, 0xea, 0x1d, 0x79, + 0x96, 0x59, 0x2a, 0xff, 0x83, 0x13, 0xfd, 0xce, 0xbe, 0xe5, 0x30, 0x5f, + 0xdd, 0x93, 0x9d, 0x41, 0x45, 0x6b, 0x53, 0x11, 0x2e, 0xf4, 0x2d, 0x0e, + 0xac, 0x3c, 0x96, 0x97, 0xdf, 0x27, 0x36, 0x82, 0x75, 0xfb, 0xb1, 0xbb, + 0xab, 0x9d, 0x7f, 0xfd, 0x1e, 0xd0, 0x73, 0xc9, 0xd0, 0x66, 0xfe, 0x3a, + 0xba, 0x7f, 0x3e, 0x2a, 0xb7, 0x0e, 0xbf, 0xd9, 0x8d, 0xfb, 0xb3, 0xb8, + 0x75, 0xc0, 0xd1, 0xd7, 0xff, 0xec, 0x0c, 0x66, 0xff, 0x7c, 0x82, 0x09, + 0x66, 0x8e, 0xb9, 0x7f, 0x9d, 0x73, 0x89, 0xd5, 0xd3, 0x56, 0xe2, 0xf7, + 0xe5, 0xa7, 0xbf, 0x73, 0xaa, 0x74, 0xf8, 0x72, 0x13, 0xaa, 0xe4, 0x53, + 0x08, 0x39, 0xa8, 0x8b, 0x7a, 0x10, 0x00, 0x20, 0xbe, 0xef, 0x92, 0x73, + 0xaf, 0xf3, 0x53, 0x43, 0x9b, 0x1c, 0xeb, 0xe8, 0x9d, 0xe4, 0x75, 0xd9, + 0xe3, 0xaf, 0xd9, 0x38, 0xe6, 0xe7, 0x56, 0x22, 0xc7, 0x72, 0x2e, 0x19, + 0x74, 0x84, 0x45, 0x6f, 0x76, 0x02, 0x75, 0xdc, 0xd1, 0xd4, 0x72, 0x16, + 0xd7, 0xfa, 0x06, 0x4e, 0xbc, 0x09, 0xd7, 0xde, 0x5a, 0xf8, 0x75, 0xff, + 0xdf, 0xc0, 0xb5, 0xfd, 0xff, 0xd1, 0x91, 0xd7, 0xa4, 0x9d, 0x3a, 0xfb, + 0xc3, 0x92, 0x3a, 0xfd, 0x80, 0x54, 0xe9, 0xce, 0xbf, 0xfc, 0x9a, 0xee, + 0x04, 0x73, 0x60, 0xe6, 0x8e, 0xa9, 0x26, 0x8a, 0xa1, 0x86, 0xe4, 0x53, + 0x23, 0x70, 0x6c, 0x48, 0x3c, 0x55, 0x4a, 0xa6, 0xcf, 0xc6, 0x23, 0x04, + 0x9e, 0x11, 0x72, 0x22, 0x0c, 0x34, 0x32, 0x3e, 0x8d, 0xe3, 0x33, 0x48, + 0x73, 0xcd, 0x0b, 0xce, 0x42, 0xa5, 0x6d, 0xdd, 0x97, 0x02, 0xf0, 0xee, + 0xfd, 0xe9, 0x52, 0x42, 0x31, 0x91, 0x6a, 0x50, 0x17, 0xa3, 0x2f, 0x65, + 0x27, 0x6c, 0xc7, 0xec, 0x6b, 0xb7, 0xfc, 0xc7, 0x93, 0x36, 0xb4, 0x08, + 0x3a, 0xff, 0xff, 0x81, 0x0c, 0x7b, 0x49, 0xd7, 0x4f, 0x67, 0x3f, 0x5b, + 0xc8, 0xea, 0x61, 0x50, 0xec, 0xf1, 0xbe, 0x04, 0xee, 0xfd, 0xc6, 0xbb, + 0xb4, 0xd1, 0x5b, 0xdf, 0xf9, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4e, + 0x16, 0x63, 0x0f, 0xf5, 0x66, 0x77, 0x2a, 0x82, 0x75, 0xba, 0x75, 0xb4, + 0x75, 0x00, 0xd0, 0x6d, 0x88, 0x5f, 0x35, 0xdd, 0xa6, 0x8b, 0x46, 0xff, + 0xf6, 0x07, 0xae, 0xa4, 0xd3, 0x26, 0x80, 0xb3, 0xab, 0x87, 0xf3, 0xd2, + 0xdb, 0xe6, 0xb8, 0xfe, 0x75, 0xff, 0x4d, 0x8a, 0xfa, 0xe7, 0x1f, 0xc7, + 0x5f, 0xd0, 0xe2, 0x00, 0xe1, 0xd7, 0x22, 0x87, 0x5f, 0xff, 0xa7, 0x8f, + 0x40, 0x79, 0x1d, 0x7d, 0x0e, 0x7e, 0x75, 0xff, 0xa3, 0x77, 0x57, 0xe8, + 0xba, 0xbc, 0xe7, 0x5f, 0xfa, 0x39, 0xfe, 0x26, 0x73, 0xc0, 0x3a, 0xa1, + 0x1a, 0xbd, 0x54, 0xd2, 0x25, 0xb2, 0x64, 0xc6, 0xb5, 0x0e, 0xbb, 0xfd, + 0xde, 0x81, 0x45, 0xc6, 0x8e, 0xbf, 0xff, 0x26, 0x87, 0x36, 0x3f, 0x87, + 0x35, 0xd7, 0x98, 0xea, 0xc4, 0x44, 0x4c, 0x69, 0x7d, 0x9f, 0xbf, 0x4e, + 0xbb, 0xba, 0x3a, 0xcc, 0x2a, 0x15, 0xd5, 0xab, 0x67, 0x59, 0x09, 0xd6, + 0x91, 0x4c, 0x42, 0xb3, 0xce, 0xc6, 0x89, 0xe8, 0x5b, 0xed, 0x91, 0xfd, + 0x21, 0xbe, 0x6b, 0xbb, 0x4d, 0x16, 0xd5, 0xff, 0xfd, 0x0f, 0xe8, 0xec, + 0x69, 0x12, 0x49, 0xcc, 0x09, 0xd7, 0xf7, 0x61, 0x70, 0x81, 0x3a, 0xb8, + 0x8a, 0xed, 0x16, 0xf9, 0x5a, 0xff, 0xdd, 0x40, 0xbc, 0x83, 0xd4, 0x59, + 0xd7, 0xd1, 0xb3, 0x10, 0xeb, 0xfe, 0x89, 0x47, 0x27, 0x8e, 0x4e, 0x75, + 0xff, 0x47, 0x3e, 0x6a, 0x3a, 0xe8, 0x75, 0xfe, 0xea, 0x3c, 0xbc, 0x93, + 0x9d, 0x58, 0x99, 0x8b, 0x4c, 0x38, 0x7a, 0x24, 0x2c, 0x9c, 0xed, 0x9c, + 0x5f, 0xca, 0x3f, 0x02, 0x01, 0x3a, 0xfe, 0x1d, 0xb4, 0xe6, 0x28, 0x75, + 0xf9, 0x27, 0x5c, 0x34, 0xeb, 0xf3, 0xef, 0x2f, 0xba, 0x3a, 0xcc, 0x28, + 0x8a, 0xd1, 0x2d, 0xf1, 0x7e, 0xc2, 0x7a, 0x61, 0x34, 0xdf, 0xe3, 0x07, + 0xb9, 0x7d, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x72, 0xd9, 0x80, 0x9e, + 0x4e, 0x0b, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x2e, 0xdb, 0xfe, 0x49, 0x49, + 0x07, 0xf8, 0x91, 0xd6, 0x63, 0x0f, 0xa9, 0xcc, 0xea, 0x1d, 0x8a, 0x74, + 0xe5, 0x32, 0x9e, 0x62, 0x0c, 0x6d, 0x0a, 0x52, 0x35, 0x12, 0xb6, 0xf1, + 0x57, 0x85, 0xbf, 0x65, 0xe9, 0x8c, 0xbd, 0xed, 0x3a, 0xfa, 0x12, 0x57, + 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa9, 0xef, 0x06, 0x75, 0x9d, 0x6f, + 0x1d, 0x7f, 0xd0, 0xf3, 0xfc, 0xdf, 0x50, 0x13, 0xa9, 0x0f, 0x2c, 0x44, + 0x2f, 0x9a, 0xee, 0xd3, 0x45, 0x73, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, + 0x8b, 0x3a, 0xf3, 0xbc, 0x8e, 0xbf, 0x93, 0x58, 0x2e, 0xc9, 0xd5, 0xc4, + 0x58, 0xf4, 0xb4, 0x4f, 0xfc, 0x35, 0x7f, 0xfb, 0xd1, 0xaf, 0x80, 0xd7, + 0xa2, 0x69, 0x90, 0xeb, 0xf9, 0x17, 0x38, 0x39, 0x23, 0xaf, 0xf4, 0x77, + 0xe2, 0xd5, 0xb5, 0x47, 0x8e, 0xac, 0x45, 0xcf, 0x53, 0x76, 0x17, 0x5f, + 0xb9, 0x9e, 0x45, 0x9d, 0x7c, 0xe3, 0x01, 0x3a, 0xfe, 0xc9, 0xa1, 0x71, + 0xf4, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x85, 0x7f, 0xec, 0x5e, 0x3f, + 0x27, 0xf9, 0xba, 0xce, 0xbf, 0xe4, 0xdf, 0x5e, 0x18, 0x5e, 0x8e, 0xba, + 0x4c, 0x62, 0x2b, 0x3a, 0x67, 0xfa, 0x0d, 0xff, 0xdd, 0x45, 0xe6, 0xbe, + 0x6f, 0x2c, 0xf1, 0xd7, 0xd2, 0xef, 0xdd, 0x1d, 0x50, 0x7d, 0x58, 0x8d, + 0x7c, 0xad, 0xf6, 0x16, 0x75, 0xfd, 0xdd, 0x6b, 0x39, 0x39, 0xd7, 0x43, + 0x27, 0x56, 0x1e, 0x22, 0x17, 0x59, 0x89, 0xd7, 0x33, 0xc2, 0xd1, 0x90, + 0xd1, 0x48, 0x7a, 0xf0, 0xc5, 0x64, 0xdd, 0x1f, 0x78, 0x6d, 0x0c, 0x29, + 0xf4, 0x41, 0xe6, 0xab, 0xff, 0x98, 0xeb, 0xe8, 0x73, 0xde, 0x8f, 0xce, + 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xf9, 0x4d, + 0x5e, 0x5c, 0x57, 0x9d, 0x0e, 0x5c, 0x2c, 0xfa, 0x89, 0x72, 0x6e, 0x75, + 0xff, 0xf4, 0xa7, 0x55, 0xa1, 0x5b, 0x9d, 0xbc, 0xf9, 0xf3, 0xbb, 0x67, + 0x54, 0x8f, 0xeb, 0xf1, 0x6b, 0xf6, 0x73, 0x32, 0x63, 0xac, 0xc7, 0x4f, + 0x27, 0xe9, 0x1d, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xb2, 0xbf, 0xf3, 0xc9, + 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9b, 0xac, 0xc6, 0x1f, 0xea, 0xcc, 0xe9, + 0xa8, 0xd0, 0x48, 0x54, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x25, 0x6b, 0xf0, + 0xc0, 0x5f, 0xa7, 0x5f, 0x98, 0x5b, 0xc9, 0x8c, 0x3d, 0x84, 0x33, 0xbf, + 0xf7, 0xb1, 0x8c, 0xe2, 0x4e, 0xeb, 0x3a, 0xff, 0xf2, 0xb0, 0xac, 0xaa, + 0x35, 0x8f, 0x24, 0xce, 0x61, 0xd7, 0xfe, 0x4d, 0x01, 0x62, 0x9b, 0x00, + 0xe7, 0x5f, 0xd0, 0x2e, 0xd7, 0x57, 0x3a, 0xa4, 0x7d, 0x6b, 0x3e, 0xb8, + 0x3c, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x2e, 0x5f, 0xf2, 0x3c, 0xbc, + 0x30, 0xbd, 0x1d, 0x7e, 0x96, 0xda, 0x75, 0xce, 0xbd, 0x1b, 0x70, 0x75, + 0xe4, 0x18, 0x3a, 0xa4, 0x7b, 0xe1, 0x29, 0xd8, 0x3b, 0x7f, 0xfe, 0x7f, + 0x20, 0x24, 0x29, 0x28, 0xf0, 0x82, 0x47, 0x5f, 0xd2, 0xee, 0x0e, 0x34, + 0xeb, 0xd2, 0xef, 0x8e, 0xbb, 0xb0, 0x87, 0x8f, 0xd2, 0xbb, 0xff, 0x85, + 0x3f, 0xd7, 0x21, 0x24, 0xfa, 0x3a, 0xb0, 0xfb, 0x90, 0xb2, 0xf3, 0xc9, + 0x85, 0x5e, 0xac, 0x62, 0x21, 0x81, 0x22, 0x2c, 0x16, 0xe9, 0x9b, 0xc2, + 0x57, 0x46, 0x3e, 0x8c, 0x1e, 0xcc, 0x22, 0xbe, 0xe5, 0xcb, 0x56, 0xbf, + 0xf9, 0x87, 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x1d, 0xdf, 0xf7, 0xbb, + 0x92, 0x61, 0xc7, 0x47, 0x5f, 0xca, 0xa1, 0x86, 0xe0, 0x9d, 0x70, 0x3a, + 0x75, 0xfc, 0xa8, 0x1c, 0xeb, 0xf8, 0xeb, 0xff, 0xfb, 0xd2, 0x40, 0xf5, + 0x36, 0x7c, 0xc0, 0xf1, 0x00, 0xd3, 0xaf, 0xf6, 0x33, 0xa8, 0x1f, 0x68, + 0xeb, 0xfc, 0xe3, 0xfb, 0xf1, 0xfe, 0x9d, 0x7f, 0xe4, 0xe7, 0xcd, 0x0e, + 0x2e, 0x1a, 0x75, 0xff, 0xa0, 0x41, 0xe4, 0x7d, 0x8f, 0x23, 0xaf, 0x9a, + 0xee, 0xd3, 0x45, 0x43, 0x7f, 0xd9, 0xdc, 0x17, 0xe7, 0x10, 0xea, 0x51, + 0x1b, 0xad, 0x3e, 0xe1, 0xee, 0x8b, 0x6e, 0x96, 0x1d, 0x7f, 0xd2, 0xf2, + 0x71, 0xda, 0x82, 0x75, 0xff, 0xe7, 0x5e, 0x70, 0x71, 0x36, 0x27, 0x1c, + 0xeb, 0xff, 0xba, 0x39, 0x37, 0xbb, 0x9c, 0x4d, 0x1d, 0x7e, 0xdc, 0x51, + 0x68, 0x75, 0x42, 0x2c, 0x31, 0x1d, 0x10, 0xef, 0xf4, 0x79, 0xfb, 0xf0, + 0x30, 0x75, 0xff, 0x81, 0xf1, 0xc7, 0x36, 0xbe, 0x74, 0x07, 0x5f, 0xe9, + 0x47, 0x27, 0x8e, 0x4e, 0x75, 0xff, 0xda, 0xd6, 0x0f, 0xb5, 0x92, 0x4e, + 0x9d, 0x7f, 0xfd, 0x1f, 0xe0, 0xfc, 0x7f, 0x7c, 0xee, 0x7e, 0xe7, 0x5c, + 0x33, 0x9d, 0x50, 0x8d, 0xec, 0x34, 0x44, 0x21, 0x52, 0xbf, 0xb6, 0x3a, + 0xfa, 0xcb, 0x9d, 0x7f, 0xff, 0x92, 0x3c, 0xfd, 0x63, 0x5d, 0xc1, 0xf7, + 0xcf, 0xe5, 0xa3, 0xad, 0x88, 0x89, 0x21, 0x2f, 0xbe, 0xef, 0xb2, 0x73, + 0xaf, 0xd9, 0x3b, 0x8e, 0xc3, 0xaf, 0xff, 0xff, 0xf4, 0x4b, 0xe7, 0xba, + 0x91, 0xaf, 0x98, 0x06, 0xc6, 0xcf, 0x99, 0xce, 0x66, 0xc0, 0x3f, 0x4e, + 0xbe, 0xe8, 0xbe, 0xd1, 0xd5, 0x89, 0x81, 0x89, 0x16, 0x8a, 0x3d, 0x09, + 0x6b, 0xff, 0xfe, 0x03, 0xab, 0xa4, 0xfd, 0x74, 0xf4, 0x75, 0x3d, 0xac, + 0x09, 0xd6, 0x61, 0x50, 0xbe, 0xd4, 0xad, 0x97, 0x2a, 0x85, 0xa0, 0xbe, + 0x75, 0xe0, 0x99, 0x64, 0x62, 0x0d, 0x3e, 0xdc, 0x57, 0x90, 0xe6, 0x59, + 0x6f, 0x4c, 0xc6, 0x32, 0x2d, 0x43, 0x2f, 0xd1, 0x94, 0xed, 0xa0, 0xdf, + 0x35, 0xdd, 0xa6, 0x8a, 0xa2, 0xff, 0x72, 0x36, 0x6f, 0x2c, 0xf1, 0xd5, + 0xc3, 0xe2, 0x01, 0x6d, 0xff, 0x9e, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, + 0xd7, 0x79, 0x6f, 0xe3, 0xac, 0xc6, 0x22, 0x1d, 0x64, 0x4e, 0x95, 0x7e, + 0xe3, 0x5d, 0xda, 0x68, 0xab, 0x2f, 0xfa, 0x25, 0x1c, 0x9e, 0x39, 0x39, + 0xd6, 0x63, 0x0f, 0xb0, 0x4c, 0xef, 0xfc, 0xc7, 0x63, 0x7f, 0x47, 0x5d, + 0x5c, 0xeb, 0xff, 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x25, + 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xd2, 0xbf, 0xf3, 0xc9, 0x8c, 0xe3, 0x5d, + 0xda, 0x68, 0x9f, 0x6c, 0xc6, 0x1f, 0xea, 0xcc, 0xef, 0xff, 0x30, 0xb7, + 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x42, 0x5f, 0xba, 0x93, 0xc7, 0x0e, + 0xbf, 0x71, 0xae, 0xed, 0x34, 0x51, 0xf7, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, + 0x9c, 0xeb, 0xff, 0x0c, 0x4d, 0x03, 0x13, 0x76, 0x0e, 0xbf, 0xff, 0xb0, + 0x3d, 0x8f, 0xac, 0x78, 0x5f, 0xfd, 0x6a, 0x3f, 0x2a, 0xfc, 0xc2, 0xde, + 0x4c, 0x42, 0x65, 0xb8, 0x4e, 0x26, 0x7e, 0x39, 0xdb, 0x3c, 0xa8, 0x6c, + 0x8d, 0xe7, 0x9c, 0x2d, 0x91, 0x96, 0x28, 0xa9, 0x3f, 0x44, 0xd8, 0xfd, + 0xf7, 0x85, 0x0a, 0x13, 0xcc, 0x85, 0xd8, 0x67, 0x7e, 0x51, 0xe8, 0xe1, + 0x2f, 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x11, 0x5f, 0xd9, 0xc6, 0xbb, + 0xb4, 0xd1, 0x15, 0xdf, 0xf2, 0xbb, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x5c, + 0x53, 0x08, 0x80, 0x73, 0x8b, 0xff, 0xdf, 0xc0, 0xb5, 0x87, 0xf7, 0xff, + 0x46, 0x47, 0x5f, 0x31, 0x3c, 0xca, 0xe7, 0x59, 0x37, 0x3f, 0x5f, 0xd3, + 0x6f, 0xb3, 0xaf, 0xe3, 0xaf, 0xf6, 0x27, 0x3f, 0xfc, 0x1a, 0x3a, 0xca, + 0x81, 0x3d, 0x4d, 0x10, 0x5f, 0xff, 0xde, 0xd2, 0x75, 0xd2, 0x48, 0x3e, + 0x07, 0x79, 0x87, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x29, 0xeb, 0xfc, 0xb4, + 0x08, 0x1f, 0x92, 0x3a, 0xe5, 0xa1, 0xd5, 0x07, 0x8e, 0xd3, 0x2b, 0xff, + 0xfd, 0x28, 0xf6, 0x80, 0xb6, 0xa7, 0xf1, 0x9d, 0x40, 0x34, 0xeb, 0xff, + 0xfb, 0x9c, 0x07, 0x39, 0x03, 0x8a, 0x27, 0x7b, 0x9f, 0x4e, 0xbf, 0xf9, + 0x25, 0x83, 0xfc, 0x2d, 0x39, 0x23, 0xaf, 0xf4, 0xa3, 0x93, 0xc7, 0x27, + 0x3a, 0xfb, 0xe0, 0xbc, 0x8e, 0xbf, 0x3e, 0x75, 0x16, 0x75, 0x68, 0xf1, + 0xf6, 0x11, 0x54, 0x22, 0x7f, 0x1e, 0xef, 0xfa, 0x05, 0xb9, 0xb3, 0x3d, + 0xa3, 0xaf, 0xcf, 0x3c, 0x70, 0x07, 0x52, 0xa9, 0x59, 0xdc, 0x15, 0xe2, + 0xc3, 0x5e, 0xb7, 0x21, 0x46, 0x07, 0x5c, 0x18, 0x70, 0xec, 0x21, 0xdb, + 0x38, 0xbf, 0xfc, 0xf2, 0x60, 0x22, 0xec, 0xeb, 0x51, 0xf9, 0xd7, 0xff, + 0xbf, 0xfc, 0x1a, 0x63, 0xe8, 0xba, 0xc6, 0x0e, 0xbf, 0xf8, 0x73, 0xf7, + 0x1f, 0xd8, 0x5a, 0x2c, 0xea, 0xe2, 0x24, 0x7c, 0x9b, 0x4c, 0x27, 0x2c, + 0x18, 0x4b, 0xa4, 0x37, 0x2e, 0x0e, 0x1d, 0x7f, 0xf2, 0x07, 0x8f, 0xbb, + 0x1c, 0xe4, 0x4e, 0x75, 0x30, 0x7b, 0x7d, 0x15, 0xb8, 0x30, 0x75, 0xff, + 0xfb, 0xb1, 0xcc, 0x92, 0x3f, 0xb0, 0x28, 0x06, 0x95, 0x7e, 0x89, 0x7e, + 0x09, 0x1d, 0x7c, 0xd7, 0x76, 0x9a, 0x2b, 0x3a, 0x98, 0xf5, 0x78, 0x51, + 0x7d, 0xe4, 0x5e, 0x8e, 0xbf, 0xa7, 0x5c, 0x0c, 0xb4, 0x75, 0xfb, 0x3d, + 0xaf, 0xba, 0x3a, 0xf4, 0x4e, 0x87, 0x5f, 0xbd, 0xff, 0xd1, 0x91, 0xd7, + 0x80, 0xfa, 0x3a, 0xff, 0xb2, 0x48, 0x05, 0x75, 0x6f, 0xf5, 0x9d, 0x7e, + 0xc9, 0xa7, 0x07, 0xe7, 0x59, 0x88, 0x54, 0x42, 0x11, 0x5c, 0x85, 0x3e, + 0xe4, 0x7c, 0x21, 0x59, 0x6f, 0x4a, 0x5c, 0x6c, 0x4a, 0xb4, 0x37, 0xf5, + 0x06, 0xff, 0xdd, 0x4f, 0x3f, 0x27, 0x84, 0x09, 0xd7, 0xef, 0x20, 0xe2, + 0xce, 0xbe, 0x93, 0x8b, 0x18, 0x7c, 0x5b, 0x47, 0xb7, 0xfe, 0x79, 0x31, + 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x2d, 0xff, 0x9f, 0xcc, 0x42, 0x71, 0x3c, + 0x03, 0xa9, 0x84, 0x43, 0xba, 0x55, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, + 0x4d, 0xff, 0xef, 0x6b, 0xee, 0x98, 0xc9, 0xd0, 0x65, 0xa3, 0xa9, 0x84, + 0x42, 0xe1, 0xc5, 0xff, 0xfe, 0x74, 0xf0, 0x38, 0xfa, 0x61, 0xbd, 0x4e, + 0x44, 0xb4, 0x75, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, 0xc5, 0xff, 0xfc, + 0xa8, 0xef, 0xc1, 0xce, 0x7b, 0x5d, 0x9b, 0xe7, 0xce, 0xed, 0x9d, 0x7b, + 0x80, 0xe9, 0xd7, 0x79, 0x88, 0x44, 0x37, 0x1a, 0xa9, 0x84, 0x76, 0xa4, + 0x2f, 0xaf, 0x66, 0xb0, 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x6d, 0xdf, 0x6a, + 0x77, 0xe1, 0xd5, 0xc3, 0xcf, 0xf1, 0x6d, 0xfc, 0x9d, 0xf2, 0x7e, 0x03, + 0xaf, 0xfa, 0x25, 0x1c, 0x9e, 0x39, 0x39, 0xd6, 0x62, 0x48, 0xf1, 0xc6, + 0x99, 0x88, 0x84, 0xb6, 0xff, 0xf6, 0x0f, 0xec, 0x2d, 0xc3, 0x98, 0x2a, + 0x1d, 0x79, 0x55, 0xd0, 0x9d, 0x7a, 0x7e, 0xa1, 0xd7, 0xfe, 0x55, 0x2a, + 0x95, 0xa7, 0xbb, 0x83, 0x1f, 0x9d, 0x7f, 0x40, 0xc8, 0x20, 0x59, 0xd7, + 0xcd, 0x77, 0x69, 0xa2, 0xf0, 0xbf, 0xf3, 0xfa, 0x36, 0x73, 0x99, 0xbe, + 0x8e, 0xae, 0x1f, 0x68, 0x96, 0xdf, 0x7b, 0x6f, 0x3a, 0x75, 0xf9, 0x70, + 0x32, 0x73, 0xaf, 0xf4, 0xa0, 0x7d, 0xb1, 0xda, 0x75, 0xfe, 0x8f, 0x3f, + 0x7e, 0x06, 0x0e, 0xbf, 0xf7, 0xd5, 0xef, 0x2f, 0x60, 0xfb, 0x47, 0x5d, + 0x8a, 0x1d, 0x50, 0x7a, 0xf8, 0x83, 0x7c, 0x93, 0xe2, 0xce, 0xbf, 0x60, + 0xff, 0xb5, 0x07, 0x5f, 0xa3, 0xe8, 0x1f, 0x47, 0x5f, 0xfe, 0xc5, 0xc3, + 0x7e, 0x60, 0x82, 0x59, 0xa3, 0xaf, 0xfe, 0xce, 0xf5, 0xe4, 0xb4, 0x8e, + 0x48, 0xeb, 0xa3, 0xf3, 0xaa, 0x47, 0xb1, 0xe4, 0x2a, 0x54, 0x2b, 0x9d, + 0x55, 0x10, 0x2a, 0xf1, 0xc9, 0xd3, 0x32, 0x13, 0x3b, 0x90, 0xa1, 0x24, + 0xc4, 0xab, 0x33, 0xec, 0x22, 0x9c, 0x83, 0xf2, 0x11, 0x29, 0xd1, 0x47, + 0xa1, 0x43, 0x7f, 0xb7, 0x63, 0x3f, 0x7e, 0x68, 0xeb, 0xfd, 0xfb, 0x13, + 0x4a, 0x07, 0xc7, 0x53, 0x09, 0xaa, 0xc4, 0x3a, 0xf8, 0x6b, 0x79, 0x33, + 0x73, 0xaf, 0x9a, 0xee, 0xd3, 0x45, 0xe9, 0x7f, 0xe4, 0xf7, 0x45, 0xe5, + 0xfb, 0xfe, 0x75, 0x70, 0xfa, 0xd6, 0x5b, 0x79, 0x69, 0xe3, 0xaf, 0xf9, + 0xfd, 0x28, 0x53, 0xc9, 0x39, 0xd4, 0xb3, 0xd4, 0x11, 0xbb, 0xf6, 0x2f, + 0xae, 0x13, 0xa8, 0x29, 0xa1, 0xe4, 0x21, 0xbe, 0xbb, 0x6d, 0x10, 0xdf, + 0xff, 0xf2, 0x6c, 0xc1, 0x60, 0x38, 0x1e, 0xe2, 0xd6, 0xf2, 0xc1, 0x3a, + 0x98, 0x45, 0x66, 0x23, 0xd4, 0x36, 0xc7, 0xf3, 0xc2, 0xfe, 0x50, 0x98, + 0xc9, 0xd4, 0xe6, 0xc2, 0x59, 0x25, 0x22, 0x4d, 0x18, 0x3f, 0x21, 0x84, + 0xb8, 0x54, 0x74, 0x8f, 0xf8, 0xd3, 0x46, 0x31, 0x9d, 0x21, 0x82, 0x74, + 0xed, 0x99, 0x44, 0xb7, 0x03, 0xa7, 0x5f, 0xfc, 0x08, 0x98, 0x73, 0x63, + 0xad, 0x68, 0x75, 0xf6, 0x75, 0xfc, 0x75, 0xfe, 0xc4, 0xe7, 0xff, 0x83, + 0x47, 0x59, 0x50, 0xa2, 0x26, 0x05, 0x13, 0x44, 0x17, 0xde, 0x8d, 0xe7, + 0x3a, 0xff, 0xbd, 0xac, 0xde, 0x5d, 0x02, 0x87, 0x52, 0x1e, 0xf0, 0x91, + 0xdf, 0x46, 0xc8, 0x91, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0x8e, 0xff, + 0xfb, 0xa0, 0xd6, 0xb1, 0x63, 0x9b, 0x3e, 0x42, 0xb0, 0x75, 0xff, 0x44, + 0xfc, 0xcf, 0x79, 0x3c, 0x75, 0xe1, 0x8d, 0xce, 0xa9, 0x1e, 0x98, 0x4e, + 0x2f, 0xfb, 0x39, 0x9a, 0xc7, 0x19, 0xce, 0xbd, 0x81, 0x59, 0xd7, 0xff, + 0xfb, 0xae, 0x9e, 0x8e, 0x8e, 0x7b, 0xa9, 0xdc, 0x46, 0x4e, 0xbf, 0xff, + 0xfd, 0xef, 0x22, 0xf8, 0x99, 0xb8, 0x83, 0xd1, 0xdf, 0x9b, 0x13, 0xd3, + 0x41, 0xd5, 0x08, 0xd8, 0xc5, 0xdb, 0xfc, 0xeb, 0xce, 0x4a, 0x16, 0x75, + 0xd3, 0xac, 0xab, 0x99, 0x64, 0xab, 0xff, 0x30, 0xde, 0xa4, 0xdd, 0x89, + 0xd8, 0xfc, 0xd7, 0xb2, 0x2f, 0x7d, 0xb2, 0x3d, 0x07, 0x54, 0x8f, 0xf5, + 0x16, 0xef, 0xec, 0x75, 0xe6, 0xfe, 0x3a, 0xff, 0x3b, 0x1a, 0x4e, 0x3f, + 0xe7, 0x59, 0x5c, 0xeb, 0xfe, 0x8c, 0xde, 0x1e, 0x4f, 0x23, 0xa9, 0x59, + 0x3c, 0x90, 0x89, 0xdf, 0xca, 0xe3, 0x9d, 0x7f, 0x1d, 0x7f, 0x42, 0x98, + 0x28, 0xa1, 0xd7, 0xf6, 0x7b, 0x6b, 0xd9, 0xd3, 0xab, 0x11, 0x12, 0x25, + 0xda, 0x2c, 0xbf, 0xff, 0x9a, 0xc7, 0x1c, 0x53, 0xcc, 0x72, 0x3c, 0x2f, + 0xf9, 0xd4, 0xad, 0xaf, 0x58, 0x2a, 0xa1, 0x5d, 0x10, 0x98, 0x91, 0x06, + 0x11, 0x34, 0xcf, 0x78, 0x55, 0x21, 0x14, 0xc6, 0xdc, 0x87, 0x9f, 0x48, + 0x5e, 0x1b, 0xbf, 0x90, 0x89, 0x66, 0x9f, 0x3d, 0x0b, 0x0d, 0x85, 0xd7, + 0x6d, 0x74, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x5d, 0x7e, 0xf7, 0xff, + 0x46, 0x45, 0x5f, 0xb5, 0xee, 0xc7, 0xe7, 0x5f, 0x9e, 0x78, 0xe0, 0x0e, + 0xb3, 0x13, 0xa3, 0x17, 0x06, 0x5c, 0xcc, 0x05, 0x5b, 0x65, 0x14, 0xc2, + 0xa2, 0x89, 0x47, 0xab, 0x7f, 0xf2, 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, + 0x44, 0xcd, 0x7f, 0x2a, 0xca, 0xd1, 0x51, 0xa8, 0xf1, 0xd7, 0xb7, 0x8d, + 0x1d, 0x79, 0xa8, 0xb3, 0xaf, 0x95, 0x5e, 0x71, 0x3a, 0xed, 0xb5, 0x64, + 0xeb, 0xb0, 0x07, 0x5f, 0xfe, 0xec, 0x2d, 0xfd, 0x9b, 0xfe, 0xbf, 0xbd, + 0x3a, 0xfe, 0xf6, 0x4f, 0x9f, 0xcc, 0x75, 0xfe, 0xf9, 0x82, 0xfc, 0xff, + 0x6c, 0xeb, 0xff, 0xf2, 0xdf, 0xb9, 0xbf, 0xfd, 0x65, 0xfb, 0x37, 0x40, + 0x75, 0x05, 0x12, 0x18, 0x6f, 0x76, 0xb0, 0xeb, 0xb6, 0xbc, 0x75, 0x95, + 0x27, 0x5b, 0xf8, 0x35, 0xa0, 0x19, 0xbf, 0xff, 0xf2, 0x0c, 0x34, 0x61, + 0x7f, 0x23, 0x9c, 0x4d, 0x9c, 0x77, 0xfc, 0xea, 0x56, 0x55, 0x1b, 0x34, + 0x79, 0x05, 0x66, 0x4d, 0xec, 0x2f, 0xdc, 0x8b, 0xf4, 0x2f, 0x13, 0xdf, + 0xcc, 0xc0, 0x8e, 0x78, 0xeb, 0xe7, 0xea, 0x4c, 0x75, 0xf7, 0x66, 0x80, + 0x9d, 0x58, 0x7d, 0xcd, 0x2b, 0x72, 0x1b, 0xfc, 0xd4, 0xc1, 0x0f, 0x60, + 0xea, 0x3a, 0xfd, 0xd7, 0xf4, 0xbf, 0x3a, 0xff, 0xf7, 0xce, 0xba, 0x7b, + 0xf0, 0x08, 0xbc, 0x8e, 0xac, 0x45, 0x63, 0x4c, 0x10, 0x29, 0x65, 0x17, + 0xff, 0xff, 0xff, 0xff, 0x95, 0x7a, 0xa3, 0x15, 0x7a, 0xa9, 0x5a, 0x2b, + 0x46, 0xaa, 0x61, 0x57, 0x2a, 0xb9, 0x3e, 0xd6, 0x00, 0x2a, 0xd6, 0x36, + 0xf7, 0xfb, 0xd5, 0x54, 0x42, 0xa9, 0x5d, 0x56, 0xf7, 0xcf, 0x9d, 0xdb, + 0x3a, 0xff, 0xfd, 0xfe, 0xf2, 0xe8, 0x23, 0x8c, 0x75, 0x1a, 0xfc, 0x3a, + 0xff, 0xed, 0xd9, 0x8f, 0x05, 0x15, 0xf5, 0x0b, 0x3a, 0xff, 0xff, 0xc8, + 0xb4, 0xe7, 0x41, 0xa9, 0x46, 0xce, 0x40, 0xfb, 0xb9, 0x23, 0xaf, 0xfc, + 0x9e, 0x46, 0xa0, 0x7d, 0x8d, 0x3a, 0xb1, 0x1e, 0x1e, 0x48, 0xda, 0x6c, + 0xbe, 0xf6, 0xde, 0x74, 0xeb, 0xff, 0xfc, 0xe2, 0xd1, 0xc0, 0xf4, 0x1f, + 0x3b, 0x12, 0xe4, 0x4e, 0x75, 0x62, 0x21, 0x40, 0x49, 0x7f, 0xff, 0x9d, + 0x41, 0xcf, 0xc1, 0xaf, 0x92, 0x4e, 0xc3, 0x45, 0xce, 0xbe, 0xf2, 0x75, + 0x0e, 0xbf, 0xe7, 0xe4, 0xbe, 0x63, 0x43, 0x87, 0x52, 0xa9, 0x70, 0x1a, + 0x23, 0x2b, 0xc8, 0xd2, 0x3b, 0x0b, 0x77, 0x22, 0x16, 0x10, 0x10, 0x5b, + 0x87, 0x5f, 0xde, 0xc5, 0xef, 0x8b, 0x3a, 0xdd, 0xc3, 0x7a, 0x82, 0x17, + 0xf8, 0x01, 0x79, 0x69, 0x24, 0x75, 0xff, 0xf8, 0x28, 0x33, 0xe6, 0x91, + 0xfa, 0xc3, 0x2c, 0xb2, 0x55, 0xfd, 0xee, 0xc4, 0xfd, 0x01, 0xd7, 0xf6, + 0xf2, 0xd7, 0xe0, 0x98, 0xeb, 0xfe, 0x9f, 0x3f, 0x08, 0x1f, 0x92, 0x3a, + 0xf3, 0xbb, 0x4d, 0x16, 0x7d, 0xfd, 0xfb, 0x8c, 0x91, 0x67, 0x54, 0xe8, + 0x8d, 0x69, 0xd7, 0xe4, 0xf7, 0xfe, 0x4e, 0xc4, 0x93, 0xd1, 0xed, 0x1d, + 0x7f, 0xfb, 0x9d, 0x7f, 0x99, 0xb0, 0x73, 0x58, 0x27, 0x5f, 0xfd, 0xaf, + 0x24, 0xcc, 0xb8, 0x63, 0x7d, 0x1d, 0x48, 0x89, 0x00, 0x25, 0x5e, 0x65, + 0x96, 0x4a, 0xbf, 0xf3, 0xcb, 0x43, 0x8d, 0x0e, 0x70, 0xa6, 0x0b, 0xfb, + 0xf6, 0xd0, 0x17, 0x81, 0x3a, 0xff, 0x7b, 0xb9, 0xb3, 0xe4, 0x96, 0x75, + 0x61, 0xf0, 0x80, 0xaa, 0xff, 0xdb, 0xc8, 0x41, 0xff, 0xc6, 0xaf, 0xf3, + 0xae, 0x85, 0x0e, 0xa8, 0x3d, 0xa9, 0xd1, 0x2f, 0xf7, 0x50, 0x22, 0xef, + 0x31, 0xd7, 0xf8, 0x3d, 0x03, 0xff, 0xb7, 0x87, 0x54, 0x1f, 0x3a, 0x18, + 0xdf, 0xf2, 0x08, 0x7e, 0x84, 0x1e, 0xd1, 0xd7, 0xa0, 0x54, 0x3a, 0xa4, + 0xba, 0x00, 0x12, 0x56, 0x99, 0x6e, 0xb1, 0x31, 0x77, 0x21, 0x7c, 0xb3, + 0x2e, 0xc3, 0x33, 0xf4, 0x11, 0x85, 0x6e, 0x9e, 0xfd, 0x08, 0x9d, 0x84, + 0x1f, 0x4e, 0xaf, 0xfb, 0x8e, 0xcf, 0x52, 0x39, 0x07, 0x5f, 0xfb, 0x89, + 0xa9, 0x7d, 0xec, 0x0c, 0x1d, 0x7d, 0xc4, 0x85, 0x9d, 0x7f, 0xfe, 0xf2, + 0x80, 0x8c, 0x0f, 0x73, 0x5b, 0xca, 0x3a, 0x75, 0x71, 0x16, 0x8b, 0x3e, + 0x12, 0x0b, 0x9e, 0x47, 0x5f, 0xff, 0xff, 0xc2, 0xec, 0xfb, 0x3a, 0x39, + 0xe0, 0x7e, 0xb7, 0x93, 0x86, 0x05, 0xf8, 0xf2, 0x3a, 0xff, 0x67, 0x7a, + 0x0f, 0x38, 0x9d, 0x7c, 0xb4, 0x9b, 0x47, 0x59, 0x02, 0x8e, 0xd9, 0x85, + 0x79, 0x08, 0x55, 0x98, 0xdf, 0xb9, 0x36, 0xcc, 0x09, 0xd7, 0xfe, 0xc6, + 0x76, 0xb9, 0x9b, 0x42, 0x06, 0x4e, 0xa8, 0x4f, 0x4f, 0xb1, 0x8e, 0x3a, + 0x40, 0x95, 0x5f, 0xff, 0xff, 0x7f, 0xac, 0xc1, 0x53, 0xef, 0x06, 0x33, + 0xac, 0x68, 0x72, 0x75, 0xe2, 0xce, 0xbf, 0x7d, 0x81, 0xfa, 0xb3, 0xab, + 0x11, 0x53, 0xe7, 0xfb, 0xf6, 0xc7, 0xec, 0x7d, 0x3a, 0xb0, 0xf3, 0x10, + 0x8a, 0xf6, 0xa2, 0x73, 0xaf, 0xfa, 0x31, 0xbd, 0x4d, 0x8f, 0xc3, 0xae, + 0xce, 0x9d, 0x42, 0x79, 0xbb, 0x67, 0x15, 0x24, 0x56, 0xe8, 0x83, 0xcd, + 0x37, 0xba, 0x06, 0x4e, 0xbd, 0xf8, 0x1a, 0x75, 0xef, 0x67, 0xd3, 0xaf, + 0xe8, 0xdf, 0x5f, 0x39, 0x07, 0x5e, 0x08, 0x1a, 0x75, 0xf0, 0x46, 0x24, + 0x75, 0x21, 0xbc, 0x71, 0xca, 0x0a, 0x38, 0x77, 0x1d, 0x41, 0xd5, 0x8e, + 0xf5, 0xae, 0xec, 0x69, 0xd7, 0xf7, 0x13, 0x66, 0x0e, 0x8e, 0xbf, 0xb7, + 0xf6, 0x74, 0x0a, 0xe7, 0x5f, 0xdc, 0xce, 0xf4, 0x1e, 0x3a, 0xfd, 0xd1, + 0x8c, 0xe1, 0x97, 0xf6, 0x72, 0x70, 0x38, 0x4d, 0x10, 0x6b, 0x06, 0x96, + 0xdc, 0x9d, 0x13, 0xb2, 0x52, 0xa8, 0x47, 0xc2, 0x43, 0x3a, 0xfc, 0xed, + 0x45, 0xc1, 0xd7, 0xf4, 0xba, 0x2f, 0xbf, 0x8e, 0xb6, 0x34, 0xf4, 0x84, + 0x96, 0xfd, 0x1e, 0xf8, 0xb6, 0x4e, 0xbf, 0xd2, 0x45, 0xc7, 0x7e, 0x84, + 0xeb, 0xff, 0xd1, 0x83, 0xbf, 0xb3, 0x89, 0x3b, 0xac, 0xeb, 0xf3, 0xb3, + 0xec, 0xee, 0x8f, 0xf3, 0xc6, 0x94, 0xad, 0xaa, 0xbd, 0x81, 0x59, 0x46, + 0x4b, 0x8f, 0x1c, 0x26, 0x18, 0x53, 0x5e, 0xd6, 0x48, 0xeb, 0xf2, 0x6f, + 0x24, 0x13, 0xaf, 0x27, 0x70, 0xeb, 0xa1, 0x78, 0x78, 0x0d, 0x26, 0xbe, + 0x0e, 0xbb, 0x07, 0x5f, 0x87, 0x8c, 0xbc, 0xe7, 0x56, 0x1e, 0x4b, 0x90, + 0xdc, 0x01, 0x3a, 0xa1, 0x30, 0x54, 0x5b, 0xe3, 0xae, 0x88, 0x2f, 0x77, + 0x04, 0xeb, 0xfd, 0x34, 0x4e, 0xb7, 0x9a, 0x0e, 0xbf, 0xfe, 0x75, 0x3d, + 0x1c, 0xff, 0x91, 0xe1, 0x7f, 0xce, 0xbf, 0xff, 0x85, 0xd4, 0xf9, 0xf4, + 0x5f, 0xda, 0x4d, 0xfa, 0x8c, 0x9d, 0x58, 0x8f, 0xd7, 0x1a, 0x13, 0x40, + 0x28, 0x5d, 0xad, 0x87, 0x5f, 0x20, 0xb8, 0x4e, 0xbf, 0xf2, 0xf3, 0xda, + 0xfb, 0xa7, 0x96, 0x1d, 0x7e, 0xd4, 0x73, 0xd0, 0x73, 0x06, 0xfe, 0x82, + 0x89, 0x5d, 0x2f, 0x5f, 0xbe, 0xcc, 0xef, 0xc3, 0xaf, 0xbb, 0x89, 0xb0, + 0xeb, 0xfb, 0x49, 0xcc, 0x07, 0x0e, 0xbf, 0xff, 0xd1, 0x37, 0xc4, 0x68, + 0x39, 0xa0, 0x7c, 0x5a, 0x7b, 0xa8, 0x75, 0x62, 0x75, 0x89, 0x0a, 0xd5, + 0x91, 0xf4, 0xa7, 0xc4, 0x5b, 0x45, 0x97, 0x2d, 0x50, 0x68, 0xbf, 0x2f, + 0xb5, 0xcc, 0xc3, 0xaf, 0xfe, 0x97, 0x81, 0x29, 0x2f, 0xde, 0x85, 0x9d, + 0x7f, 0xbd, 0xa8, 0x9f, 0x34, 0x13, 0xae, 0xee, 0x1d, 0x7f, 0xfd, 0xd8, + 0x0e, 0x37, 0xe6, 0x0e, 0x07, 0xb0, 0x75, 0xff, 0xc9, 0x83, 0x99, 0xaf, + 0x92, 0xd2, 0xce, 0xbf, 0xf3, 0xc6, 0xf2, 0xf9, 0xad, 0xc3, 0x07, 0x50, + 0x53, 0x7f, 0xdc, 0x81, 0x11, 0x55, 0xcc, 0xe6, 0x15, 0xd2, 0x77, 0x90, + 0xef, 0x29, 0x1c, 0x3a, 0xfe, 0x0c, 0x7f, 0xcc, 0xdc, 0xea, 0x60, 0xf2, + 0x96, 0x39, 0x7f, 0xa1, 0x78, 0x9c, 0x9a, 0x47, 0x5c, 0x93, 0x1d, 0x7f, + 0xfb, 0xd1, 0xd1, 0x79, 0xe3, 0x9c, 0x79, 0x1d, 0x7b, 0xc9, 0x39, 0xd7, + 0xef, 0xdf, 0x78, 0x98, 0xeb, 0xc3, 0x0d, 0x3a, 0xff, 0xe0, 0xa4, 0xdd, + 0x8e, 0x6f, 0x28, 0xe1, 0xd7, 0xff, 0x90, 0x5f, 0x7d, 0x6b, 0x38, 0x1e, + 0xe1, 0xd5, 0xf1, 0x34, 0xa4, 0x16, 0x5a, 0x43, 0x8e, 0x09, 0x4e, 0x86, + 0xb6, 0x91, 0x6d, 0x07, 0x5e, 0xea, 0x78, 0xeb, 0x6c, 0xc3, 0x55, 0xf4, + 0x3e, 0xa1, 0x74, 0x44, 0x2b, 0xd9, 0x1d, 0x32, 0x42, 0xcf, 0xa4, 0x6f, + 0x1b, 0xe7, 0xf0, 0x91, 0xbf, 0xec, 0x19, 0x0e, 0x2e, 0x1a, 0x75, 0xfb, + 0xa9, 0xb3, 0x02, 0x75, 0xff, 0x83, 0x03, 0x82, 0x09, 0x66, 0x8e, 0xbf, + 0x3a, 0xd3, 0x6b, 0x0e, 0xbd, 0xe8, 0xdc, 0xea, 0xc3, 0xc4, 0x72, 0x8b, + 0xd0, 0x93, 0x1d, 0x78, 0x55, 0x9d, 0xa3, 0xaf, 0xd9, 0x3a, 0xe3, 0x47, + 0x5f, 0xff, 0xfa, 0x3a, 0x8b, 0x62, 0x69, 0x3f, 0x3e, 0xf5, 0x37, 0xd3, + 0x52, 0x73, 0xa8, 0x29, 0xe9, 0x28, 0x6a, 0x85, 0x13, 0x3f, 0xf4, 0x80, + 0x46, 0xf4, 0x47, 0xb4, 0x4f, 0x7f, 0x3f, 0x23, 0xbf, 0x42, 0x75, 0xf4, + 0x24, 0xf0, 0x75, 0xf3, 0x2f, 0x9a, 0x3a, 0xff, 0xa4, 0xb7, 0x97, 0xb5, + 0x0a, 0x1d, 0x50, 0x7b, 0x4e, 0x43, 0x7b, 0x48, 0x27, 0x5f, 0x85, 0xbf, + 0x35, 0xb9, 0xd5, 0x87, 0x88, 0xe3, 0x54, 0xe9, 0x96, 0x7e, 0x5c, 0x2f, + 0x40, 0x64, 0xba, 0x79, 0x1d, 0x79, 0x3a, 0x87, 0x56, 0xe6, 0xc7, 0xc2, + 0xf7, 0xdf, 0x40, 0xfa, 0x3a, 0xff, 0x48, 0x03, 0x3e, 0x93, 0x73, 0xaf, + 0xbf, 0xff, 0x37, 0x3a, 0xfe, 0xda, 0xf6, 0x38, 0xb4, 0xeb, 0xfe, 0x03, + 0xc8, 0x39, 0x9f, 0xe8, 0xeb, 0xfd, 0xfa, 0x6f, 0xbc, 0xb3, 0xc7, 0x57, + 0x4f, 0xb7, 0x47, 0x17, 0xed, 0xf4, 0xb4, 0x57, 0x3a, 0xff, 0xfd, 0x9a, + 0xf9, 0xd7, 0x4f, 0x7e, 0x01, 0x17, 0x91, 0xd5, 0x08, 0x80, 0x12, 0xbb, + 0xf9, 0xe7, 0xfd, 0xc4, 0x27, 0x54, 0xc9, 0xf1, 0xf0, 0xd3, 0xa4, 0x9e, + 0x84, 0xde, 0xc8, 0x51, 0x6d, 0x90, 0xdf, 0xf7, 0x7e, 0xc3, 0x76, 0xf3, + 0x90, 0x75, 0x42, 0xaa, 0xac, 0x94, 0x0c, 0xed, 0x17, 0x4c, 0x03, 0xac, + 0xb3, 0xab, 0x73, 0x4e, 0xa9, 0x17, 0xbf, 0xfa, 0x39, 0x9b, 0x1e, 0x5f, + 0xe6, 0x04, 0xeb, 0xf9, 0xf7, 0x90, 0xc0, 0x4e, 0xbf, 0xe8, 0xde, 0x48, + 0x2b, 0x7f, 0x1d, 0x4e, 0x7c, 0x62, 0x59, 0x7e, 0x79, 0x64, 0xf0, 0x75, + 0xff, 0xd1, 0xad, 0x62, 0xfc, 0x30, 0xbd, 0x1d, 0x7f, 0xf2, 0x46, 0x85, + 0xe5, 0xf3, 0x59, 0xc3, 0xaf, 0xff, 0xf2, 0x6a, 0x7c, 0x67, 0x04, 0x1b, + 0x50, 0xc6, 0x0b, 0xf0, 0xeb, 0xfd, 0xbc, 0xb5, 0x34, 0xa2, 0x73, 0xa8, + 0x29, 0xa1, 0xb4, 0x98, 0x50, 0xbc, 0x86, 0x06, 0x2b, 0xff, 0xff, 0x75, + 0x37, 0xf6, 0x6f, 0xee, 0x72, 0x3d, 0xff, 0xd1, 0x97, 0x70, 0xeb, 0xe0, + 0x85, 0xc4, 0xeb, 0xff, 0x4a, 0x07, 0xdc, 0x4d, 0x98, 0x13, 0xaf, 0xfc, + 0xfd, 0x6a, 0x3f, 0xcd, 0x3f, 0x4e, 0xbf, 0xff, 0x68, 0x7e, 0x75, 0xd3, + 0xdf, 0x80, 0x45, 0xe4, 0x75, 0xfe, 0xea, 0x29, 0xb6, 0x0e, 0x28, 0x75, + 0xff, 0x43, 0x2b, 0xec, 0x20, 0xce, 0x75, 0xff, 0xf0, 0xe6, 0xb1, 0x70, + 0xdc, 0xf2, 0x73, 0x0e, 0xb6, 0x35, 0x17, 0x7e, 0x38, 0xd8, 0x71, 0x7f, + 0x4f, 0x9c, 0x46, 0xc1, 0xd7, 0xc2, 0x18, 0x59, 0xd7, 0xed, 0x98, 0x20, + 0x73, 0xaf, 0xe7, 0xff, 0x02, 0xf2, 0x3a, 0xa0, 0xfc, 0xf0, 0x81, 0x09, + 0xe9, 0x11, 0x97, 0xd8, 0x4f, 0xd4, 0x2e, 0xdf, 0xce, 0x4c, 0x18, 0x53, + 0xe4, 0x6c, 0x6d, 0x4a, 0x47, 0x09, 0x88, 0x3a, 0x7d, 0xf9, 0xf0, 0xc6, + 0x21, 0xe8, 0xc0, 0xaf, 0xfe, 0xc1, 0xff, 0x33, 0x9a, 0xf4, 0x61, 0xd7, + 0xfd, 0xbf, 0xb3, 0x89, 0x3b, 0xac, 0xeb, 0x67, 0xe7, 0xf4, 0x28, 0x37, + 0x95, 0x32, 0x43, 0xaf, 0xa0, 0x5e, 0x47, 0x5f, 0xb1, 0x5d, 0xc7, 0xff, + 0x86, 0xfb, 0x83, 0xf7, 0xf6, 0xce, 0xa4, 0x73, 0x47, 0x5f, 0xff, 0xa0, + 0x65, 0x9d, 0x45, 0x87, 0x26, 0x8c, 0xe1, 0xd7, 0xcd, 0xea, 0x4c, 0x75, + 0xff, 0xf8, 0x71, 0x45, 0x10, 0x3d, 0x49, 0xba, 0x9b, 0xf8, 0xea, 0x83, + 0xf9, 0xc2, 0x2b, 0xcd, 0x7e, 0x1d, 0x7e, 0xd3, 0x63, 0x8a, 0x1d, 0x5d, + 0x3c, 0x3f, 0xc6, 0xef, 0xf6, 0x4b, 0x10, 0x3d, 0x43, 0xaf, 0xbd, 0x25, + 0xf4, 0xeb, 0xe4, 0x51, 0x19, 0x3a, 0xb0, 0xf1, 0x04, 0x8a, 0xef, 0x98, + 0x75, 0xf6, 0x86, 0x16, 0x75, 0x41, 0xb7, 0xdc, 0x5e, 0xfb, 0x3b, 0x25, + 0x9d, 0x50, 0xac, 0xce, 0x4c, 0xb8, 0x84, 0xa1, 0x77, 0x61, 0x96, 0xec, + 0x62, 0x47, 0xa7, 0x40, 0x2b, 0xed, 0x90, 0xde, 0x0a, 0xda, 0x75, 0xba, + 0x75, 0xda, 0x91, 0xd5, 0xf9, 0xa6, 0x00, 0x85, 0xfd, 0x3c, 0xd2, 0x55, + 0x72, 0x73, 0xaf, 0x3e, 0x70, 0xeb, 0xc3, 0x9e, 0x3a, 0xba, 0x6d, 0x04, + 0x6a, 0xef, 0x09, 0xd7, 0xa3, 0x7d, 0x1d, 0x7c, 0x83, 0x2c, 0x3a, 0xf4, + 0xee, 0x27, 0x50, 0x4f, 0x59, 0x63, 0x9e, 0x1f, 0xbf, 0x67, 0xba, 0x9e, + 0x3a, 0xfc, 0xfb, 0xe6, 0xfe, 0x3a, 0xca, 0x74, 0xf3, 0xbc, 0x4d, 0x72, + 0x70, 0xeb, 0xfa, 0x7f, 0x93, 0xbb, 0xf4, 0xea, 0x56, 0x53, 0xdf, 0x86, + 0x99, 0x10, 0x63, 0x5a, 0x3e, 0xf4, 0xa5, 0xc5, 0x6f, 0xfb, 0x02, 0x14, + 0xdf, 0x37, 0xf1, 0xd7, 0xcd, 0x18, 0x91, 0xd5, 0xd3, 0xd9, 0x73, 0x9b, + 0xfd, 0x19, 0xe8, 0xeb, 0x84, 0xea, 0x9c, 0xf4, 0x42, 0x43, 0x7f, 0xf0, + 0x60, 0x3c, 0x8f, 0x23, 0x50, 0x27, 0x5f, 0x4d, 0x1b, 0x52, 0x3a, 0xfe, + 0xf3, 0x42, 0x15, 0xf0, 0xeb, 0xfe, 0x9b, 0x5b, 0x1c, 0x67, 0x00, 0x4e, + 0xbe, 0xcf, 0x62, 0xce, 0xb8, 0x54, 0x3a, 0xda, 0x73, 0x6c, 0x02, 0x0b, + 0xfb, 0xa0, 0x9e, 0x6e, 0xa1, 0xd7, 0xc2, 0x39, 0xe3, 0xaa, 0x13, 0x9e, + 0x09, 0x1e, 0x21, 0x28, 0x4a, 0x85, 0xd3, 0x39, 0x74, 0x9b, 0xc5, 0xf7, + 0xf7, 0xc9, 0xa3, 0xc3, 0xb0, 0xeb, 0xff, 0xc3, 0x1b, 0x39, 0x1c, 0xc4, + 0xec, 0x04, 0xeb, 0xc2, 0xeb, 0x3a, 0xa4, 0x89, 0x3c, 0x31, 0x44, 0x8b, + 0x30, 0xac, 0xbb, 0xa0, 0xd5, 0x6c, 0xf1, 0x5a, 0x0e, 0x2b, 0x51, 0xb8, + 0x94, 0xb5, 0x3c, 0x3a, 0xe5, 0x0d, 0x90, 0xce, 0x20, 0xe4, 0xed, 0xaa, + 0x90, 0xdc, 0x6c, 0xab, 0xed, 0xe3, 0xe3, 0x48, 0xc4, 0x66, 0x96, 0x0f, + 0xc8, 0xda, 0xd7, 0x19, 0xcf, 0x67, 0xbd, 0xde, 0x52, 0x67, 0xf1, 0xd0, + 0xaa, 0x5b, 0x86, 0x56, 0x66, 0xa7, 0x87, 0x3d, 0x38, 0xbc, 0x08, 0x49, + 0x32, 0x85, 0xb7, 0x28, 0x07, 0xec, 0xaa, 0xed, 0xa8, 0xc1, 0x29, 0x87, + 0x79, 0x27, 0xdb, 0x74, 0xbb, 0x7f, 0xf9, 0x85, 0xbc, 0x98, 0xce, 0x35, + 0xdd, 0xa6, 0x89, 0xb2, 0xff, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x15, 0x6d, + 0xfe, 0x94, 0x81, 0xe1, 0x89, 0x1d, 0x7d, 0x9d, 0x7f, 0x1d, 0x65, 0x46, + 0x1e, 0x90, 0x99, 0x5f, 0xee, 0x63, 0x63, 0xff, 0xab, 0x3a, 0xff, 0xa3, + 0xb1, 0x3f, 0x23, 0x02, 0x75, 0x70, 0xfb, 0x3a, 0x6b, 0x7e, 0x8e, 0x2f, + 0xa1, 0x3a, 0xf0, 0x70, 0x4e, 0xbc, 0xee, 0xd3, 0x45, 0x69, 0x7e, 0x53, + 0x7d, 0x03, 0x73, 0xa9, 0xa7, 0xa4, 0x84, 0xf7, 0xff, 0x93, 0xd2, 0x86, + 0xf5, 0x3d, 0xa7, 0xdc, 0xea, 0xe1, 0xf5, 0x6c, 0x21, 0xbf, 0xfd, 0xd4, + 0x5c, 0x37, 0x17, 0x83, 0xed, 0xb3, 0xaf, 0xff, 0x9b, 0x1c, 0xcf, 0xdd, + 0x6f, 0x28, 0x46, 0x9d, 0x7f, 0xfd, 0x2d, 0x60, 0xc2, 0xdf, 0x3d, 0xe8, + 0x59, 0xd7, 0x7b, 0xd0, 0x89, 0x97, 0x4d, 0xbf, 0xff, 0xfd, 0x1b, 0x13, + 0xda, 0xc5, 0x1b, 0xd4, 0xf6, 0x4c, 0x30, 0xb9, 0xf1, 0x93, 0xaf, 0xf4, + 0x79, 0xfb, 0xf0, 0x30, 0x75, 0xf4, 0xbc, 0x93, 0x9d, 0x7e, 0xfb, 0xe1, + 0x8f, 0xce, 0xad, 0xcf, 0x2f, 0x61, 0x15, 0xfe, 0x79, 0x79, 0x27, 0xea, + 0x1d, 0x50, 0x7a, 0xe8, 0x4b, 0x7e, 0xce, 0xa6, 0x2c, 0xeb, 0xff, 0x85, + 0xd1, 0xbd, 0x70, 0x4f, 0xc4, 0x3a, 0xa7, 0x3e, 0x7e, 0x92, 0xdf, 0xe9, + 0x47, 0x27, 0x8e, 0x4e, 0x75, 0xec, 0xe7, 0xe7, 0x5f, 0xa6, 0xc0, 0xad, + 0x5c, 0xeb, 0xf8, 0x61, 0x9d, 0xe5, 0xa3, 0xa9, 0x0f, 0xd6, 0x61, 0xcd, + 0xa2, 0xba, 0x84, 0x6d, 0xe4, 0x2a, 0x6f, 0xff, 0xff, 0xec, 0x46, 0xe7, + 0xa0, 0x7d, 0xaf, 0x90, 0x81, 0xc5, 0xfc, 0xe4, 0x24, 0x9f, 0x47, 0x5f, + 0xd9, 0xe7, 0x1f, 0xc0, 0x75, 0xfd, 0xdf, 0x89, 0x3b, 0x89, 0xd5, 0x23, + 0xda, 0xc2, 0xcb, 0x30, 0xaa, 0x5e, 0xe5, 0x88, 0x4b, 0x4e, 0x44, 0x12, + 0x7c, 0x86, 0xb3, 0x49, 0x12, 0x1c, 0x7c, 0x2d, 0x5b, 0xd7, 0x61, 0xaa, + 0xf0, 0x87, 0x18, 0x7f, 0x68, 0x9b, 0xd0, 0xe1, 0xbf, 0xcc, 0x67, 0x1a, + 0xee, 0xd3, 0x45, 0x81, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x9d, 0x6f, 0xff, + 0xf7, 0x62, 0x70, 0xe2, 0xd8, 0xd6, 0xb3, 0xa9, 0xa0, 0x4e, 0x75, 0xf9, + 0x85, 0xbc, 0x98, 0xc4, 0x4b, 0x4c, 0x67, 0x7f, 0xa5, 0xa6, 0x14, 0x52, + 0x16, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xd9, 0xbf, 0xff, 0xcf, 0x26, + 0x35, 0x09, 0x81, 0x4c, 0xd6, 0x78, 0x60, 0xeb, 0xff, 0x7f, 0x1a, 0x63, + 0xa8, 0xd7, 0xe1, 0xd7, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0x31, + 0x89, 0x83, 0xac, 0xcd, 0xd7, 0x04, 0xfe, 0xff, 0xfc, 0xff, 0xfe, 0x0d, + 0x31, 0x9c, 0x7d, 0x75, 0xe4, 0x75, 0xf3, 0x5d, 0xda, 0x68, 0xb9, 0xac, + 0xb3, 0xab, 0x86, 0xf5, 0x92, 0xdb, 0xfd, 0xc1, 0xcd, 0xff, 0x49, 0x1d, + 0x74, 0xcb, 0x3a, 0x8e, 0xb3, 0x18, 0x7e, 0xc8, 0x44, 0xc9, 0x9e, 0xd8, + 0xbd, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xef, 0xbf, 0xd2, 0x63, 0x5c, 0xe2, + 0x32, 0x75, 0x98, 0xc3, 0xe8, 0x73, 0x3b, 0xe6, 0x14, 0x0f, 0xe7, 0x54, + 0x3e, 0x52, 0x36, 0x5b, 0xcb, 0xf6, 0x9a, 0xee, 0xae, 0x93, 0xee, 0xdc, + 0x87, 0x62, 0xe1, 0xaa, 0xe8, 0x5f, 0xc6, 0x7a, 0x28, 0x5a, 0x8c, 0x2b, + 0xd0, 0xad, 0xfa, 0x4f, 0x7f, 0xe6, 0x5c, 0x67, 0xd2, 0x0e, 0xf2, 0x3a, + 0xff, 0xec, 0x9f, 0x19, 0xee, 0x6b, 0x10, 0x4e, 0xb9, 0x18, 0xea, 0x20, + 0x44, 0xfe, 0xfd, 0xad, 0x2d, 0xe4, 0x75, 0xff, 0xff, 0xff, 0xba, 0x9d, + 0x48, 0x1f, 0x0b, 0xa9, 0x9e, 0x07, 0x93, 0xda, 0xea, 0x72, 0x27, 0x7e, + 0x34, 0xeb, 0xb5, 0x07, 0x5f, 0xfd, 0xbb, 0x40, 0xfb, 0xfb, 0x30, 0x54, + 0x3a, 0xf0, 0xbb, 0x10, 0x98, 0xc3, 0x49, 0xf5, 0x09, 0x7f, 0x0a, 0xde, + 0x03, 0xac, 0xeb, 0xf6, 0x6d, 0x7a, 0x14, 0x3a, 0xdb, 0x47, 0x54, 0xe6, + 0xf7, 0x0a, 0xab, 0x87, 0xf2, 0x2b, 0x17, 0xfe, 0xd3, 0xa9, 0xd4, 0x81, + 0x04, 0x1d, 0x7f, 0xee, 0xbf, 0x9f, 0xbb, 0xcb, 0x3c, 0x75, 0x61, 0xfd, + 0x21, 0xe5, 0xcf, 0xf9, 0xd7, 0xff, 0xff, 0x85, 0xd9, 0x1c, 0xf7, 0xb2, + 0x78, 0x17, 0x53, 0x4b, 0x8c, 0x10, 0x9d, 0x58, 0x88, 0xae, 0x0b, 0x5f, + 0xee, 0xe0, 0x53, 0x67, 0x30, 0xeb, 0xce, 0xed, 0x34, 0x4a, 0xf7, 0xf9, + 0x47, 0x1f, 0xfd, 0x9d, 0x3a, 0x9a, 0x7b, 0x48, 0x4f, 0x7f, 0xfb, 0xdd, + 0xc9, 0x37, 0xa8, 0x18, 0x1f, 0x1d, 0x52, 0x47, 0xb7, 0x21, 0x1a, 0x24, + 0x37, 0x4a, 0x73, 0xaf, 0xfc, 0x2e, 0xc8, 0x7b, 0x13, 0xe3, 0x27, 0x5f, + 0xff, 0xb1, 0x3f, 0xc5, 0xa7, 0xb5, 0x0b, 0x7d, 0xfc, 0x75, 0xff, 0x42, + 0xfd, 0x93, 0x49, 0x3c, 0x75, 0x49, 0x11, 0x9e, 0x54, 0xbe, 0x03, 0xf2, + 0x47, 0x5f, 0xf4, 0x34, 0x62, 0x7f, 0xdf, 0xc7, 0x5f, 0xff, 0xe4, 0xf3, + 0xad, 0xc7, 0xfe, 0xb2, 0xe3, 0x3b, 0x52, 0x73, 0xa8, 0x28, 0xba, 0x42, + 0x17, 0x38, 0xbf, 0xe0, 0x7e, 0xb7, 0x96, 0xb8, 0x13, 0xaf, 0xff, 0xf6, + 0x20, 0xfb, 0x07, 0xe0, 0xb8, 0x60, 0x67, 0x8e, 0x1d, 0x6c, 0xf2, 0x25, + 0xf6, 0x1d, 0x5f, 0xf6, 0xff, 0xe7, 0x33, 0x3d, 0xa3, 0xa8, 0x2a, 0xb4, + 0x32, 0x19, 0x7d, 0x86, 0xe8, 0xc3, 0x17, 0xe9, 0x55, 0xff, 0xbc, 0xf2, + 0xd7, 0x63, 0x9f, 0x42, 0x75, 0xff, 0xde, 0x4d, 0x89, 0xe9, 0xa5, 0x03, + 0xe3, 0xaf, 0xff, 0x3e, 0x4b, 0xb8, 0x83, 0x9f, 0xed, 0xe1, 0xd7, 0x9e, + 0x4c, 0x42, 0xf5, 0x0c, 0xa1, 0x36, 0x18, 0x55, 0x64, 0x63, 0x0b, 0x34, + 0xd4, 0xae, 0x7f, 0x2d, 0xfd, 0x40, 0xda, 0x45, 0xbf, 0xfd, 0x9d, 0x60, + 0x70, 0x28, 0x3e, 0xce, 0x9d, 0x7b, 0xd0, 0x12, 0xaf, 0xff, 0x75, 0xd3, + 0xd1, 0x24, 0xe4, 0xe0, 0xfc, 0xab, 0xfc, 0xed, 0x60, 0x3c, 0x54, 0xb1, + 0x07, 0xcb, 0xa1, 0xbb, 0x30, 0x16, 0x52, 0xe3, 0x63, 0x46, 0x5c, 0xfb, + 0x6f, 0xa1, 0x5b, 0xb2, 0x15, 0x97, 0xff, 0x98, 0x5b, 0xc9, 0x8c, 0xe3, + 0x5d, 0xda, 0x68, 0x98, 0x6f, 0xff, 0xec, 0xd8, 0xe1, 0xec, 0x31, 0xee, + 0xe0, 0x41, 0xed, 0x1d, 0x7f, 0xfb, 0x8f, 0xfb, 0x0a, 0x7a, 0x4c, 0xc6, + 0xa4, 0x75, 0xd8, 0xc0, 0xa2, 0xaf, 0xea, 0xed, 0xff, 0xca, 0x8c, 0xde, + 0x40, 0x7f, 0x0c, 0x48, 0xeb, 0xf6, 0x2f, 0xe6, 0xea, 0xe7, 0x5f, 0xd0, + 0xbc, 0xfe, 0x36, 0x1d, 0x41, 0x3d, 0xbe, 0x96, 0xdf, 0xee, 0x63, 0x63, + 0xff, 0xab, 0x3a, 0xfd, 0xd8, 0x0a, 0x28, 0x75, 0x21, 0xff, 0x70, 0x8b, + 0x68, 0xd6, 0xff, 0x43, 0xcf, 0xe5, 0x1f, 0x87, 0x5f, 0x9f, 0x92, 0x75, + 0x9d, 0x42, 0x7b, 0x20, 0x33, 0xbf, 0xff, 0x27, 0x3a, 0xff, 0x03, 0x92, + 0xec, 0x6c, 0x0c, 0x1d, 0x7f, 0xcc, 0xfd, 0xec, 0x37, 0xa9, 0x31, 0xd7, + 0xc0, 0x5e, 0x04, 0xeb, 0x66, 0xe7, 0xbb, 0xb4, 0x79, 0x5d, 0x46, 0xf8, + 0xc2, 0xd2, 0xfe, 0x5c, 0x60, 0xfb, 0x6c, 0xeb, 0x68, 0xeb, 0xf4, 0x60, + 0xfb, 0x6c, 0xeb, 0xfb, 0xa9, 0xed, 0x3e, 0xff, 0x0f, 0x9a, 0x62, 0xe5, + 0x88, 0x5f, 0xe9, 0x7a, 0x17, 0xb3, 0xf9, 0x1d, 0x7f, 0xff, 0x99, 0xda, + 0xf6, 0x77, 0xe0, 0xe4, 0xe9, 0x83, 0xbc, 0xb4, 0x75, 0xf9, 0x9f, 0x67, + 0x5a, 0x75, 0x87, 0x11, 0x1c, 0xec, 0xd7, 0xff, 0xbc, 0x2f, 0xff, 0x71, + 0x02, 0x0f, 0x68, 0xeb, 0xfe, 0x89, 0xfe, 0xcb, 0xa0, 0x79, 0xce, 0xa8, + 0x44, 0x2f, 0x12, 0x6f, 0xfe, 0xcd, 0xe5, 0xf3, 0xae, 0xd8, 0x10, 0x9d, + 0x7f, 0x6c, 0xfb, 0xe1, 0x8f, 0xce, 0xbf, 0xfd, 0x1e, 0xfe, 0x25, 0x9b, + 0xfa, 0x70, 0x32, 0x75, 0x41, 0xff, 0x21, 0x8d, 0xfc, 0xff, 0xf3, 0x89, + 0xc3, 0xaf, 0x7b, 0xe6, 0x1d, 0x5f, 0x9e, 0x57, 0xd2, 0xdb, 0xfb, 0x48, + 0xa2, 0xdf, 0xc7, 0x5f, 0xff, 0xfb, 0x99, 0xb2, 0x07, 0xdf, 0x3e, 0x8c, + 0x75, 0xd3, 0xd1, 0xed, 0x1d, 0x7f, 0x0e, 0x6b, 0xe3, 0x55, 0x47, 0x56, + 0xe8, 0xcd, 0xe1, 0x6e, 0xc6, 0xeb, 0xef, 0x9b, 0x36, 0xa7, 0x3a, 0xb0, + 0xf7, 0x54, 0x33, 0xb2, 0xb9, 0xd7, 0x7b, 0x0e, 0xbf, 0xfc, 0xa9, 0x18, + 0x5b, 0xa7, 0x5f, 0xdd, 0x83, 0xaa, 0x0f, 0x7c, 0x02, 0xb7, 0xfb, 0xa9, + 0x33, 0xb7, 0x52, 0x3a, 0xff, 0x40, 0xf9, 0xd6, 0x9e, 0x3a, 0xff, 0xb1, + 0x31, 0x63, 0x93, 0xb9, 0xd7, 0xe8, 0xf6, 0xbf, 0x01, 0xd4, 0xac, 0xa6, + 0xa7, 0x8e, 0x4d, 0x21, 0xe9, 0x98, 0x98, 0x78, 0xd6, 0xff, 0xfd, 0xd1, + 0xcf, 0x75, 0x33, 0x7f, 0x66, 0xc8, 0xd1, 0xd7, 0xff, 0x38, 0xf6, 0x10, + 0x29, 0xac, 0x91, 0xd7, 0xa3, 0xff, 0xa7, 0x56, 0x22, 0xcd, 0xd5, 0x45, + 0x02, 0xf7, 0xd0, 0xe1, 0xd7, 0x95, 0x3a, 0x55, 0x1d, 0x4e, 0x78, 0x3a, + 0x1d, 0xbf, 0xc2, 0xec, 0xc7, 0xb2, 0x73, 0xac, 0xc2, 0xa9, 0x95, 0xbb, + 0x11, 0x90, 0x06, 0x11, 0x59, 0x18, 0x03, 0x61, 0x1b, 0xba, 0xac, 0xd0, + 0xc4, 0xe4, 0x2a, 0xd6, 0x45, 0xd8, 0x61, 0xfe, 0xd4, 0x31, 0xa7, 0xea, + 0x37, 0x5f, 0x46, 0x1c, 0x06, 0xed, 0xb2, 0x1b, 0xff, 0xee, 0x26, 0xf2, + 0xd2, 0x7b, 0xb1, 0xcf, 0x41, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x8a, 0xba, + 0xf7, 0x21, 0x67, 0x5f, 0xf4, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0xf2, + 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xe8, 0xf2, 0x01, 0x53, + 0x92, 0x9e, 0x63, 0xac, 0xc0, 0x53, 0x5e, 0xc4, 0xfe, 0x19, 0xb8, 0xd8, + 0xa2, 0xe8, 0xe6, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x60, 0xde, 0x52, 0x27, + 0x3a, 0xff, 0xfe, 0x10, 0x3c, 0xeb, 0xcd, 0xb0, 0x73, 0x39, 0x2f, 0xb2, + 0x3a, 0xfd, 0x83, 0x9e, 0xd1, 0xd7, 0xfb, 0x8e, 0xbf, 0xbc, 0x7d, 0xce, + 0xb3, 0x18, 0x98, 0x52, 0x86, 0x6d, 0x1d, 0x76, 0x0f, 0xa4, 0xb7, 0xf9, + 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xb2, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x16, + 0x9d, 0xff, 0x38, 0x7a, 0xf3, 0x75, 0x16, 0x75, 0x98, 0xc3, 0xeb, 0x59, + 0x9d, 0xf9, 0x5a, 0x2a, 0xf5, 0x65, 0x59, 0x56, 0xce, 0xbf, 0xe5, 0x57, + 0x51, 0x90, 0xbb, 0xb4, 0xeb, 0xf2, 0xb4, 0x54, 0x6b, 0x20, 0xeb, 0xfd, + 0xf5, 0x79, 0xed, 0x26, 0x8e, 0xb2, 0x1d, 0x4a, 0xa3, 0xc3, 0xdb, 0x34, + 0xbf, 0xff, 0x93, 0xae, 0x3e, 0x96, 0x73, 0x20, 0x47, 0x3c, 0x75, 0xfb, + 0x63, 0x87, 0x16, 0x75, 0xf2, 0xe3, 0x7d, 0x1d, 0x52, 0x44, 0xfe, 0x2a, + 0xcc, 0x51, 0x7e, 0xf9, 0xce, 0x03, 0xa7, 0x5f, 0x91, 0x48, 0x16, 0x9d, + 0x6c, 0xd1, 0xe8, 0x78, 0xaa, 0xff, 0xf8, 0x5b, 0xd4, 0xea, 0x72, 0x26, + 0x67, 0x3a, 0x75, 0xff, 0x96, 0xb7, 0x96, 0xd8, 0x3a, 0x9c, 0x3a, 0xfc, + 0xfa, 0xf4, 0x04, 0xea, 0x83, 0xe7, 0x02, 0x0d, 0x42, 0x35, 0xfb, 0x0b, + 0x6b, 0xe8, 0xfb, 0x1d, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x5b, 0x97, 0xfe, + 0xce, 0x60, 0xfc, 0xee, 0x6e, 0xc9, 0xd7, 0xe1, 0xfd, 0xf7, 0xd1, 0xd5, + 0x07, 0xd0, 0xe8, 0x15, 0xba, 0x35, 0xf8, 0x45, 0xa8, 0x4a, 0xdf, 0xe7, + 0x1f, 0xe6, 0x18, 0x59, 0xd7, 0x96, 0x28, 0x75, 0x84, 0xeb, 0xfe, 0xe8, + 0x1f, 0x59, 0x82, 0xa1, 0xd7, 0xed, 0x3e, 0xee, 0x13, 0xac, 0x81, 0x3d, + 0xef, 0x1b, 0xd4, 0x22, 0xbb, 0x06, 0xba, 0xdb, 0x7f, 0xd0, 0xe3, 0xdc, + 0xc1, 0x69, 0xd7, 0xfb, 0xde, 0x49, 0xd7, 0x02, 0x75, 0x48, 0xf9, 0xb0, + 0xd2, 0xff, 0xa0, 0x40, 0xb8, 0xd7, 0x90, 0xeb, 0xe0, 0xc6, 0x70, 0xeb, + 0xf7, 0xcd, 0xf4, 0x8a, 0x1d, 0x67, 0x9c, 0xf2, 0xf7, 0x20, 0xbf, 0xfa, + 0x59, 0xd4, 0xe0, 0x7b, 0x02, 0xd3, 0xaf, 0xf6, 0xf2, 0x81, 0xf6, 0x7e, + 0x75, 0xf6, 0xbf, 0x4f, 0x1d, 0x4e, 0x8c, 0x0d, 0x14, 0x81, 0x0b, 0xe9, + 0x9d, 0xff, 0xde, 0x4f, 0xe2, 0x41, 0xec, 0x0b, 0x4e, 0xa3, 0xaf, 0x01, + 0xfc, 0x75, 0xc0, 0x83, 0xaa, 0x46, 0xc3, 0xc3, 0x74, 0x75, 0xf6, 0xed, + 0x4e, 0x1d, 0x7a, 0x16, 0xc6, 0x22, 0x1f, 0x73, 0xa5, 0x90, 0xf8, 0x2a, + 0xa1, 0x31, 0x94, 0x86, 0x55, 0xe1, 0xf6, 0xd9, 0xd7, 0xfd, 0x26, 0x33, + 0x8d, 0x77, 0x69, 0xa2, 0x87, 0xa4, 0x3e, 0x37, 0x1e, 0xbf, 0x7f, 0x0d, + 0xc5, 0x9d, 0x7d, 0x13, 0x60, 0x4e, 0xae, 0x1e, 0x46, 0x89, 0xef, 0xfb, + 0x20, 0x3d, 0x8d, 0xa8, 0x98, 0xeb, 0xfd, 0xfa, 0x77, 0xb9, 0xfb, 0x9d, + 0x4b, 0x3e, 0xdf, 0xce, 0xaa, 0x11, 0x64, 0xf0, 0x8f, 0xbf, 0xf3, 0x86, + 0x03, 0xd4, 0x14, 0x59, 0xd7, 0xff, 0x6a, 0x06, 0x6c, 0x1f, 0xdf, 0xd8, + 0x75, 0xfe, 0xd0, 0x1b, 0x9e, 0x18, 0x3a, 0x96, 0x8a, 0xee, 0x9d, 0xf9, + 0x0a, 0xff, 0xe0, 0x4b, 0xaf, 0xcd, 0xfd, 0x09, 0x39, 0xd7, 0xfd, 0x12, + 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0xf2, 0x7b, 0x4e, 0x87, 0x5f, 0xf7, 0x3f, + 0xe3, 0x8f, 0xb3, 0xf3, 0xab, 0xf3, 0xde, 0x01, 0x2d, 0xef, 0xbc, 0x91, + 0xd7, 0xf7, 0xdf, 0x02, 0x32, 0x73, 0xaa, 0x47, 0x9b, 0x30, 0xf5, 0xff, + 0xcd, 0x18, 0xf0, 0xe6, 0xcc, 0xe4, 0x8e, 0xbf, 0xe0, 0x0a, 0x9f, 0x7b, + 0xd0, 0x68, 0xeb, 0xfc, 0x22, 0xfe, 0xfb, 0x0d, 0x3a, 0xf8, 0x7f, 0x9f, + 0xf3, 0xab, 0x0f, 0x59, 0x0c, 0xaf, 0xf6, 0xbe, 0x7b, 0xe0, 0x70, 0x4e, + 0xb7, 0xe7, 0x59, 0x37, 0x3c, 0x7e, 0x1b, 0x5f, 0x9f, 0x7d, 0x79, 0x0e, + 0xa8, 0x4e, 0xbb, 0x08, 0xd1, 0x0f, 0xb0, 0x92, 0x16, 0x7d, 0x14, 0x5f, + 0x9c, 0x0a, 0x47, 0xd3, 0xaf, 0xca, 0xac, 0xe4, 0x68, 0xea, 0x98, 0xf4, + 0xc4, 0xa6, 0xff, 0x9f, 0x51, 0x36, 0xf2, 0xcd, 0x87, 0x5f, 0xff, 0x83, + 0xd8, 0xfa, 0xc7, 0x85, 0xff, 0xd6, 0xa3, 0xf2, 0xae, 0x0e, 0x1d, 0x7e, + 0x9e, 0x27, 0x7d, 0x1d, 0x58, 0x89, 0x64, 0x59, 0x71, 0x5b, 0xbf, 0x01, + 0xd7, 0xf3, 0xff, 0x30, 0xc0, 0x4e, 0xa8, 0x3c, 0x4e, 0x8b, 0xd9, 0x85, + 0x61, 0xb0, 0x6c, 0x56, 0xd0, 0xd5, 0x79, 0xe2, 0xac, 0xe7, 0x10, 0xc8, + 0x94, 0x20, 0x03, 0x0f, 0xec, 0x87, 0xf2, 0x86, 0xcd, 0x87, 0x06, 0xf0, + 0x94, 0x42, 0x19, 0xa3, 0x41, 0xe4, 0x6a, 0xeb, 0x84, 0x57, 0x63, 0x1a, + 0x78, 0x6a, 0x7e, 0x60, 0x28, 0xba, 0x84, 0xbf, 0xa5, 0x0f, 0x02, 0x15, + 0x9b, 0x08, 0xb6, 0xe1, 0xa3, 0xf5, 0xc6, 0xfe, 0x62, 0x78, 0xe4, 0x96, + 0x75, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2f, 0x3a, 0x87, 0x48, 0x51, + 0x26, 0xf0, 0xc6, 0x05, 0x94, 0xb0, 0xdd, 0xe5, 0x40, 0x72, 0x36, 0x65, + 0xa9, 0xf6, 0x15, 0x43, 0x58, 0x4a, 0x6a, 0x3c, 0x5d, 0x85, 0xf7, 0xf9, + 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa5, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x16, + 0x15, 0xff, 0xfa, 0x30, 0x43, 0x1d, 0x8d, 0xfd, 0x82, 0xeb, 0x3a, 0xfe, + 0x07, 0x12, 0x77, 0x59, 0xd6, 0x63, 0x11, 0x62, 0xb3, 0x3d, 0xb5, 0x1b, + 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x59, 0x77, 0x71, 0x43, 0xaf, 0x98, + 0x51, 0x56, 0x56, 0x0e, 0xbc, 0xc7, 0xd5, 0x9d, 0x4d, 0x3c, 0xd0, 0x17, + 0x50, 0xa2, 0x1b, 0x4c, 0x96, 0xfc, 0xeb, 0x94, 0x9c, 0xeb, 0x9f, 0x92, + 0x35, 0x38, 0x23, 0x7f, 0xcf, 0xb8, 0xe6, 0xfe, 0x85, 0x0e, 0xbf, 0xd3, + 0xef, 0xa8, 0x0f, 0x90, 0xeb, 0xf4, 0x66, 0xc8, 0xd1, 0xd6, 0x87, 0x3d, + 0xb6, 0x4d, 0x29, 0xd1, 0x76, 0x30, 0x94, 0xbe, 0x79, 0x48, 0x27, 0x5f, + 0xcf, 0xc8, 0xf3, 0xf4, 0xeb, 0xcc, 0xb2, 0xc9, 0x57, 0xfd, 0x12, 0xdf, + 0xdc, 0x8c, 0xdc, 0xa6, 0x0b, 0xfb, 0xfe, 0x03, 0xef, 0x9e, 0x4d, 0xd9, + 0x3a, 0xe8, 0xd1, 0xd4, 0x14, 0xc0, 0xfa, 0x42, 0x29, 0x5a, 0x49, 0xd8, + 0x75, 0x7f, 0x23, 0xeb, 0xfd, 0x00, 0xeb, 0xff, 0xfb, 0xa9, 0xee, 0xe6, + 0x87, 0x16, 0x0d, 0x75, 0xe4, 0x75, 0xfe, 0x89, 0x79, 0xfa, 0xe1, 0x3a, + 0xb1, 0x11, 0x5c, 0x59, 0xb4, 0x8e, 0xb4, 0x8e, 0xb4, 0x8e, 0xa8, 0x36, + 0x0a, 0x08, 0x20, 0x85, 0xff, 0xfb, 0xda, 0x46, 0xe0, 0xf2, 0x07, 0x03, + 0x8a, 0x1d, 0x6d, 0xce, 0xbb, 0x40, 0x3a, 0xb0, 0xfe, 0x74, 0xa5, 0xe1, + 0x1b, 0x92, 0x0e, 0xbf, 0x86, 0x16, 0x31, 0x87, 0x5d, 0x28, 0x3a, 0x82, + 0x7a, 0x53, 0x0a, 0x00, 0xa6, 0xff, 0xff, 0xfb, 0xb1, 0xed, 0x26, 0xb5, + 0x1e, 0xea, 0x47, 0x3f, 0x5b, 0xca, 0x5e, 0x50, 0xeb, 0x93, 0x73, 0xae, + 0x85, 0x9d, 0x7f, 0xff, 0x4a, 0x04, 0x12, 0x94, 0x7b, 0xb8, 0xbf, 0xb1, + 0xf9, 0xd7, 0x35, 0x88, 0x5e, 0x0a, 0x9d, 0x2c, 0x30, 0xe6, 0xc8, 0xca, + 0x5a, 0x99, 0xc8, 0x5b, 0xba, 0x90, 0xc2, 0x9b, 0x50, 0x80, 0xf1, 0x86, + 0xc7, 0xed, 0xb1, 0x6f, 0xa2, 0xb7, 0xff, 0x98, 0x5b, 0xc9, 0x8c, 0xe3, + 0x5d, 0xda, 0x68, 0xa3, 0x2f, 0xdb, 0x23, 0x91, 0xf9, 0xd7, 0xe1, 0x7f, + 0xe3, 0xe9, 0xd7, 0xff, 0x6e, 0xd4, 0xe7, 0x73, 0x06, 0x5a, 0x3a, 0xcc, + 0x42, 0x25, 0x3a, 0x53, 0xe2, 0x8a, 0x93, 0x27, 0xe7, 0x90, 0xf0, 0x59, + 0xcb, 0xcf, 0x67, 0xea, 0x1c, 0x1e, 0x87, 0x5d, 0xff, 0xcc, 0x3c, 0x98, + 0xce, 0x35, 0xdd, 0xa6, 0x88, 0xe6, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, + 0x6b, 0xbb, 0x4d, 0x13, 0x95, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2c, + 0xcb, 0xfe, 0x96, 0x9d, 0x6c, 0x77, 0xdf, 0x9d, 0x7f, 0xca, 0xb8, 0x38, + 0xb8, 0xde, 0x16, 0x75, 0xff, 0x7f, 0xc8, 0xf7, 0x5f, 0x79, 0x1d, 0x7f, + 0xb3, 0x5c, 0xe6, 0x6f, 0xa3, 0xaf, 0xee, 0x37, 0xae, 0x8a, 0x93, 0xae, + 0xdd, 0x67, 0x59, 0x85, 0x61, 0x1e, 0x50, 0x7d, 0x23, 0xa0, 0x19, 0xed, + 0x98, 0x5f, 0xe6, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0xdd, 0xbf, 0x85, 0xd8, + 0xe4, 0xfd, 0x3a, 0xf2, 0x6f, 0xf9, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x8a, + 0x42, 0xff, 0xd9, 0xd4, 0xd9, 0xdc, 0xc1, 0x69, 0xd7, 0x9e, 0x4c, 0x61, + 0xf8, 0x68, 0xce, 0xcc, 0x35, 0x1d, 0xdc, 0x2e, 0x5c, 0x23, 0x6f, 0xfe, + 0x61, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4a, 0x55, 0x3a, 0xe1, 0x34, + 0xca, 0x2b, 0x57, 0x73, 0xff, 0xe3, 0x2d, 0x15, 0x8f, 0x46, 0x5b, 0xb4, + 0x79, 0x7f, 0xa4, 0x83, 0xec, 0x40, 0x9d, 0x7b, 0x40, 0x59, 0xd6, 0x63, + 0x73, 0xcc, 0x43, 0x0b, 0xc2, 0xf2, 0x3a, 0xff, 0xcf, 0x26, 0x33, 0x8d, + 0x77, 0x69, 0xa2, 0x76, 0xba, 0x75, 0x73, 0xaf, 0xff, 0xc8, 0x10, 0x2e, + 0x36, 0x9c, 0x23, 0x03, 0x8d, 0x3a, 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, + 0x9d, 0x66, 0x31, 0x30, 0xb5, 0x8d, 0x75, 0x29, 0xc6, 0x85, 0x52, 0xff, + 0xf9, 0x8f, 0xbb, 0x6e, 0x3f, 0xe7, 0xa0, 0x53, 0xf3, 0xaf, 0xfe, 0x75, + 0xf7, 0x1a, 0xfd, 0x8f, 0xb2, 0x3a, 0xf2, 0x05, 0xce, 0xbf, 0xf8, 0x73, + 0xaf, 0x3e, 0x68, 0x5f, 0x73, 0xae, 0xdb, 0x60, 0x28, 0xa0, 0xea, 0x26, + 0x86, 0xaa, 0x4a, 0xad, 0xd7, 0x19, 0xa6, 0x93, 0xf6, 0xe1, 0xe9, 0x7f, + 0xff, 0x05, 0xfc, 0xc6, 0x6a, 0x07, 0x7f, 0xf5, 0xa8, 0xfc, 0xeb, 0xf7, + 0x1a, 0xee, 0xd3, 0x44, 0x59, 0x7f, 0xe7, 0x93, 0x19, 0xc6, 0xbb, 0xb4, + 0xd1, 0x2e, 0xdf, 0xff, 0xd8, 0x1e, 0xc7, 0xd6, 0x3c, 0x2f, 0xfe, 0xb5, + 0x1f, 0x95, 0x66, 0x31, 0x1b, 0x6b, 0x33, 0xdb, 0x4a, 0xbf, 0xfc, 0xc2, + 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xc5, 0x7e, 0xe3, 0x5d, 0xda, + 0x68, 0xaa, 0x6d, 0x87, 0x56, 0x1e, 0x12, 0x86, 0x77, 0xff, 0xff, 0xb8, + 0xfd, 0xde, 0x59, 0xe6, 0x3a, 0xfa, 0xe2, 0x33, 0xee, 0xa7, 0x24, 0x75, + 0x30, 0x89, 0xc7, 0x22, 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, + 0xd3, 0x44, 0xe9, 0x7f, 0x91, 0xf9, 0x12, 0x7d, 0x87, 0x5f, 0xa6, 0x89, + 0xa3, 0x47, 0x5f, 0xcc, 0xe2, 0x6c, 0xc1, 0x3a, 0x90, 0xf5, 0x74, 0x51, + 0x79, 0x3b, 0x07, 0x30, 0x68, 0x6f, 0xfe, 0x06, 0xbd, 0x1b, 0xb0, 0x09, + 0x91, 0x67, 0x52, 0xcf, 0xcb, 0xa5, 0x77, 0xfe, 0x79, 0x31, 0x9c, 0x6b, + 0xbb, 0x4d, 0x13, 0xbd, 0xfb, 0xc0, 0x75, 0xa1, 0x57, 0xfe, 0x18, 0xf6, + 0x6b, 0x33, 0x79, 0x1d, 0x41, 0x4f, 0xa3, 0x23, 0x1a, 0x59, 0x13, 0xa5, + 0x78, 0x9a, 0xfe, 0x86, 0x3f, 0x1c, 0x09, 0xd4, 0xc1, 0xfe, 0x0a, 0x7d, + 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0x5b, 0xff, + 0xff, 0xdd, 0x02, 0xd6, 0xf2, 0x61, 0xbd, 0x07, 0xa0, 0x72, 0x75, 0x01, + 0x13, 0x1d, 0x7e, 0x06, 0xfe, 0x46, 0x9d, 0x7e, 0xcf, 0xf1, 0xc4, 0xeb, + 0xd1, 0xfb, 0x13, 0x9e, 0x68, 0x94, 0x52, 0x23, 0xf4, 0x61, 0x91, 0x7f, + 0xf9, 0x85, 0xbc, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x4a, 0xff, 0xff, + 0x66, 0x98, 0xfb, 0x93, 0x75, 0xd7, 0xee, 0xc7, 0x80, 0xb3, 0xaa, 0x17, + 0xf6, 0xe7, 0x8c, 0xe2, 0x47, 0x2d, 0x8c, 0xd7, 0x84, 0x6b, 0x95, 0x77, + 0xf9, 0x17, 0xa3, 0x54, 0x01, 0x36, 0xda, 0xbd, 0xfe, 0x63, 0x38, 0xd7, + 0x76, 0x9a, 0x22, 0x4b, 0xff, 0xcc, 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, + 0x34, 0x4b, 0xd7, 0xdc, 0x07, 0xb4, 0x75, 0xfb, 0x9f, 0xad, 0x34, 0x75, + 0xe8, 0x1d, 0xce, 0xbf, 0x7b, 0xea, 0xc6, 0x0e, 0xb2, 0x74, 0xf0, 0xc4, + 0x6e, 0xff, 0xf7, 0x76, 0x40, 0xfe, 0xaf, 0x81, 0xce, 0x6e, 0x75, 0xd1, + 0xe3, 0xaf, 0xff, 0x00, 0x29, 0xcf, 0xb3, 0x6d, 0x01, 0xc6, 0x63, 0xaa, + 0x48, 0xda, 0x42, 0x6f, 0xd3, 0xf4, 0x2b, 0x7f, 0xf3, 0xcd, 0xa8, 0xd8, + 0xfd, 0x8d, 0xe6, 0x3a, 0xfd, 0x93, 0xe6, 0x96, 0x75, 0xff, 0xd3, 0x7c, + 0xfa, 0x31, 0xb1, 0xf6, 0x44, 0xc7, 0x51, 0xd7, 0xf4, 0xd2, 0x7f, 0x3e, + 0xc3, 0xaa, 0x11, 0x0b, 0x89, 0x8e, 0x15, 0x77, 0x20, 0xea, 0x0a, 0xad, + 0x94, 0x22, 0x9a, 0x34, 0x5e, 0x1e, 0x8a, 0x3e, 0xc8, 0x56, 0x6d, 0x16, + 0xde, 0x0e, 0x09, 0xd7, 0x07, 0x73, 0xaf, 0xf9, 0x1c, 0x41, 0xe9, 0xa1, + 0x43, 0xaf, 0xff, 0x93, 0x9f, 0x3b, 0x09, 0xed, 0x01, 0xa0, 0x83, 0xaf, + 0x92, 0x7f, 0xd5, 0xce, 0xbe, 0x6b, 0xbb, 0x4d, 0x14, 0xbd, 0xf0, 0xfa, + 0x38, 0x75, 0xff, 0x67, 0x15, 0xf0, 0x39, 0xcd, 0xce, 0xa4, 0x3d, 0xbd, + 0x84, 0x14, 0xa2, 0x64, 0x33, 0x28, 0x70, 0x9b, 0xb0, 0x88, 0xbf, 0x0f, + 0xa7, 0xc6, 0x4e, 0xbf, 0xf4, 0x0c, 0x77, 0xe0, 0x04, 0x0d, 0x3a, 0xf0, + 0x1f, 0x47, 0x5f, 0xa3, 0xf7, 0xdf, 0x47, 0x5e, 0x14, 0xfc, 0xeb, 0xd9, + 0xed, 0x1d, 0x50, 0x6d, 0xb4, 0x37, 0x41, 0x46, 0xbc, 0xc7, 0xdf, 0x8d, + 0xf9, 0x7a, 0xfc, 0xae, 0xe2, 0x1d, 0xa3, 0xaf, 0xfb, 0xfd, 0x72, 0x37, + 0x92, 0x2c, 0xeb, 0xde, 0x7d, 0x87, 0x5f, 0xf3, 0xcf, 0xf2, 0x70, 0x4d, + 0x0a, 0xe7, 0x54, 0x22, 0x5d, 0xce, 0x80, 0x3b, 0x7f, 0xc9, 0xa9, 0x90, + 0x7d, 0x1f, 0x9d, 0x52, 0x3e, 0x65, 0x97, 0x5c, 0xe2, 0x75, 0xff, 0x47, + 0xff, 0x3b, 0x0b, 0x71, 0x3a, 0xdc, 0xdc, 0xf3, 0x76, 0x0a, 0x54, 0x27, + 0x87, 0x91, 0x94, 0xa3, 0x7d, 0xee, 0x42, 0xce, 0xbf, 0xa0, 0x66, 0xf2, + 0x28, 0x75, 0xff, 0x4b, 0x39, 0x36, 0x0c, 0x2c, 0xeb, 0xf7, 0xf0, 0xdc, + 0x59, 0xd4, 0x87, 0xbd, 0xc3, 0x7b, 0xa5, 0x87, 0x5e, 0x8f, 0xf4, 0x75, + 0x41, 0xe9, 0x04, 0x85, 0x91, 0x5b, 0xf7, 0x40, 0xa6, 0x09, 0xd7, 0xfd, + 0x1d, 0xd3, 0xfa, 0x39, 0xb4, 0x75, 0xff, 0x96, 0xe1, 0xfb, 0x34, 0xa0, + 0x77, 0x3a, 0x82, 0x7f, 0x68, 0x75, 0x7d, 0xcf, 0xfe, 0xec, 0x3a, 0xf2, + 0x33, 0xe3, 0xab, 0xa7, 0x87, 0xa2, 0x7a, 0x0a, 0x65, 0x1d, 0x85, 0x17, + 0x99, 0x2f, 0xfb, 0xf4, 0xee, 0x71, 0xe6, 0xd1, 0xd7, 0xff, 0xe8, 0x90, + 0xc4, 0xff, 0x66, 0xd7, 0x73, 0x6b, 0x9f, 0x9d, 0x7f, 0x7c, 0x5e, 0x79, + 0xfc, 0x75, 0x9a, 0x75, 0xdb, 0xeb, 0x0d, 0xf3, 0x97, 0x56, 0xe8, 0xff, + 0x59, 0xcb, 0xc2, 0x6a, 0xff, 0x63, 0x32, 0x4d, 0x01, 0x67, 0x5d, 0xb3, + 0x47, 0x5f, 0xb2, 0x7c, 0xee, 0x8e, 0xa8, 0x37, 0xe2, 0x31, 0x7b, 0x39, + 0xa3, 0xa9, 0xa6, 0xeb, 0x60, 0xfd, 0xff, 0x7f, 0x1f, 0xfd, 0xd9, 0x03, + 0xb4, 0x75, 0x42, 0x61, 0xf9, 0x0a, 0xc4, 0x23, 0xbf, 0xff, 0xfb, 0xb1, + 0xcd, 0xda, 0x9b, 0xfc, 0x51, 0xfe, 0x6b, 0xae, 0xd8, 0x10, 0x9d, 0x7d, + 0xe1, 0x45, 0x9d, 0x7f, 0x86, 0x1c, 0x7d, 0x82, 0x75, 0xfe, 0xeb, 0xcc, + 0x9c, 0x89, 0xce, 0xbb, 0x16, 0x75, 0x05, 0x30, 0xdc, 0x77, 0x59, 0x03, + 0x97, 0x6c, 0x33, 0xbf, 0x6d, 0x22, 0xe3, 0x47, 0x5f, 0x9f, 0x66, 0x73, + 0x47, 0x50, 0x4f, 0x45, 0x65, 0x37, 0xee, 0xb8, 0xa2, 0xce, 0xbe, 0x52, + 0x6d, 0x41, 0xd7, 0xf9, 0xff, 0xd4, 0x76, 0x34, 0x75, 0x42, 0x27, 0x30, + 0x89, 0x09, 0x44, 0x8e, 0xef, 0xda, 0x75, 0xb4, 0x75, 0xc8, 0xa6, 0x8d, + 0x38, 0x05, 0xef, 0x7e, 0xed, 0x3a, 0xff, 0xfc, 0x81, 0xcd, 0x8f, 0xc9, + 0xbe, 0xc9, 0xfc, 0xeb, 0x3a, 0xa0, 0xfd, 0x38, 0x39, 0x66, 0x21, 0x9b, + 0xb7, 0x3b, 0xac, 0x86, 0x82, 0x2f, 0x91, 0xac, 0xee, 0x8a, 0x90, 0xff, + 0x9a, 0x50, 0x17, 0x0d, 0x16, 0x37, 0xd8, 0x6e, 0xbc, 0x6a, 0xff, 0xc6, + 0x6a, 0x31, 0xa2, 0x6a, 0x34, 0x0f, 0x46, 0x71, 0xb6, 0xc1, 0xf6, 0x14, + 0x37, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa7, 0x2f, 0xfc, 0x9c, 0x7d, + 0x77, 0x30, 0x5a, 0x75, 0xf9, 0x7c, 0xe6, 0x68, 0xeb, 0xff, 0xf7, 0x41, + 0xee, 0x47, 0xb5, 0x8d, 0xd4, 0x71, 0xa7, 0x5f, 0xe4, 0x58, 0x63, 0x40, + 0x13, 0xaf, 0xec, 0xf6, 0xf2, 0x86, 0x4e, 0xbf, 0xf9, 0x44, 0xdf, 0x43, + 0x81, 0xeb, 0xb2, 0x75, 0xff, 0xb3, 0xb1, 0xcc, 0x61, 0x96, 0x59, 0x2a, + 0xe4, 0x64, 0xeb, 0xa7, 0x60, 0x29, 0xd9, 0x61, 0xdb, 0x49, 0xfa, 0xaa, + 0x26, 0x3e, 0x2e, 0xdb, 0x45, 0xda, 0x41, 0xbf, 0x71, 0xae, 0xed, 0x34, + 0x57, 0x97, 0xff, 0xf6, 0x07, 0xb1, 0xf5, 0x8f, 0x0b, 0xff, 0xad, 0x47, + 0xe5, 0x59, 0x8c, 0x44, 0x8e, 0xd9, 0x9d, 0xff, 0xcc, 0x3c, 0x98, 0xce, + 0x35, 0xdd, 0xa6, 0x89, 0x1e, 0xf3, 0x71, 0x67, 0x5e, 0x4f, 0xe0, 0xeb, + 0xcd, 0xc5, 0x94, 0xc1, 0x77, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x92, 0x2f, + 0xff, 0xe8, 0x4e, 0x26, 0xd4, 0x0c, 0xf1, 0xe4, 0xeb, 0xce, 0x75, 0xd2, + 0x62, 0x11, 0x73, 0x85, 0x7d, 0x33, 0xbf, 0x67, 0x58, 0xc5, 0x9d, 0x66, + 0x21, 0x35, 0x17, 0x87, 0x7f, 0x8e, 0xef, 0xfe, 0x61, 0xe4, 0xc6, 0x71, + 0xae, 0xed, 0x34, 0x49, 0x57, 0xee, 0x35, 0xdd, 0xa6, 0x8b, 0xc6, 0xff, + 0xa4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x49, 0xb6, 0x63, 0x0f, 0xe1, 0xcc, + 0xee, 0x67, 0xa7, 0x5f, 0x93, 0xfd, 0x60, 0x9d, 0x7f, 0xfc, 0x07, 0xdf, + 0x31, 0x45, 0x1e, 0x59, 0xbf, 0x8e, 0xa9, 0x1f, 0xbe, 0x89, 0xaf, 0x7d, + 0x19, 0xce, 0xbb, 0x9e, 0x3a, 0xf4, 0xc3, 0x39, 0xd6, 0x13, 0xae, 0xfb, + 0xf4, 0xea, 0xfc, 0xd4, 0xfd, 0x0f, 0xbb, 0x6d, 0x88, 0x4d, 0x3b, 0x21, + 0x1d, 0xd2, 0x27, 0x1e, 0xd0, 0xb7, 0xd4, 0x6a, 0x86, 0xe8, 0xfe, 0x73, + 0xf9, 0x56, 0x21, 0x61, 0x8c, 0xf1, 0x23, 0xf1, 0x9a, 0x31, 0x55, 0x96, + 0x76, 0x3a, 0x2f, 0x1d, 0x82, 0x19, 0x3f, 0x63, 0x75, 0xa8, 0x97, 0xf8, + 0x0d, 0x3c, 0xa4, 0x69, 0x4e, 0xbb, 0x86, 0x75, 0x2b, 0x31, 0x1c, 0x84, + 0xa4, 0xe3, 0x73, 0x6f, 0x53, 0x77, 0x7a, 0xcb, 0x8d, 0x29, 0x2f, 0xaa, + 0xf2, 0x88, 0xe6, 0xb6, 0x18, 0xfc, 0xb4, 0x26, 0x4b, 0xcd, 0xb0, 0x8b, + 0xb4, 0xa8, 0xc7, 0xb6, 0x50, 0x5f, 0xcf, 0x9a, 0xaa, 0x63, 0xe3, 0x1a, + 0xca, 0xdb, 0x55, 0xb8, 0x8f, 0xaf, 0x50, 0xe0, 0x16, 0xbf, 0xaf, 0x65, + 0x2b, 0x21, 0x99, 0xc9, 0x7d, 0xb9, 0x70, 0xff, 0x69, 0x05, 0x1b, 0x55, + 0xd7, 0x55, 0x00, }; -static const unsigned kPreloadedHSTSBits = 265770; +static const unsigned kPreloadedHSTSBits = 265744; -static const unsigned kHSTSRootPosition = 265157; +static const unsigned kHSTSRootPosition = 265131; #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 4bff1ea..74153f8 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -2217,8 +2217,6 @@ { "name": "domainkauf.de", "include_subdomains": true, "mode": "force-https" }, { "name": "emptypath.com", "include_subdomains": true, "mode": "force-https" }, { "name": "eromixx.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "ezequiel-garzon.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "ezequiel-garzon.net", "include_subdomains": true, "mode": "force-https" }, { "name": "fa-works.com", "include_subdomains": true, "mode": "force-https" }, { "name": "flagspot.net", "include_subdomains": true, "mode": "force-https" }, { "name": "getmango.com", "include_subdomains": true, "mode": "force-https" }, @@ -3852,7 +3850,9 @@ { "name": "wjglerum.nl", "include_subdomains": true, "mode": "force-https" }, { "name": "wp-tao.com", "include_subdomains": true, "mode": "force-https" }, { "name": "yoloprod.fr", "include_subdomains": true, "mode": "force-https" }, - { "name": "zzsec.org", "include_subdomains": true, "mode": "force-https" } + { "name": "zzsec.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "internetbank.swedbank.se", "include_subdomains": true, "mode": "force-https" }, + { "name": "my.swedbank.se", "include_subdomains": true, "mode": "force-https" } ], // |ReportUMAOnPinFailure| uses these to report which domain was associated
diff --git a/net/net.gypi b/net/net.gypi index a6e27b3..4d446b06 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -1144,6 +1144,7 @@ 'udp/datagram_client_socket.h', 'udp/datagram_server_socket.h', 'udp/datagram_socket.h', + 'udp/diff_serv_code_point.h', 'udp/udp_client_socket.cc', 'udp/udp_client_socket.h', 'udp/udp_net_log_parameters.cc',
diff --git a/net/quic/quic_server_id.cc b/net/quic/quic_server_id.cc index 15c9c5ce..89fd471c 100644 --- a/net/quic/quic_server_id.cc +++ b/net/quic/quic_server_id.cc
@@ -4,6 +4,10 @@ #include "net/quic/quic_server_id.h" +#include "net/base/host_port_pair.h" +#include "net/base/port_util.h" +#include "url/gurl.h" + using std::string; namespace net { @@ -52,6 +56,16 @@ host_port_pair_.Equals(other.host_port_pair_); } +// static +QuicServerId QuicServerId::FromString(const std::string& str) { + GURL url(str); + if (!url.is_valid()) + return QuicServerId(); + return QuicServerId( + HostPortPair::FromURL(url), url.scheme() == "https", + url.path() == "/private" ? PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED); +} + string QuicServerId::ToString() const { return (is_https_ ? "https://" : "http://") + host_port_pair_.ToString() + (privacy_mode_ == PRIVACY_MODE_ENABLED ? "/private" : "");
diff --git a/net/quic/quic_server_id.h b/net/quic/quic_server_id.h index 7236bfc..0daf0b8 100644 --- a/net/quic/quic_server_id.h +++ b/net/quic/quic_server_id.h
@@ -34,6 +34,10 @@ bool operator<(const QuicServerId& other) const; bool operator==(const QuicServerId& other) const; + // Creates a QuicServerId from a string formatted in same manner as + // ToString(). + static QuicServerId FromString(const std::string& str); + // ToString() will convert the QuicServerId to "scheme:hostname:port" or // "scheme:hostname:port/private". "scheme" would either be "http" or "https" // based on |is_https|.
diff --git a/net/spdy/spdy_alt_svc_wire_format.cc b/net/spdy/spdy_alt_svc_wire_format.cc index a418cd7..4ac8dc5 100644 --- a/net/spdy/spdy_alt_svc_wire_format.cc +++ b/net/spdy/spdy_alt_svc_wire_format.cc
@@ -34,6 +34,22 @@ } // namespace +SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {} + +SpdyAltSvcWireFormat::AlternativeService::AlternativeService( + const std::string& protocol_id, + const std::string& host, + uint16 port, + uint16 version, + uint32 max_age, + double p) + : protocol_id(protocol_id), + host(host), + port(port), + version(version), + max_age(max_age), + p(p) {} + // static bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( StringPiece value, @@ -82,6 +98,7 @@ } ++c; // Parse parameters. + uint16 version = 0; uint32 max_age = 86400; double p = 1.0; StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); @@ -114,7 +131,11 @@ if (c == parameter_value_begin) { return false; } - if (parameter_name.compare("ma") == 0) { + if (parameter_name.compare("v") == 0) { + if (!ParsePositiveInteger16(parameter_value_begin, c, &version)) { + return false; + } + } else if (parameter_name.compare("ma") == 0) { if (!ParsePositiveInteger32(parameter_value_begin, c, &max_age)) { return false; } @@ -125,7 +146,7 @@ } } altsvc_vector->push_back( - AlternativeService(protocol_id, host, port, max_age, p)); + AlternativeService(protocol_id, host, port, version, max_age, p)); for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { } } @@ -182,6 +203,9 @@ value.push_back(c); } base::StringAppendF(&value, ":%d\"", altsvc.port); + if (altsvc.version != 0) { + base::StringAppendF(&value, "; v=%d", altsvc.version); + } if (altsvc.max_age != 86400) { base::StringAppendF(&value, "; ma=%d", altsvc.max_age); }
diff --git a/net/spdy/spdy_alt_svc_wire_format.h b/net/spdy/spdy_alt_svc_wire_format.h index 85e8d81f..7081bf7 100644 --- a/net/spdy/spdy_alt_svc_wire_format.h +++ b/net/spdy/spdy_alt_svc_wire_format.h
@@ -26,28 +26,26 @@ class NET_EXPORT_PRIVATE SpdyAltSvcWireFormat { public: - struct AlternativeService { + struct NET_EXPORT_PRIVATE AlternativeService { std::string protocol_id; std::string host; uint16 port; + uint16 version; uint32 max_age; double p; - AlternativeService() = default; + AlternativeService(); AlternativeService(const std::string& protocol_id, const std::string& host, uint16 port, + uint16 version, uint32 max_age, - double p) - : protocol_id(protocol_id), - host(host), - port(port), - max_age(max_age), - p(p) {} + double p); bool operator==(const AlternativeService& other) const { return protocol_id == other.protocol_id && host == other.host && - port == other.port && max_age == other.max_age && p == other.p; + port == other.port && version == other.version && + max_age == other.max_age && p == other.p; } }; typedef std::vector<AlternativeService> AlternativeServiceVector;
diff --git a/net/spdy/spdy_alt_svc_wire_format_test.cc b/net/spdy/spdy_alt_svc_wire_format_test.cc index f4cb0cb..e2b3a9c 100644 --- a/net/spdy/spdy_alt_svc_wire_format_test.cc +++ b/net/spdy/spdy_alt_svc_wire_format_test.cc
@@ -92,9 +92,11 @@ expected_altsvc->p = 0.33; header_field_value->append("; P=.33"); } + expected_altsvc->version = 0; if (i & 1 << 6) { expected_altsvc->p = 0.0; - header_field_value->append("; p=0"); + expected_altsvc->version = 24; + header_field_value->append("; p=0;v=24"); } if (i & 1 << 7) { expected_altsvc->max_age = 999999999; @@ -132,13 +134,18 @@ expected_header_field_value->append("foo\\\"bar\\\\baz"); } expected_header_field_value->append(":42\""); - altsvc->max_age = 86400; + altsvc->version = 0; if (i & 1 << 1) { + altsvc->version = 24; + expected_header_field_value->append("; v=24"); + } + altsvc->max_age = 86400; + if (i & 1 << 2) { altsvc->max_age = 1111; expected_header_field_value->append("; ma=1111"); } altsvc->p = 1.0; - if (i & 1 << 2) { + if (i & 1 << 3) { altsvc->p = 0.33; expected_header_field_value->append("; p=0.33"); } @@ -169,6 +176,7 @@ EXPECT_EQ(expected_altsvc.protocol_id, altsvc_vector[0].protocol_id); EXPECT_EQ(expected_altsvc.host, altsvc_vector[0].host); EXPECT_EQ(expected_altsvc.port, altsvc_vector[0].port); + EXPECT_EQ(expected_altsvc.version, altsvc_vector[0].version); EXPECT_EQ(expected_altsvc.max_age, altsvc_vector[0].max_age); EXPECT_DOUBLE_EQ(expected_altsvc.p, altsvc_vector[0].p); } @@ -199,6 +207,7 @@ altsvc_vector[j].protocol_id); EXPECT_EQ(expected_altsvc_vector[j].host, altsvc_vector[j].host); EXPECT_EQ(expected_altsvc_vector[j].port, altsvc_vector[j].port); + EXPECT_EQ(expected_altsvc_vector[j].version, altsvc_vector[j].version); EXPECT_EQ(expected_altsvc_vector[j].max_age, altsvc_vector[j].max_age); EXPECT_DOUBLE_EQ(expected_altsvc_vector[j].p, altsvc_vector[j].p); } @@ -213,7 +222,7 @@ // Test SerializeHeaderFieldValue() with and without hostname and each // parameter. Single alternative service at a time. TEST(SpdyAltSvcWireFormatTest, SerializeHeaderFieldValue) { - for (int i = 0; i < 1 << 3; ++i) { + for (int i = 0; i < 1 << 4; ++i) { SpdyAltSvcWireFormat::AlternativeService altsvc; std::string expected_header_field_value; FuzzAlternativeService(i, &altsvc, &expected_header_field_value); @@ -229,7 +238,7 @@ TEST(SpdyAltSvcWireFormatTest, SerializeHeaderFieldValueMultiple) { SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; std::string expected_header_field_value; - for (int i = 0; i < 1 << 3; ++i) { + for (int i = 0; i < 1 << 4; ++i) { SpdyAltSvcWireFormat::AlternativeService altsvc; FuzzAlternativeService(i, &altsvc, &expected_header_field_value); altsvc_vector.push_back(altsvc); @@ -248,7 +257,8 @@ "a=\"c:42foo\"", "a=\"b:42\"bar", "a=\"b:42\" ; m", "a=\"b:42\" ; min-age", "a=\"b:42\" ; ma", "a=\"b:42\" ; ma=", "a=\"b:42\" ; ma=ma", "a=\"b:42\" ; ma=123bar", "a=\"b:42\" ; p=-2", - "a=\"b:42\" ; p=..", "a=\"b:42\" ; p=1.05"}; + "a=\"b:42\" ; p=..", "a=\"b:42\" ; p=1.05", + "a=\"b:42\" ; v=-3", "a=\"b:42\" ; v=1.2"}; for (const char* invalid_field_value : invalid_field_value_array) { EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue( invalid_field_value, &altsvc_vector))
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 1c359356..e593862 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -3532,20 +3532,20 @@ const char kType = static_cast<unsigned char>( SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC)); const unsigned char kFrameData[] = { - 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o', - 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h', - 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a', - '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%', - '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"', - 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=', - '4', '2', ';', ' ', 'p', '=', '0', '.', '2', '0', - }; + 0x00, 0x00, 0x4f, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, + 'o', 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', + '"', 'h', 'o', 's', 't', ':', '4', '4', '3', '"', ';', + ' ', 'm', 'a', '=', '5', ',', 'p', '%', '2', '2', '%', + '3', 'D', 'i', '%', '3', 'A', 'd', '=', '"', 'h', '_', + '\\', '\\', 'o', '\\', '"', 's', 't', ':', '1', '2', '3', + '"', ';', ' ', 'v', '=', '2', '4', ';', ' ', 'm', 'a', + '=', '4', '2', ';', ' ', 'p', '=', '0', '.', '2', '0'}; SpdyAltSvcIR altsvc_ir(3); altsvc_ir.set_origin("origin"); altsvc_ir.add_altsvc( - SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0)); + SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 0, 5, 1.0)); altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService( - "p\"=i:d", "h_\\o\"st", 123, 42, 0.2)); + "p\"=i:d", "h_\\o\"st", 123, 24, 42, 0.2)); scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir)); CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData)); } @@ -5803,9 +5803,10 @@ SpdyFramer framer(spdy_version_); framer.set_visitor(&visitor); - SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0); + SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 0, 5, + 1.0); SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123, - 42, 0.2); + 24, 42, 0.2); SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; altsvc_vector.push_back(altsvc1); altsvc_vector.push_back(altsvc2); @@ -5835,9 +5836,10 @@ SpdyFramer framer(spdy_version_); framer.set_visitor(&visitor); - SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0); + SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 0, 5, + 1.0); SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123, - 42, 0.2); + 24, 42, 0.2); SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; altsvc_vector.push_back(altsvc1); altsvc_vector.push_back(altsvc2); @@ -5868,9 +5870,9 @@ SpdyAltSvcIR altsvc_ir(1); altsvc_ir.set_origin("o1"); altsvc_ir.add_altsvc( - SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 5, 1.0)); + SpdyAltSvcWireFormat::AlternativeService("pid1", "host", 443, 0, 5, 1.0)); altsvc_ir.add_altsvc( - SpdyAltSvcWireFormat::AlternativeService("", "h1", 443, 10, 1.0)); + SpdyAltSvcWireFormat::AlternativeService("", "h1", 443, 0, 10, 1.0)); scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir)); framer.ProcessInput(frame->data(), frame->size()); @@ -5890,7 +5892,7 @@ SpdyFramer framer(spdy_version_); framer.set_visitor(&visitor); - SpdyAltSvcWireFormat::AlternativeService altsvc("pid", "h1", 443, 10, 1.0); + SpdyAltSvcWireFormat::AlternativeService altsvc("pid", "h1", 443, 0, 10, 1.0); SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; altsvc_vector.push_back(altsvc); EXPECT_CALL(visitor, OnAltSvc(kStreamId, StringPiece("o1"), altsvc_vector)); @@ -5914,9 +5916,10 @@ SpdyFramer framer(spdy_version_); SpdyAltSvcIR altsvc_ir(1); - SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 5, 1.0); + SpdyAltSvcWireFormat::AlternativeService altsvc1("pid1", "host", 443, 0, 5, + 1.0); SpdyAltSvcWireFormat::AlternativeService altsvc2("p\"=i:d", "h_\\o\"st", 123, - 42, 0.2); + 24, 42, 0.2); altsvc_ir.add_altsvc(altsvc1); altsvc_ir.add_altsvc(altsvc2);
diff --git a/net/udp/datagram_server_socket.h b/net/udp/datagram_server_socket.h index d3796c3..0002868 100644 --- a/net/udp/datagram_server_socket.h +++ b/net/udp/datagram_server_socket.h
@@ -6,8 +6,8 @@ #define NET_UDP_DATAGRAM_SERVER_SOCKET_H_ #include "net/base/completion_callback.h" -#include "net/base/net_util.h" #include "net/udp/datagram_socket.h" +#include "net/udp/diff_serv_code_point.h" namespace net {
diff --git a/net/udp/diff_serv_code_point.h b/net/udp/diff_serv_code_point.h new file mode 100644 index 0000000..f4a8786 --- /dev/null +++ b/net/udp/diff_serv_code_point.h
@@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_UDP_DIFF_SERV_CODE_POINT_H_ +#define NET_UDP_DIFF_SERV_CODE_POINT_H_ + +namespace net { + +// Differentiated Services Code Point. +// See http://tools.ietf.org/html/rfc2474 for details. +enum DiffServCodePoint { + DSCP_NO_CHANGE = -1, + DSCP_FIRST = DSCP_NO_CHANGE, + DSCP_DEFAULT = 0, // Same as DSCP_CS0 + DSCP_CS0 = 0, // The default + DSCP_CS1 = 8, // Bulk/background traffic + DSCP_AF11 = 10, + DSCP_AF12 = 12, + DSCP_AF13 = 14, + DSCP_CS2 = 16, + DSCP_AF21 = 18, + DSCP_AF22 = 20, + DSCP_AF23 = 22, + DSCP_CS3 = 24, + DSCP_AF31 = 26, + DSCP_AF32 = 28, + DSCP_AF33 = 30, + DSCP_CS4 = 32, + DSCP_AF41 = 34, // Video + DSCP_AF42 = 36, // Video + DSCP_AF43 = 38, // Video + DSCP_CS5 = 40, // Video + DSCP_EF = 46, // Voice + DSCP_CS6 = 48, // Voice + DSCP_CS7 = 56, // Control messages + DSCP_LAST = DSCP_CS7 +}; + +} // namespace net + +#endif // NET_UDP_DIFF_SERV_CODE_POINT_H_
diff --git a/net/udp/udp_socket_posix.h b/net/udp/udp_socket_posix.h index eb18daa..44547d5f 100644 --- a/net/udp/udp_socket_posix.h +++ b/net/udp/udp_socket_posix.h
@@ -14,11 +14,12 @@ #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_export.h" -#include "net/base/net_util.h" +#include "net/base/network_change_notifier.h" #include "net/base/rand_callback.h" #include "net/log/net_log.h" #include "net/socket/socket_descriptor.h" #include "net/udp/datagram_socket.h" +#include "net/udp/diff_serv_code_point.h" namespace net {
diff --git a/net/udp/udp_socket_win.h b/net/udp/udp_socket_win.h index d01e67b..b06a6a7a 100644 --- a/net/udp/udp_socket_win.h +++ b/net/udp/udp_socket_win.h
@@ -19,10 +19,11 @@ #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_export.h" -#include "net/base/net_util.h" +#include "net/base/network_change_notifier.h" #include "net/base/rand_callback.h" #include "net/log/net_log.h" #include "net/udp/datagram_socket.h" +#include "net/udp/diff_serv_code_point.h" namespace net {
diff --git a/remoting/webapp/crd/js/activation_handler.js b/remoting/webapp/crd/js/activation_handler.js index cadb882..32c93a5 100644 --- a/remoting/webapp/crd/js/activation_handler.js +++ b/remoting/webapp/crd/js/activation_handler.js
@@ -95,11 +95,13 @@ }; /** - * @param {Event} launchData + * @param {Object?} launchData |launchData| is null when this function + * is invoked from an IPC. + * * @private */ remoting.ActivationHandler.prototype.onLaunched_ = function(launchData) { - if (launchData['isPublicSession']) { + if (Boolean(launchData) && Boolean(launchData['isPublicSession'])) { this.launchIt2MeSession_(); } else { this.launchDefaultSession_();
diff --git a/remoting/webapp/crd/js/host_list.js b/remoting/webapp/crd/js/host_list.js index 64d33c9..e9e878d 100644 --- a/remoting/webapp/crd/js/host_list.js +++ b/remoting/webapp/crd/js/host_list.js
@@ -321,7 +321,6 @@ remoting.AppsV2Migration.hasHostsInV1App().then( /** * @param {remoting.MigrationSettings} previousIdentity - * @this {remoting.HostList} */ function(previousIdentity) { that.noHosts_.innerHTML = remoting.AppsV2Migration.buildMigrationTips(
diff --git a/remoting/webapp/js_proto/chrome_mocks.js b/remoting/webapp/js_proto/chrome_mocks.js index 92fa421..d3dfd95 100644 --- a/remoting/webapp/js_proto/chrome_mocks.js +++ b/remoting/webapp/js_proto/chrome_mocks.js
@@ -163,7 +163,7 @@ if (!keys) { // No keys are specified, returns the entire storage. var storageCopy = base.deepCopy(this.storage_); - onDone(/** @type {Object} */ (storageCopy)); + onDone(/** @type {!Object} */ (storageCopy)); return; }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 793d6b6..02bb811 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -448,7 +448,6 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ ":skia_library_config", - "//build/config:precompiled_headers", "//build/config/compiler:no_chromium_code", ] public_configs = [ ":skia_config" ]
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index cb0da9cf..b02fa88 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1019,6 +1019,10 @@ { "isolate_name": "telemetry_gpu_unittests", "name": "telemetry_gpu_unittests" + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests" } ], "scripts": [ @@ -1039,10 +1043,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" }, @@ -1386,6 +1386,10 @@ { "isolate_name": "telemetry_gpu_unittests", "name": "telemetry_gpu_unittests" + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests" } ], "scripts": [ @@ -1394,10 +1398,6 @@ "script": "telemetry_unittests.py" }, { - "name": "telemetry_perf_unittests", - "script": "telemetry_perf_unittests.py" - }, - { "name": "nacl_integration", "script": "nacl_integration.py" }
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 93a5d2bcb..224e300 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -389,6 +389,16 @@ "-v", ], }, + "telemetry_perf_unittests": { + "label": "//chrome/test:telemetry_perf_unittests", + "type": "script", + "script": "//testing/scripts/run_telemetry_as_googletest.py", + "args": [ + "--xvfb", + "../../tools/perf/run_tests", + "-v", + ], + }, "ui_base_unittests": { "label": "//ui/base:ui_base_unittests", "type": "windowed_test_launcher",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index adb7544..bb8d70f 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -73,6 +73,7 @@ 'tab_capture_end2end_tests', 'telemetry_gpu_test', 'telemetry_gpu_unittests', + 'telemetry_perf_unittests', }
diff --git a/testing/scripts/common.py b/testing/scripts/common.py index 3697c4b..69ee3e49 100644 --- a/testing/scripts/common.py +++ b/testing/scripts/common.py
@@ -59,9 +59,9 @@ return args.func(args) -def run_command(argv): +def run_command(argv, env=None): print 'Running %r' % argv - rc = subprocess.call(argv) + rc = subprocess.call(argv, env=env) print 'Command %r returned exit code %d' % (argv, rc) return rc
diff --git a/testing/scripts/run_telemetry_as_googletest.py b/testing/scripts/run_telemetry_as_googletest.py index 0dd5345f..0c111cb 100755 --- a/testing/scripts/run_telemetry_as_googletest.py +++ b/testing/scripts/run_telemetry_as_googletest.py
@@ -27,31 +27,46 @@ import common +# Add src/testing/ into sys.path for importing xvfb. +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import xvfb + def main(): parser = argparse.ArgumentParser() parser.add_argument( - '--isolated-script-test-output', - type=argparse.FileType('w'), - required=True) + '--isolated-script-test-output', type=argparse.FileType('w'), + required=True) + parser.add_argument('--xvfb', help='Start xvfb.', action='store_true') args, rest_args = parser.parse_known_args() - with common.temporary_file() as tempfile_path: - rc = common.run_command([sys.executable] + rest_args + [ - '--write-full-results-to', tempfile_path, - ]) - with open(tempfile_path) as f: - results = json.load(f) - parsed_results = common.parse_common_test_results(results, - test_separator='.') - failures = parsed_results['unexpected_failures'] + xvfb_proc = None + openbox_proc = None + env = os.environ.copy() + if args.xvfb and xvfb.should_start_xvfb(env): + xvfb_proc, openbox_proc = xvfb.start_xvfb(env=env, build_dir='.') + assert xvfb_proc and openbox_proc, 'Failed to start xvfb' + try: + with common.temporary_file() as tempfile_path: + rc = common.run_command([sys.executable] + rest_args + [ + '--write-full-results-to', tempfile_path, + ], env=env) + with open(tempfile_path) as f: + results = json.load(f) + parsed_results = common.parse_common_test_results(results, + test_separator='.') + failures = parsed_results['unexpected_failures'] - json.dump({ - 'valid': bool(rc <= common.MAX_FAILURES_EXIT_STATUS and - ((rc == 0) or failures)), - 'failures': failures.keys(), - }, args.isolated_script_test_output) + json.dump({ + 'valid': bool(rc <= common.MAX_FAILURES_EXIT_STATUS and + ((rc == 0) or failures)), + 'failures': failures.keys(), + }, args.isolated_script_test_output) - return rc + return rc + finally: + xvfb.kill(xvfb_proc) + xvfb.kill(openbox_proc) + # This is not really a "script test" so does not need to manually add
diff --git a/testing/variations/fieldtrial_testing_config_android.json b/testing/variations/fieldtrial_testing_config_android.json index e4dc736a..3c3008a 100644 --- a/testing/variations/fieldtrial_testing_config_android.json +++ b/testing/variations/fieldtrial_testing_config_android.json
@@ -28,10 +28,6 @@ { "group_name": "OptOut", "params": { - "contextual_search_arrow_icon_enabled": "true", - "contextual_search_narrow_panel_supported": "true", - "contextual_search_side_search_provider_icon_enabled": "true", - "disable_for_cjk": "true", "enabled": "true", "promo_on_limited_taps": "true", "promo_opt_out": "true",
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 5cf89ba..f9793e5 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -461,11 +461,6 @@ crbug.com/380217 [ Linux Win ] fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-large-radius.html [ Skip ] crbug.com/380217 [ Win ] fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-bottom-left.html [ Skip ] -crbug.com/533448 svg/W3C-SVG-1.1/text-align-06-b.svg [ NeedsRebaseline ] -crbug.com/533448 [ Linux Mac Win7 ] svg/batik/text/verticalText.svg [ NeedsRebaseline ] -crbug.com/533448 svg/batik/text/verticalTextOnPath.svg [ NeedsRebaseline ] -crbug.com/533448 svg/text/text-selection-align-06-b.svg [ NeedsRebaseline ] - crbug.com/405389 imported/csswg-test/css-shapes-1/shape-outside/supported-shapes/polygon/shape-outside-polygon-017.html [ ImageOnlyFailure ] crbug.com/424365 imported/csswg-test/css-shapes-1/shape-outside/shape-image/shape-image-010.html [ ImageOnlyFailure ] crbug.com/424365 imported/csswg-test/css-shapes-1/shape-outside/shape-image/shape-image-024.html [ ImageOnlyFailure ] @@ -718,9 +713,6 @@ crbug.com/309675 compositing/gestures/gesture-tapHighlight-simple-longPress.html [ ImageOnlyFailure ] -crbug.com/509581 [ Win ] css3/filters/filter-repaint-composited-fallback-crash.html [ ImageOnlyFailure ] -crbug.com/509581 [ Win ] css3/filters/filter-repaint-composited-fallback.html [ ImageOnlyFailure ] - crbug.com/245556 compositing/transitions/transform-on-large-layer.html [ ImageOnlyFailure ] crbug.com/253763 fast/text-autosizing/first-line-scale-factor.html [ ImageOnlyFailure ] @@ -1211,7 +1203,7 @@ crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubEmbed-in-default-context.svg [ ImageOnlyFailure ] crbug.com/521730 [ Win10 ] svg/W3C-I18N/tspan-dirRTL-ubNone-in-ltr-context.svg [ ImageOnlyFailure ImageOnlyFailure Timeout ImageOnlyFailure ] crbug.com/521730 [ Win10 ] svg/W3C-SVG-1.1/text-intro-03-b.svg [ ImageOnlyFailure ImageOnlyFailure Timeout ImageOnlyFailure ] -crbug.com/521730 [ Win10 ] svg/batik/text/verticalText.svg [ ImageOnlyFailure ImageOnlyFailure ImageOnlyFailure Timeout ] +crbug.com/521730 [ XP Win10 ] svg/batik/text/verticalText.svg [ Failure ] crbug.com/521730 [ Win10 ] svg/carto.net/combobox.svg [ ImageOnlyFailure Timeout ImageOnlyFailure ImageOnlyFailure ] crbug.com/521730 [ Win10 ] svg/css/text-gradient-shadow.svg [ ImageOnlyFailure ImageOnlyFailure ImageOnlyFailure Timeout ] crbug.com/521730 [ Win10 ] compositing/plugins/invalidate_rect.html [ Crash ] @@ -1507,13 +1499,6 @@ crbug.com/474759 fast/writing-mode/vertical-rl-replaced-selection.html [ ImageOnlyFailure ] crbug.com/474759 fast/block/line-layout/selection-highlight-overlap.html [ ImageOnlyFailure ] - -# GrGLConvolutionEffect optimization causes blink layout test image differences -crbug.com/505086 css3/filters/effect-blur-hw.html [ NeedsManualRebaseline ] -crbug.com/505086 css3/filters/effect-brightness-clamping-hw.html [ NeedsManualRebaseline ] -crbug.com/505086 css3/filters/effect-combined-hw.html [ NeedsManualRebaseline ] -crbug.com/505086 css3/filters/effect-reference-zoom-hw.html [ Crash NeedsManualRebaseline ] - crbug.com/502927 [ XP ] paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Failure ] crbug.com/502927 [ XP ] paint/frames/frameset-with-stacking-contexts.html [ Failure ] crbug.com/502927 [ XP ] virtual/spv2/paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Skip ] @@ -1617,3 +1602,7 @@ crbug.com/502267 fast/css/image-orientation/image-orientation-default.html [ NeedsRebaseline ] crbug.com/499780 fast/css/font_property_normal.html [ NeedsRebaseline ] + +crbug.com/541357 [ XP ] svg/text/text-selection-align-06-b.svg [ Failure ] +crbug.com/541357 [ XP ] svg/W3C-SVG-1.1/text-align-06-b.svg [ Failure ] +crbug.com/541357 [ XP ] svg/batik/text/verticalTextOnPath.svg [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow-expected.html b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow-expected.html new file mode 100644 index 0000000..a9601fd --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow-expected.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<style> +.flex { + height: 200px; + background: blue; +} +</style> +There should only be a blue box below, and the word "FAIL" should +not be seen. +<div class="flex"> +</div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow.html b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow.html new file mode 100644 index 0000000..310871e --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-column-overflow.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<style> +.flex { + display: flex; + flex-flow: column wrap; + max-height: 200px; + background: blue; + color: blue; +} + +.item { + flex: 0 0 auto; + line-height: 20px; +} +</style> +There should only be a blue box below, and the word "FAIL" should +not be seen. +<div class="flex"> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> + <span class="item">FAIL</span> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away-expected.txt b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away-expected.txt new file mode 100644 index 0000000..53a416e --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away-expected.txt
@@ -0,0 +1,4 @@ +Test +Test +PASS +crbug.com/535381 : Clear floats nested in earlier siblings. There should be a green box and no red.
diff --git a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html new file mode 100644 index 0000000..a3443d0d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<style> +html, body { margin: 0; padding: 0 } +#float { + float: right; + background: green; + width: 100px; + height: 50px; +} + +#test { + width: 100px; + height: 50px; + overflow: hidden; + margin-top: -50px; + background: green; +} + +.clear { + display: block; + clear: both; + height: 0px; +} + +#red { + position:absolute; + width:100px; + height:100px; + background-color: red; + top:0px; + z-index: -1; +} +</style> +<div id="red"></div> +<div style="width: 100px;"> + <div> + <div id="float"></div> + <div class="clear">Test</div> + </div> + <div>Test</div> +</div> +<div id="test" data-offset-y=50></div> +<script src="../../../resources/check-layout.js"></script> +<script> +window.checkLayout("#test", document.getElementById("test-output")); +</script> +<p>crbug.com/535381 : Clear floats nested in earlier siblings. There should be a green box and no red.</p>
diff --git a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins-expected.html b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins-expected.html new file mode 100644 index 0000000..5e0c14d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins-expected.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<style> +.outer { + width: 600px; + height: 100px; + background-color: green; +} +</style> +<body> +<p>You should see no red.</p> +<div class="outer"> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins.html b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins.html new file mode 100644 index 0000000..38919c2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/fill-available-large-margins.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<style> +.outer { + width: 600px; + height: 100px; + background-color: green; + + display: flex; +} + +.inner { + max-width: -webkit-fill-available; + margin-right: 1000px; + + width: 700px; + height: 100px; + + background-color: red; +} +</style> +<body> +<p>You should see no red.</p> +<div class="outer"> + <div class="inner"> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt index dae3966ee..83941ec8 100644 --- a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. PASS check MediaRecorder.canRecordMimeType() with video/invalid PASS check MediaRecorder.canRecordMimeType() with video/vp8 +PASS check MediaRecorder.canRecordMimeType() with video/vp9 PASS check MediaRecorder.canRecordMimeType() with audio/invalid FAIL check MediaRecorder.canRecordMimeType() with audio/opus assert_equals: expected "maybe" but got "" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType.html b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType.html index aa43a3b..2743790 100644 --- a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType.html +++ b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType.html
@@ -2,8 +2,8 @@ <script src=../../resources/testharness.js></script> <script src=../../resources/testharnessreport.js></script> <script> -// Check one Video format that should be recordable and another that should not -// be. Supported formats return "maybe". Same for Audio. +// Check the Video formats that should be recordable and one that should not be. +// Supported formats return "maybe". Same for Audio. // https://w3c.github.io/mediacapture-record/MediaRecorder.html#methods test(function() { @@ -15,6 +15,10 @@ }, 'check MediaRecorder.canRecordMimeType() with video/vp8'); test(function() { + assert_equals(MediaRecorder.canRecordMimeType("video/vp9"), "maybe"); +}, 'check MediaRecorder.canRecordMimeType() with video/vp9'); + +test(function() { assert_equals(MediaRecorder.canRecordMimeType("audio/invalid"), ""); }, 'check MediaRecorder.canRecordMimeType() with audio/invalid');
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text-expected.html b/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text-expected.html new file mode 100644 index 0000000..36abc16 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text-expected.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<script src="../../resources/ahem.js"></script> +<div style="position: relative;"> + <pre id="demo" style="font-family: Ahem; width: 2em; white-space: pre-wrap">a b </pre> + <div style="position: absolute; top: 0; left: 1em; width: 1em; height: 2em; background-color: #ff9632;"></div> +</div> +<p>Test for crbug.com/521047. Passes if find-in-page marker highlight is visible in both lines above.
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text.html b/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text.html new file mode 100644 index 0000000..c1dbf4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/text-match-pre-wrapped-text.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<script src="../../resources/ahem.js"></script> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<pre id="demo" style="font-family: Ahem; width: 2em; white-space: pre-wrap">a b </pre> +<p>Test for crbug.com/521047. Passes if find-in-page marker highlight is visible in both lines above. +<script> +function highlightRange(id, start, end, active) { + var range = document.createRange(); + var elem = document.getElementById(id).firstChild; + range.setStart(elem, start); + range.setEnd(elem, end); + if (window.internals) { + window.internals.addTextMatchMarker(range, active); + window.internals.setMarkedTextMatchesAreHighlighted(document, true); + } +} + +runAfterLayoutAndPaint(function() { + highlightRange('demo', 0, 4, true); +}, true); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode-expected.html b/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode-expected.html new file mode 100644 index 0000000..2b146416 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode-expected.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="en"><head> +<title>Selection in quirks mode</title> +<style> +body { + margin: 0; + padding: 0; +} + +pre { + margin: 0; +} + +code { + font-size: 14px; + padding-top: 4px; + margin-top: 8px; + line-height: 1.4em; +} +</style> +</head> +<body> + <pre><code> + Selection should render the same in both + standards and quirks mode. + </code></pre> + <script> + var node = document.getElementsByTagName('code')[0].firstChild; + var range = document.createRange(); + range.setStart(node, node.length - 17); + range.setEnd(node, node.length - 11); + window.getSelection().addRange(range); + </script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode.html b/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode.html new file mode 100644 index 0000000..49cc3ea --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/selection-padding-quirks-mode.html
@@ -0,0 +1,34 @@ +<html lang="en"><head> +<title>Selection in quirks mode</title> +<style> +body { + margin: 0; + padding: 0; +} + +pre { + margin: 0; +} + +code { + font-size: 14px; + padding-top: 4px; + margin-top: 8px; + line-height: 1.4em; +} +</style> +</head> +<body> + <pre><code> + Selection should render the same in both + standards and quirks mode. + </code></pre> + <script> + var node = document.getElementsByTagName('code')[0].firstChild; + var range = document.createRange(); + range.setStart(node, node.length - 17); + range.setEnd(node, node.length - 11); + window.getSelection().addRange(range); + </script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline-expected.html b/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline-expected.html index 39dc181..4288d2d 100644 --- a/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline-expected.html +++ b/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline-expected.html
@@ -1,11 +1,14 @@ <!DOCTYPE html> <style> +body { + font: 10px/1 Ahem; +} + #inlineBlock { display: inline-block; - font: 10px/1 sans-serif; position: relative; - top: 107px; + top: 142px; } </style> <div>This test checks baselines on writing mode boundaries with an overflow clip.</div> -<div id="inlineBlock">There should be about 100px (#verticalTextWithOverflowClip margin-bottom) above this line.</div> +<div id="inlineBlock">There should be about 100px above this line.</div>
diff --git a/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline.html b/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline.html index dff8bbc2..9156a3b 100644 --- a/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline.html +++ b/third_party/WebKit/LayoutTests/fast/text/writing-root-with-overflow-clip-baseline.html
@@ -1,8 +1,11 @@ <!DOCTYPE html> <style> +body { + font: 10px/1 Ahem; +} + #inlineBlock { display: inline-block; - font: 10px/1 sans-serif; } #verticalTextWithOverflowClip { @@ -15,7 +18,5 @@ visibility: hidden; } </style> -<div style="position: relative"> - <div>This test checks baselines on writing mode boundaries with an overflow clip.</div> - <div id="inlineBlock" data-offset-y="107">There should be about 100px (#verticalTextWithOverflowClip margin-bottom) above this line.<span id="verticalTextWithOverflowClip">Text.</span></div> -</div> +<div>This test checks baselines on writing mode boundaries with an overflow clip.</div> +<div id="inlineBlock">There should be about 100px above this line.<span id="verticalTextWithOverflowClip">Text.</span></div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js index 1737b837..541713bc5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -538,4 +538,26 @@ }); }; +InspectorTest.waitForExecutionContextInTarget = function(target, callback) +{ + if (target.runtimeModel.executionContexts().length) { + callback(target.runtimeModel.executionContexts()[0]); + return; + } + target.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.ExecutionContextCreated, contextCreated); + + function contextCreated() + { + target.runtimeModel.removeEventListener(WebInspector.RuntimeModel.Events.ExecutionContextCreated, contextCreated); + callback(target.runtimeModel.executionContexts()[0]); + } +} + +InspectorTest.selectThread = function(target) +{ + var threadsPane = WebInspector.panels.sources.sidebarPanes.threads; + var listItem = threadsPane._debuggerModelToListItems.get(WebInspector.DebuggerModel.fromTarget(target)); + threadsPane._onListItemClick(listItem); +} + };
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js index 1407a0b..b173fd2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -437,52 +437,7 @@ InspectorTest.expandAndDumpSelectedElementEventListeners = function(callback) { - InspectorTest.addSniffer(WebInspector.EventListenersView.prototype, "_eventListenersArrivedForTest", listenersArrived); - - var eventListenersWidget = InspectorTest.eventListenersWidget(); - - function listenersArrived() - { - var listenerTypes = eventListenersWidget._eventListenersView._treeOutline.rootElement().children(); - for (var i = 0; i < listenerTypes.length; ++i) { - listenerTypes[i].expand(); - var listenerItems = listenerTypes[i].children(); - for (var j = 0; j < listenerItems.length; ++j) - listenerItems[j].expand(); - } - InspectorTest.runAfterPendingDispatches(objectsExpanded); - } - - function objectsExpanded() - { - var listenerTypes = eventListenersWidget._eventListenersView._treeOutline.rootElement().children(); - for (var i = 0; i < listenerTypes.length; ++i) { - if (!listenerTypes[i].children().length) - continue; - var eventType = listenerTypes[i]._title; - InspectorTest.addResult(""); - InspectorTest.addResult("======== " + eventType + " ========"); - var listenerItems = listenerTypes[i].children(); - for (var j = 0; j < listenerItems.length; ++j) { - InspectorTest.addResult("== " + listenerItems[j].eventListener().listenerType()); - InspectorTest.dumpObjectPropertyTreeElement(listenerItems[j]); - } - } - callback(); - } -} - -InspectorTest.dumpObjectPropertyTreeElement = function(treeElement) -{ - var expandedSubstring = treeElement.expanded ? "[expanded]" : "[collapsed]"; - InspectorTest.addResult(expandedSubstring + " " + treeElement.listItemElement.deepTextContent()); - - for (var i = 0; i < treeElement.childCount(); ++i) { - var property = treeElement.childAt(i).property; - var key = property.name; - var value = property.value._description; - InspectorTest.addResult(" " + key + ": " + value); - } + InspectorTest.expandAndDumpEventListeners(InspectorTest.eventListenersWidget()._eventListenersView, null, callback); } InspectorTest.dumpObjectPropertySectionDeep = function(section)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt new file mode 100644 index 0000000..7017b01 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt
@@ -0,0 +1,18 @@ +Tests framework event listeners output in Sources panel when service worker is present. + +Inspect Me +Selecting service worker thread +Context is dedicated worker: true +Dumping listeners +Selecting main thread +Context is dedicated worker: false +Dumping listeners + +======== load ======== +== normal +[expanded] WindowRemoveevent-listeners-framework-with-service-worker.html:56 + useCapture: false + handler: function onload(event) { + runTest() +} +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html new file mode 100644 index 0000000..2bd44f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html
@@ -0,0 +1,62 @@ +<html> +<head> +<script src="../inspector-test.js"></script> +<script src="../debugger-test.js"></script> +<script src="../console-test.js"></script> +<script src="../service-workers/service-workers-test.js"></script> +<script> +function test() +{ + WebInspector.settingForTest("showEventListenersForAncestors").set(false); + var scriptURL = "http://127.0.0.1:8000/inspector/service-workers/resources/service-worker-empty.js"; + var scope = "http://127.0.0.1:8000/inspector/service-workers/resources/scope1/"; + + InspectorTest.waitForServiceWorker(step1); + InspectorTest.registerServiceWorker(scriptURL, scope); + + var objectEventListenersPane = WebInspector.panels.sources.sidebarPanes.objectEventListeners; + + function forceUpdate() + { + objectEventListenersPane.expand(); + objectEventListenersPane.update(); + } + + function step1(target) + { + InspectorTest.waitForExecutionContextInTarget(target, step2); + } + + function step2(executionContext) + { + InspectorTest.addResult("Selecting service worker thread"); + InspectorTest.selectThread(executionContext.target()); + InspectorTest.addResult("Context is dedicated worker: " + WebInspector.context.flavor(WebInspector.ExecutionContext).target().isDedicatedWorker()); + InspectorTest.addResult("Dumping listeners"); + InspectorTest.expandAndDumpEventListeners(objectEventListenersPane._eventListenersView, forceUpdate, step3); + } + + function step3() + { + InspectorTest.addResult("Selecting main thread"); + InspectorTest.selectThread(WebInspector.targetManager.mainTarget()); + InspectorTest.addResult("Context is dedicated worker: " + WebInspector.context.flavor(WebInspector.ExecutionContext).target().isDedicatedWorker()); + InspectorTest.addResult("Dumping listeners"); + InspectorTest.expandAndDumpEventListeners(objectEventListenersPane._eventListenersView, forceUpdate, step4); + } + + function step4() + { + InspectorTest.dumpConsoleMessages(false, false, InspectorTest.textContentWithLineBreaks); + InspectorTest.completeTest(); + } +} +</script> +</head> +<body onload="runTest()"> +<p> +Tests framework event listeners output in Sources panel when service worker is present. +</p> +<button id="inspectedNode">Inspect Me</button> +</body> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js index 6ddc6ab8..1282aa74 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -345,6 +345,57 @@ return output.join("\n"); } +InspectorTest.dumpObjectPropertyTreeElement = function(treeElement) +{ + var expandedSubstring = treeElement.expanded ? "[expanded]" : "[collapsed]"; + InspectorTest.addResult(expandedSubstring + " " + treeElement.listItemElement.deepTextContent()); + + for (var i = 0; i < treeElement.childCount(); ++i) { + var property = treeElement.childAt(i).property; + var key = property.name; + var value = property.value._description; + InspectorTest.addResult(" " + key + ": " + value); + } +} + +InspectorTest.expandAndDumpEventListeners = function(eventListenersView, updateCallback, callback) +{ + InspectorTest.addSniffer(WebInspector.EventListenersView.prototype, "_eventListenersArrivedForTest", listenersArrived); + + if (updateCallback) + updateCallback(); + + function listenersArrived() + { + var listenerTypes = eventListenersView._treeOutline.rootElement().children(); + for (var i = 0; i < listenerTypes.length; ++i) { + listenerTypes[i].expand(); + var listenerItems = listenerTypes[i].children(); + for (var j = 0; j < listenerItems.length; ++j) + listenerItems[j].expand(); + } + InspectorTest.runAfterPendingDispatches(objectsExpanded); + } + + function objectsExpanded() + { + var listenerTypes = eventListenersView._treeOutline.rootElement().children(); + for (var i = 0; i < listenerTypes.length; ++i) { + if (!listenerTypes[i].children().length) + continue; + var eventType = listenerTypes[i]._title; + InspectorTest.addResult(""); + InspectorTest.addResult("======== " + eventType + " ========"); + var listenerItems = listenerTypes[i].children(); + for (var j = 0; j < listenerItems.length; ++j) { + InspectorTest.addResult("== " + listenerItems[j].eventListener().listenerType()); + InspectorTest.dumpObjectPropertyTreeElement(listenerItems[j]); + } + } + callback(); + } +} + InspectorTest.assertGreaterOrEqual = function(a, b, message) { if (a < b)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-worker-agents.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-worker-agents.html index b5d2307..a5899e9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-worker-agents.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-worker-agents.html
@@ -22,18 +22,10 @@ } }, true); + InspectorTest.waitForServiceWorker(step1); InspectorTest.registerServiceWorker(scriptURL, scope); - WebInspector.targetManager.observeTargets({ - targetAdded: function(target) - { - if (target.isDedicatedWorker()) - setTimeout(step1); - }, - targetRemoved: function(target) {} - }); - - function step1() + function step1(target) { InspectorTest.addResult("Suspending targets."); WebInspector.targetManager.suspendAllTargets();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js index 59f3a40..d1978e8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js
@@ -15,6 +15,25 @@ return InspectorTest.invokePageFunctionPromise("postToServiceWorker", [scope, message]); } +InspectorTest.waitForServiceWorker = function(callback) +{ + function isRightTarget(target) + { + return target.isDedicatedWorker() && target.parentTarget() && target.parentTarget().isServiceWorker(); + } + + WebInspector.targetManager.observeTargets({ + targetAdded: function(target) + { + if (isRightTarget(target) && callback) { + setTimeout(callback.bind(null, target), 0); + callback = null; + } + }, + targetRemoved: function(target) {} + }); +} + function replaceInnerTextAll(rootElement, selectors, replacementString) { var elements = rootElement.querySelectorAll(selectors);
diff --git a/third_party/WebKit/LayoutTests/inspector/runtime/runtime-getProperties-expected.txt b/third_party/WebKit/LayoutTests/inspector/runtime/runtime-getProperties-expected.txt index ad7cdfa..338d884 100644 --- a/third_party/WebKit/LayoutTests/inspector/runtime/runtime-getProperties-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/runtime/runtime-getProperties-expected.txt
@@ -18,6 +18,7 @@ objectId : <string> type : "function" } + synthetic : false wasThrown : false writable : false } @@ -32,6 +33,7 @@ } isOwn : true name : "foo" + synthetic : false wasThrown : false writable : false }
diff --git a/third_party/WebKit/LayoutTests/inspector/runtime/runtime-localStorage-getProperties-expected.txt b/third_party/WebKit/LayoutTests/inspector/runtime/runtime-localStorage-getProperties-expected.txt index dc0ffafe..f8cce45 100644 --- a/third_party/WebKit/LayoutTests/inspector/runtime/runtime-localStorage-getProperties-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/runtime/runtime-localStorage-getProperties-expected.txt
@@ -4,6 +4,7 @@ enumerable : true isOwn : true name : "testProperty" + synthetic : false value : { description : "testPropertyValue" type : "string"
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run.html index 002d2034..ac78638 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run.html
@@ -24,12 +24,13 @@ } } + var contextId = WebInspector.context.flavor(WebInspector.ExecutionContext).id; InspectorTest.runDebuggerTestSuite([ function testSuccessfulCompileAndRun(next) { var expression = "var a = 1; var b = 2; a + b; "; InspectorTest.addResult("Compiling script"); - InspectorTest.DebuggerAgent.compileScript(expression, "test.js", true, compileCallback.bind(this)); + InspectorTest.DebuggerAgent.compileScript(expression, "test.js", true, contextId, compileCallback.bind(this)); function compileCallback(error, scriptId, exceptionDetails) { @@ -37,7 +38,7 @@ InspectorTest.assertTrue(!exceptionDetails); InspectorTest.assertTrue(!!scriptId); InspectorTest.addResult("Running script"); - InspectorTest.DebuggerAgent.runScript(scriptId, undefined, "console", false, runCallback.bind(this)); + InspectorTest.DebuggerAgent.runScript(scriptId, contextId, "console", false, runCallback.bind(this)); } function runCallback(error, result, exceptionDetails) @@ -54,7 +55,7 @@ { var expression = "var a = 1; a + c; "; InspectorTest.addResult("Compiling script"); - InspectorTest.DebuggerAgent.compileScript(expression, "test.js", true, compileCallback.bind(this)); + InspectorTest.DebuggerAgent.compileScript(expression, "test.js", true, contextId, compileCallback.bind(this)); function compileCallback(error, scriptId, exceptionDetails) { @@ -62,7 +63,7 @@ InspectorTest.assertTrue(!exceptionDetails); InspectorTest.assertTrue(!!scriptId); InspectorTest.addResult("Running script"); - InspectorTest.DebuggerAgent.runScript(scriptId, undefined, "console", false, runCallback.bind(this)); + InspectorTest.DebuggerAgent.runScript(scriptId, contextId, "console", false, runCallback.bind(this)); } function runCallback(error, result, exceptionDetails) @@ -79,7 +80,6 @@ { var expression = "}"; InspectorTest.addResult("Compiling script"); - var contextId = undefined; InspectorTest.DebuggerAgent.compileScript(expression, "test.js", true, contextId, compileCallback.bind(this)); function compileCallback(error, scriptId, exceptionDetails)
diff --git a/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_style-expected.png b/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_style-expected.png index c9663f1..76c8f32 100644 --- a/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_style-expected.png +++ b/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_style-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_variant-expected.png b/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_variant-expected.png index c29710f2..45773a3 100644 --- a/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_variant-expected.png +++ b/third_party/WebKit/LayoutTests/platform/android/css1/font_properties/font_variant-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css1/text_properties/text_align-expected.png b/third_party/WebKit/LayoutTests/platform/android/css1/text_properties/text_align-expected.png index 79bf13c..9e1a196 100644 --- a/third_party/WebKit/LayoutTests/platform/android/css1/text_properties/text_align-expected.png +++ b/third_party/WebKit/LayoutTests/platform/android/css1/text_properties/text_align-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/hidpi/clip-text-in-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/hidpi/clip-text-in-hidpi-expected.png index fb61704..1cd28c3 100644 --- a/third_party/WebKit/LayoutTests/platform/android/fast/hidpi/clip-text-in-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/android/fast/hidpi/clip-text-in-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/inline-block/overflow-clip-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/inline-block/overflow-clip-expected.png index 427482d..ef5b8415 100644 --- a/third_party/WebKit/LayoutTests/platform/android/fast/inline-block/overflow-clip-expected.png +++ b/third_party/WebKit/LayoutTests/platform/android/fast/inline-block/overflow-clip-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1/text-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1/text-align-06-b-expected.txt new file mode 100644 index 0000000..1cb2fd6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1/text-align-06-b-expected.txt
@@ -0,0 +1,67 @@ +layer at (0,0) size 480x360 + LayoutView at (0,0) size 480x360 +layer at (0,0) size 480x360 + LayoutSVGRoot {svg} at (0,0) size 480x360 + LayoutSVGContainer {g} at (0,4) size 472x356 + LayoutSVGText {text} at (0,4) size 472x45 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 472x45 + chunk 1 text run 1 at (0.00,40.00) startOffset 0 endOffset 31 width 472.00: "Test 'baseline-shift' (vertic.)" + LayoutSVGContainer {g} at (82,60) size 294x300 + LayoutSVGContainer {g} at (82,60) size 294x300 [transform={m=((1.00,0.00)(0.00,1.00)) t=(90.00,60.00)}] + LayoutSVGText {text} at (-8,0) size 24x175 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 16x70 + chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" + chunk 1 (vertical) text run 2 at (-10.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" + LayoutSVGTSpan {tspan} at (0,0) size 18x35 + LayoutSVGInlineText {#text} at (6,70) size 17x35 + chunk 1 (vertical) text run 1 at (-3.50,70.00) startOffset 0 endOffset 1 height 35.00: "7" + LayoutSVGInlineText {#text} at (1,105) size 14x70 + chunk 1 (vertical) text run 1 at (-10.50,105.00) startOffset 0 endOffset 1 height 35.00: "x" + chunk 1 (vertical) text run 2 at (-10.50,140.00) startOffset 1 endOffset 2 height 35.00: "t" + LayoutSVGText {text} at (45,0) size 43x280 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (26,0) size 16x70 + chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" + chunk 1 (vertical) text run 2 at (69.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" + LayoutSVGTSpan {tspan} at (0,0) size 27x140 + LayoutSVGInlineText {#text} at (0,70) size 27x140 + chunk 1 (vertical) text run 1 at (48.50,70.00) startOffset 0 endOffset 1 height 35.00: "-" + chunk 1 (vertical) text run 2 at (48.50,105.00) startOffset 1 endOffset 2 height 35.00: "7" + chunk 1 (vertical) text run 3 at (48.50,140.00) startOffset 2 endOffset 3 height 35.00: "0" + chunk 1 (vertical) text run 4 at (48.50,175.00) startOffset 3 endOffset 4 height 35.00: "%" + LayoutSVGInlineText {#text} at (27,210) size 14x70 + chunk 1 (vertical) text run 1 at (69.50,210.00) startOffset 0 endOffset 1 height 35.00: "x" + chunk 1 (vertical) text run 2 at (69.50,245.00) startOffset 1 endOffset 2 height 35.00: "t" + LayoutSVGText {text} at (154,0) size 34x245 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (18,0) size 16x70 + chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" + chunk 1 (vertical) text run 2 at (169.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" + LayoutSVGTSpan {tspan} at (0,0) size 17x105 + LayoutSVGInlineText {#text} at (0,70) size 17x105 + chunk 1 (vertical) text run 1 at (152.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" + chunk 1 (vertical) text run 2 at (152.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" + chunk 1 (vertical) text run 3 at (152.00,140.00) startOffset 2 endOffset 3 height 35.00: "b" + LayoutSVGTSpan {tspan} at (0,0) size 14x35 + LayoutSVGInlineText {#text} at (19,175) size 14x35 + chunk 1 (vertical) text run 1 at (169.50,175.00) startOffset 0 endOffset 1 height 35.00: "x" + LayoutSVGInlineText {#text} at (22,210) size 8x35 + chunk 1 (vertical) text run 1 at (169.50,210.00) startOffset 0 endOffset 1 height 35.00: "t" + LayoutSVGText {text} at (252,0) size 34x315 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 16x70 + chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" + chunk 1 (vertical) text run 2 at (249.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" + LayoutSVGTSpan {tspan} at (0,0) size 17x175 + LayoutSVGInlineText {#text} at (17,70) size 17x175 + chunk 1 (vertical) text run 1 at (267.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" + chunk 1 (vertical) text run 2 at (267.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" + chunk 1 (vertical) text run 3 at (267.00,140.00) startOffset 2 endOffset 3 height 35.00: "p" + chunk 1 (vertical) text run 4 at (267.00,175.00) startOffset 3 endOffset 4 height 35.00: "e" + chunk 1 (vertical) text run 5 at (267.00,210.00) startOffset 4 endOffset 5 height 35.00: "r" + LayoutSVGTSpan {tspan} at (0,0) size 14x35 + LayoutSVGInlineText {#text} at (1,245) size 14x35 + chunk 1 (vertical) text run 1 at (249.50,245.00) startOffset 0 endOffset 1 height 35.00: "x" + LayoutSVGInlineText {#text} at (4,280) size 8x35 + chunk 1 (vertical) text run 1 at (249.50,280.00) startOffset 0 endOffset 1 height 35.00: "t" + LayoutSVGText {text} at (10,304) size 261x46 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 261x46 + chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 261.00: "$Revision: 1.5 $" + LayoutSVGRect {rect} at (0,0) size 480x360 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/text-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/text-align-06-b-expected.txt index 1cb2fd6..7b03e961 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/text-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/text-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 16x70 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (-10.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x35 + LayoutSVGTSpan {tspan} at (0,0) size 36x17 LayoutSVGInlineText {#text} at (6,70) size 17x35 chunk 1 (vertical) text run 1 at (-3.50,70.00) startOffset 0 endOffset 1 height 35.00: "7" LayoutSVGInlineText {#text} at (1,105) size 14x70 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (26,0) size 16x70 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (69.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x140 + LayoutSVGTSpan {tspan} at (0,0) size 140x27 LayoutSVGInlineText {#text} at (0,70) size 27x140 chunk 1 (vertical) text run 1 at (48.50,70.00) startOffset 0 endOffset 1 height 35.00: "-" chunk 1 (vertical) text run 2 at (48.50,105.00) startOffset 1 endOffset 2 height 35.00: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (18,0) size 16x70 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (169.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x105 + LayoutSVGTSpan {tspan} at (0,0) size 105x17 LayoutSVGInlineText {#text} at (0,70) size 17x105 chunk 1 (vertical) text run 1 at (152.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" chunk 1 (vertical) text run 2 at (152.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" chunk 1 (vertical) text run 3 at (152.00,140.00) startOffset 2 endOffset 3 height 35.00: "b" - LayoutSVGTSpan {tspan} at (0,0) size 14x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x14 LayoutSVGInlineText {#text} at (19,175) size 14x35 chunk 1 (vertical) text run 1 at (169.50,175.00) startOffset 0 endOffset 1 height 35.00: "x" LayoutSVGInlineText {#text} at (22,210) size 8x35 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 16x70 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (249.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x175 + LayoutSVGTSpan {tspan} at (0,0) size 175x17 LayoutSVGInlineText {#text} at (17,70) size 17x175 chunk 1 (vertical) text run 1 at (267.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" chunk 1 (vertical) text run 2 at (267.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" chunk 1 (vertical) text run 3 at (267.00,140.00) startOffset 2 endOffset 3 height 35.00: "p" chunk 1 (vertical) text run 4 at (267.00,175.00) startOffset 3 endOffset 4 height 35.00: "e" chunk 1 (vertical) text run 5 at (267.00,210.00) startOffset 4 endOffset 5 height 35.00: "r" - LayoutSVGTSpan {tspan} at (0,0) size 14x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x14 LayoutSVGInlineText {#text} at (1,245) size 14x35 chunk 1 (vertical) text run 1 at (249.50,245.00) startOffset 0 endOffset 1 height 35.00: "x" LayoutSVGInlineText {#text} at (4,280) size 8x35
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalText-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalText-expected.txt index 2615546..c51b93f 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalText-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalText-expected.txt
@@ -185,7 +185,7 @@ chunk 1 (vertical) text run 7 at (345.50,123.00) startOffset 6 endOffset 7 height 17.00: "e" chunk 1 (vertical) text run 8 at (345.50,130.00) startOffset 7 endOffset 8 height 17.00: "d" chunk 1 (vertical) text run 9 at (345.50,137.00) startOffset 8 endOffset 9 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 17x47 + LayoutSVGTSpan {tspan} at (0,0) size 47x17 LayoutSVGInlineText {#text} at (0,66) size 17x47 chunk 1 (vertical) text run 1 at (345.50,141.00) startOffset 0 endOffset 1 height 17.00: "<" chunk 1 (vertical) text run 2 at (345.50,149.00) startOffset 1 endOffset 2 height 17.00: "t" @@ -214,7 +214,7 @@ chunk 1 (vertical) text run 7 at (395.50,123.00) startOffset 6 endOffset 7 height 17.00: "e" chunk 1 (vertical) text run 8 at (395.50,130.00) startOffset 7 endOffset 8 height 17.00: "d" chunk 1 (vertical) text run 9 at (395.50,137.00) startOffset 8 endOffset 9 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 7x170 + LayoutSVGTSpan {tspan} at (0,0) size 170x7 LayoutSVGInlineText {#text} at (5,66) size 7x170 chunk 1 (vertical) text run 1 at (395.50,141.00) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (395.50,158.00) startOffset 1 endOffset 2 height 17.00: "r" @@ -239,7 +239,7 @@ LayoutSVGContainer {use} at (54,450) size 317x45 LayoutSVGPath {path} at (54,449) size 317x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 0 1000 100 C 1100 200 1200 300 1300 200 C 1400 100 1500 0 1600 100 C 1700 200 1800 300 1900 200 C 2000 100 2100 0 2200 100"] LayoutSVGText {text} at (12,1) size 319x40 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 318x39 + LayoutSVGTextPath {textPath} at (0,0) size 39x318 LayoutSVGInlineText {#text} at (0,0) size 318x39 chunk 1 (vertical) text run 1 at (20.41,24.64) startOffset 0 endOffset 1 height 15.00: "V" chunk 1 (vertical) text run 2 at (31.65,14.87) startOffset 1 endOffset 2 height 15.00: "e"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalTextOnPath-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalTextOnPath-expected.txt index 0b031ff..3a3e726 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalTextOnPath-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/verticalTextOnPath-expected.txt
@@ -13,14 +13,14 @@ LayoutSVGContainer {use} at (14,70) size 121x45 LayoutSVGPath {path} at (14,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (9,-10) size 81x53 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x53 + LayoutSVGTextPath {textPath} at (0,0) size 53x81 LayoutSVGInlineText {#text} at (0,12) size 34x34 chunk 1 (vertical) text run 1 at (18.25,26.76) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (24.02,21.22) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (29.31,16.66) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (33.75,13.42) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (37.16,11.42) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 22x19 + LayoutSVGTSpan {tspan} at (0,0) size 19x22 LayoutSVGInlineText {#text} at (25,0) size 22x19 chunk 1 (vertical) text run 1 at (42.30,9.40) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (49.21,8.97) startOffset 1 endOffset 2 height 17.00: "n" @@ -47,11 +47,11 @@ LayoutSVGContainer {use} at (164,70) size 121x45 LayoutSVGPath {path} at (164,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (13,5) size 103x34 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 102x34 + LayoutSVGTextPath {textPath} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 102x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (0,0) size 102x34 chunk 1 (middle anchor, vertical) text run 1 at (21.14,23.94) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (34.18,13.14) startOffset 1 endOffset 2 height 17.00: "a" @@ -74,11 +74,11 @@ LayoutSVGContainer {use} at (314,70) size 121x45 LayoutSVGPath {path} at (314,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (11,3) size 61x31 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 61x31 + LayoutSVGTextPath {textPath} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 61x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (0,0) size 61x31 chunk 1 (end anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "P" chunk 1 (end anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: "a" @@ -98,18 +98,18 @@ LayoutSVGContainer {use} at (14,170) size 121x45 LayoutSVGPath {path} at (14,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (67,6) size 69x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 68x39 + LayoutSVGTextPath {textPath} at (0,0) size 39x68 LayoutSVGInlineText {#text} at (0,13) size 37x25 chunk 1 (vertical) text run 1 at (75.96,29.62) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (82.71,33.85) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (89.36,36.03) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (94.80,35.93) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (98.61,34.66) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 22x24 + LayoutSVGTSpan {tspan} at (0,0) size 23x23 LayoutSVGInlineText {#text} at (21,3) size 22x23 chunk 1 (vertical) text run 1 at (103.11,31.73) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (108.48,26.78) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 29x25 + LayoutSVGTSpan {tspan} at (0,0) size 25x29 LayoutSVGInlineText {#text} at (39,0) size 29x25 chunk 1 (vertical) text run 1 at (112.82,23.41) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (vertical) text run 2 at (117.46,20.49) startOffset 1 endOffset 2 height 17.00: "a" @@ -129,15 +129,15 @@ LayoutSVGContainer {use} at (164,170) size 121x45 LayoutSVGPath {path} at (164,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (15,-6) size 119x48 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 118x47 + LayoutSVGTextPath {textPath} at (0,0) size 47x118 LayoutSVGInlineText {#text} at (0,11) size 30x24 chunk 1 (middle anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (middle anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 34x28 + LayoutSVGTSpan {tspan} at (0,0) size 29x34 LayoutSVGInlineText {#text} at (32,0) size 34x28 chunk 1 (middle anchor, vertical) text run 1 at (53.13,10.12) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (66.22,21.14) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 63x32 + LayoutSVGTSpan {tspan} at (0,0) size 32x64 LayoutSVGInlineText {#text} at (55,15) size 63x31 chunk 1 (middle anchor, vertical) text run 1 at (79.28,31.92) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (95.28,35.82) startOffset 1 endOffset 2 height 17.00: "a" @@ -157,18 +157,18 @@ LayoutSVGContainer {use} at (314,170) size 121x45 LayoutSVGPath {path} at (314,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (48,2) size 81x43 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x43 + LayoutSVGTextPath {textPath} at (0,0) size 43x81 LayoutSVGInlineText {#text} at (0,0) size 34x35 chunk 1 (end anchor, vertical) text run 1 at (56.60,12.10) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (end anchor, vertical) text run 2 at (62.70,17.69) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (end anchor, vertical) text run 3 at (67.75,22.60) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (end anchor, vertical) text run 4 at (71.76,26.22) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (end anchor, vertical) text run 5 at (74.88,28.79) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x22 + LayoutSVGTSpan {tspan} at (0,0) size 21x19 LayoutSVGInlineText {#text} at (29,11) size 18x21 chunk 1 (end anchor, vertical) text run 1 at (79.38,31.98) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (end anchor, vertical) text run 2 at (85.64,35.09) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 41x37 + LayoutSVGTSpan {tspan} at (0,0) size 37x41 LayoutSVGInlineText {#text} at (40,6) size 41x36 chunk 1 (end anchor, vertical) text run 1 at (90.97,36.19) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (end anchor, vertical) text run 2 at (96.34,35.54) startOffset 1 endOffset 2 height 17.00: "a" @@ -191,14 +191,14 @@ LayoutSVGContainer {use} at (14,270) size 121x45 LayoutSVGPath {path} at (14,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (37,1) size 87x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 86x38 + LayoutSVGTextPath {textPath} at (0,0) size 38x86 LayoutSVGInlineText {#text} at (0,0) size 75x38 chunk 1 (vertical) text run 1 at (51.11,9.39) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (64.70,19.66) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (77.48,30.72) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (93.24,36.15) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (107.64,27.51) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x14 + LayoutSVGTSpan {tspan} at (0,0) size 14x19 LayoutSVGInlineText {#text} at (67,2) size 19x14 chunk 1 (vertical) text run 1 at (121.81,18.34) startOffset 0 endOffset 1 height 17.00: "o" LayoutSVGTSpan {tspan} at (0,0) size 1x1 @@ -217,16 +217,16 @@ LayoutSVGContainer {use} at (164,270) size 121x45 LayoutSVGPath {path} at (164,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (10,-6) size 70x41 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 69x41 + LayoutSVGTextPath {textPath} at (0,0) size 41x69 LayoutSVGInlineText {#text} at (0,17) size 23x23 chunk 1 (middle anchor, vertical) text run 1 at (19.33,25.70) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (middle anchor, vertical) text run 2 at (23.30,21.89) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (middle anchor, vertical) text run 3 at (26.19,19.27) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 23x23 + LayoutSVGTSpan {tspan} at (0,0) size 24x23 LayoutSVGInlineText {#text} at (5,0) size 23x23 chunk 1 (middle anchor, vertical) text run 1 at (30.48,15.74) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (36.31,11.88) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 43x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x44 LayoutSVGInlineText {#text} at (26,6) size 43x35 chunk 1 (middle anchor, vertical) text run 1 at (41.36,9.67) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (46.74,8.79) startOffset 1 endOffset 2 height 17.00: "a" @@ -246,11 +246,11 @@ LayoutSVGContainer {use} at (314,270) size 121x45 LayoutSVGPath {path} at (314,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (7,6) size 32x32 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 32x31 + LayoutSVGTextPath {textPath} at (0,0) size 31x32 LayoutSVGInlineText {#text} at (-7,-6) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-7,-6) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 32x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x32 LayoutSVGInlineText {#text} at (0,0) size 32x31 chunk 1 (end anchor, vertical) text run 1 at (16.80,28.20) startOffset 3 endOffset 4 height 17.00: "P" chunk 1 (end anchor, vertical) text run 2 at (22.58,22.56) startOffset 4 endOffset 5 height 17.00: "a" @@ -270,8 +270,8 @@ LayoutSVGContainer {use} at (39,370) size 92x50 LayoutSVGPath {path} at (39,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (12,4) size 114x46 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 114x46 - LayoutSVGTSpan {tspan} at (0,0) size 31x41 + LayoutSVGTextPath {textPath} at (0,0) size 46x114 + LayoutSVGTSpan {tspan} at (0,0) size 41x31 LayoutSVGInlineText {#text} at (0,5) size 31x41 chunk 1 (vertical) text run 1 at (30.12,46.89) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (31.17,40.56) startOffset 1 endOffset 2 height 17.00: "u" @@ -284,7 +284,7 @@ chunk 1 (vertical) text run 3 at (56.35,15.52) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (63.11,13.69) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (68.55,12.84) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 21x19 + LayoutSVGTSpan {tspan} at (0,0) size 20x21 LayoutSVGInlineText {#text} at (57,8) size 20x19 chunk 1 (vertical) text run 1 at (73.55,12.52) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (80.06,12.71) startOffset 1 endOffset 2 height 17.00: "u" @@ -311,8 +311,8 @@ LayoutSVGContainer {use} at (329,370) size 92x50 LayoutSVGPath {path} at (329,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (18,3) size 107x48 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 106x47 - LayoutSVGTSpan {tspan} at (0,0) size 38x46 + LayoutSVGTextPath {textPath} at (0,0) size 47x106 + LayoutSVGTSpan {tspan} at (0,0) size 45x39 LayoutSVGInlineText {#text} at (0,1) size 38x45 chunk 1 (vertical) text run 1 at (30.16,46.38) startOffset 0 endOffset 1 height 17.00: "p" chunk 1 (vertical) text run 2 at (31.45,39.57) startOffset 1 endOffset 2 height 17.00: "o" @@ -328,7 +328,7 @@ chunk 1 (vertical) text run 3 at (68.06,12.90) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (75.05,12.50) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (80.56,12.76) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 44x38 + LayoutSVGTSpan {tspan} at (0,0) size 38x45 LayoutSVGInlineText {#text} at (62,3) size 44x38 chunk 1 (vertical) text run 1 at (86.01,13.52) startOffset 0 endOffset 1 height 17.00: "n" chunk 1 (vertical) text run 2 at (92.80,15.24) startOffset 1 endOffset 2 height 17.00: "e" @@ -363,7 +363,7 @@ chunk 1 (vertical) text run 10 at (4.00,54.67) startOffset 9 endOffset 10 height 22.67: "t" chunk 1 (vertical) text run 11 at (4.00,60.00) startOffset 10 endOffset 11 height 22.67: "h" chunk 1 (vertical) text run 12 at (4.00,69.33) startOffset 11 endOffset 12 height 22.67: " " - LayoutSVGTextPath {textPath} at (0,0) size 59x42 + LayoutSVGTextPath {textPath} at (0,0) size 42x59 LayoutSVGInlineText {#text} at (23,21) size 58x42 chunk 1 (vertical) text run 1 at (34.24,32.91) startOffset 0 endOffset 1 height 22.67: "o" chunk 1 (vertical) text run 2 at (39.86,25.49) startOffset 1 endOffset 2 height 22.67: "n"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-06-b-expected.txt index 13c28a9d..91de2bb0 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 17x69 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 34.20: "t" chunk 1 (vertical) text run 2 at (-10.50,34.20) startOffset 1 endOffset 2 height 34.20: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x18 LayoutSVGInlineText {#text} at (7,68) size 17x35 chunk 1 (vertical) text run 1 at (-3.50,68.40) startOffset 0 endOffset 1 height 34.20: "7" LayoutSVGInlineText {#text} at (1,102) size 15x69 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (25,0) size 17x69 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 34.20: "t" chunk 1 (vertical) text run 2 at (69.50,34.20) startOffset 1 endOffset 2 height 34.20: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x138 + LayoutSVGTSpan {tspan} at (0,0) size 137x27 LayoutSVGInlineText {#text} at (0,68) size 27x137 chunk 1 (vertical) text run 1 at (48.50,68.40) startOffset 0 endOffset 1 height 34.20: "-" chunk 1 (vertical) text run 2 at (48.50,102.60) startOffset 1 endOffset 2 height 34.20: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (17,0) size 17x69 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 34.20: "t" chunk 1 (vertical) text run 2 at (169.50,34.20) startOffset 1 endOffset 2 height 34.20: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x103 + LayoutSVGTSpan {tspan} at (0,0) size 103x18 LayoutSVGInlineText {#text} at (0,68) size 17x103 chunk 1 (vertical) text run 1 at (152.00,68.40) startOffset 0 endOffset 1 height 34.20: "s" chunk 1 (vertical) text run 2 at (152.00,102.60) startOffset 1 endOffset 2 height 34.20: "u" chunk 1 (vertical) text run 3 at (152.00,136.80) startOffset 2 endOffset 3 height 34.20: "b" - LayoutSVGTSpan {tspan} at (0,0) size 16x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x15 LayoutSVGInlineText {#text} at (18,171) size 15x35 chunk 1 (vertical) text run 1 at (169.50,171.00) startOffset 0 endOffset 1 height 34.20: "x" LayoutSVGInlineText {#text} at (21,205) size 9x35 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 17x69 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 34.20: "t" chunk 1 (vertical) text run 2 at (249.50,34.20) startOffset 1 endOffset 2 height 34.20: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x172 + LayoutSVGTSpan {tspan} at (0,0) size 172x18 LayoutSVGInlineText {#text} at (17,68) size 17x171 chunk 1 (vertical) text run 1 at (267.00,68.40) startOffset 0 endOffset 1 height 34.20: "s" chunk 1 (vertical) text run 2 at (267.00,102.60) startOffset 1 endOffset 2 height 34.20: "u" chunk 1 (vertical) text run 3 at (267.00,136.80) startOffset 2 endOffset 3 height 34.20: "p" chunk 1 (vertical) text run 4 at (267.00,171.00) startOffset 3 endOffset 4 height 34.20: "e" chunk 1 (vertical) text run 5 at (267.00,205.20) startOffset 4 endOffset 5 height 34.20: "r" - LayoutSVGTSpan {tspan} at (0,0) size 15x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x15 LayoutSVGInlineText {#text} at (1,239) size 15x35 chunk 1 (vertical) text run 1 at (249.50,239.40) startOffset 0 endOffset 1 height 34.20: "x" LayoutSVGInlineText {#text} at (4,273) size 9x35
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-brightness-clamping-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-brightness-clamping-hw-expected.png deleted file mode 100644 index 5ce420cc..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-brightness-clamping-hw-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-combined-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-combined-hw-expected.png deleted file mode 100644 index c0f03d6f..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/css3/filters/effect-combined-hw-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-brightness-clamping-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-brightness-clamping-hw-expected.png index 3d9852ef..5ce420cc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-brightness-clamping-hw-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-brightness-clamping-hw-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-combined-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-combined-hw-expected.png index fbead74..c0f03d6f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-combined-hw-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-combined-hw-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/text-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/text-align-06-b-expected.txt index 13e611dfd..e4a44ec 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/text-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/text-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 17x66 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (-10.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x33 + LayoutSVGTSpan {tspan} at (0,0) size 33x17 LayoutSVGInlineText {#text} at (7,66) size 17x33 chunk 1 (vertical) text run 1 at (-3.50,66.00) startOffset 0 endOffset 1 height 33.00: "7" LayoutSVGInlineText {#text} at (0,99) size 15x66 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (26,0) size 17x66 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (69.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x132 + LayoutSVGTSpan {tspan} at (0,0) size 132x27 LayoutSVGInlineText {#text} at (0,66) size 27x132 chunk 1 (vertical) text run 1 at (48.50,66.00) startOffset 0 endOffset 1 height 33.00: "-" chunk 1 (vertical) text run 2 at (48.50,99.00) startOffset 1 endOffset 2 height 33.00: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (16,0) size 17x66 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (169.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x99 + LayoutSVGTSpan {tspan} at (0,0) size 99x17 LayoutSVGInlineText {#text} at (0,66) size 17x99 chunk 1 (vertical) text run 1 at (153.00,66.00) startOffset 0 endOffset 1 height 33.00: "s" chunk 1 (vertical) text run 2 at (153.00,99.00) startOffset 1 endOffset 2 height 33.00: "u" chunk 1 (vertical) text run 3 at (153.00,132.00) startOffset 2 endOffset 3 height 33.00: "b" - LayoutSVGTSpan {tspan} at (0,0) size 16x33 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (17,165) size 15x33 chunk 1 (vertical) text run 1 at (169.50,165.00) startOffset 0 endOffset 1 height 33.00: "x" LayoutSVGInlineText {#text} at (20,198) size 9x33 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 17x66 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (249.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x165 + LayoutSVGTSpan {tspan} at (0,0) size 166x17 LayoutSVGInlineText {#text} at (16,66) size 17x165 chunk 1 (vertical) text run 1 at (266.00,66.00) startOffset 0 endOffset 1 height 33.00: "s" chunk 1 (vertical) text run 2 at (266.00,99.00) startOffset 1 endOffset 2 height 33.00: "u" chunk 1 (vertical) text run 3 at (266.00,132.00) startOffset 2 endOffset 3 height 33.00: "p" chunk 1 (vertical) text run 4 at (266.00,165.00) startOffset 3 endOffset 4 height 33.00: "e" chunk 1 (vertical) text run 5 at (266.00,198.00) startOffset 4 endOffset 5 height 33.00: "r" - LayoutSVGTSpan {tspan} at (0,0) size 16x33 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (0,231) size 15x33 chunk 1 (vertical) text run 1 at (249.50,231.00) startOffset 0 endOffset 1 height 33.00: "x" LayoutSVGInlineText {#text} at (4,264) size 9x33
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalText-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalText-expected.txt index 4ab8690..0cf6883 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalText-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalText-expected.txt
@@ -185,7 +185,7 @@ chunk 1 (vertical) text run 7 at (345.50,124.99) startOffset 6 endOffset 7 height 17.00: "e" chunk 1 (vertical) text run 8 at (345.50,131.65) startOffset 7 endOffset 8 height 17.00: "d" chunk 1 (vertical) text run 9 at (345.50,139.15) startOffset 8 endOffset 9 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 17x50 + LayoutSVGTSpan {tspan} at (0,0) size 49x18 LayoutSVGInlineText {#text} at (0,67) size 17x49 chunk 1 (vertical) text run 1 at (345.50,142.90) startOffset 0 endOffset 1 height 17.00: "<" chunk 1 (vertical) text run 2 at (345.50,151.35) startOffset 1 endOffset 2 height 17.00: "t" @@ -214,7 +214,7 @@ chunk 1 (vertical) text run 7 at (395.50,124.99) startOffset 6 endOffset 7 height 17.00: "e" chunk 1 (vertical) text run 8 at (395.50,131.65) startOffset 7 endOffset 8 height 17.00: "d" chunk 1 (vertical) text run 9 at (395.50,139.15) startOffset 8 endOffset 9 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 9x171 + LayoutSVGTSpan {tspan} at (0,0) size 171x9 LayoutSVGInlineText {#text} at (4,67) size 8x170 chunk 1 (vertical) text run 1 at (395.50,142.90) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (395.50,159.90) startOffset 1 endOffset 2 height 17.00: "r" @@ -239,7 +239,7 @@ LayoutSVGContainer {use} at (54,450) size 317x45 LayoutSVGPath {path} at (54,449) size 317x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 0 1000 100 C 1100 200 1200 300 1300 200 C 1400 100 1500 0 1600 100 C 1700 200 1800 300 1900 200 C 2000 100 2100 0 2200 100"] LayoutSVGText {text} at (12,5) size 297x36 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 297x35 + LayoutSVGTextPath {textPath} at (0,0) size 35x297 LayoutSVGInlineText {#text} at (0,0) size 297x35 chunk 1 (vertical) text run 1 at (20.05,24.99) startOffset 0 endOffset 1 height 14.00: "V" chunk 1 (vertical) text run 2 at (30.48,15.74) startOffset 1 endOffset 2 height 14.00: "e"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalTextOnPath-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalTextOnPath-expected.txt index df5b2c9..82720ba 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalTextOnPath-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/verticalTextOnPath-expected.txt
@@ -13,18 +13,18 @@ LayoutSVGContainer {use} at (14,70) size 121x45 LayoutSVGPath {path} at (14,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (9,-10) size 81x53 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x53 + LayoutSVGTextPath {textPath} at (0,0) size 53x81 LayoutSVGInlineText {#text} at (0,12) size 34x34 chunk 1 (vertical) text run 1 at (18.31,26.70) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (24.02,21.22) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (29.36,16.61) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (34.10,13.19) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (37.47,11.26) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 24x19 + LayoutSVGTSpan {tspan} at (0,0) size 20x23 LayoutSVGInlineText {#text} at (25,0) size 23x19 chunk 1 (vertical) text run 1 at (42.75,9.28) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (50.15,9.15) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 41x41 + LayoutSVGTSpan {tspan} at (0,0) size 41x42 LayoutSVGInlineText {#text} at (40,12) size 41x40 chunk 1 (vertical) text run 1 at (55.32,11.26) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (vertical) text run 2 at (59.46,14.47) startOffset 1 endOffset 2 height 17.00: "a" @@ -47,11 +47,11 @@ LayoutSVGContainer {use} at (164,70) size 121x45 LayoutSVGPath {path} at (164,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (13,5) size 103x34 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 102x34 + LayoutSVGTextPath {textPath} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 102x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (0,0) size 102x34 chunk 1 (middle anchor, vertical) text run 1 at (21.14,23.94) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (34.18,13.14) startOffset 1 endOffset 2 height 17.00: "a" @@ -74,11 +74,11 @@ LayoutSVGContainer {use} at (314,70) size 121x45 LayoutSVGPath {path} at (314,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (11,3) size 62x31 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 61x31 + LayoutSVGTextPath {textPath} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 61x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (0,0) size 61x31 chunk 1 (end anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "P" chunk 1 (end anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: "a" @@ -98,18 +98,18 @@ LayoutSVGContainer {use} at (14,170) size 121x45 LayoutSVGPath {path} at (14,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (67,6) size 68x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 68x39 + LayoutSVGTextPath {textPath} at (0,0) size 39x68 LayoutSVGInlineText {#text} at (0,13) size 38x25 chunk 1 (vertical) text run 1 at (76.02,29.67) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (82.70,33.85) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (89.43,36.04) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (95.19,35.84) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (98.95,34.49) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 23x24 + LayoutSVGTSpan {tspan} at (0,0) size 24x24 LayoutSVGInlineText {#text} at (21,2) size 23x24 chunk 1 (vertical) text run 1 at (103.50,31.40) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (109.21,26.16) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 28x25 + LayoutSVGTSpan {tspan} at (0,0) size 25x28 LayoutSVGInlineText {#text} at (40,0) size 28x25 chunk 1 (vertical) text run 1 at (113.73,22.78) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (vertical) text run 2 at (118.19,20.09) startOffset 1 endOffset 2 height 17.00: "a" @@ -129,15 +129,15 @@ LayoutSVGContainer {use} at (164,170) size 121x45 LayoutSVGPath {path} at (164,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (15,-6) size 119x47 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 118x47 + LayoutSVGTextPath {textPath} at (0,0) size 47x118 LayoutSVGInlineText {#text} at (0,11) size 30x24 chunk 1 (middle anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (middle anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 35x29 + LayoutSVGTSpan {tspan} at (0,0) size 29x35 LayoutSVGInlineText {#text} at (32,0) size 35x29 chunk 1 (middle anchor, vertical) text run 1 at (53.13,10.12) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (66.22,21.14) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 63x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x63 LayoutSVGInlineText {#text} at (55,16) size 63x31 chunk 1 (middle anchor, vertical) text run 1 at (79.28,31.92) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (95.28,35.82) startOffset 1 endOffset 2 height 17.00: "a" @@ -157,18 +157,18 @@ LayoutSVGContainer {use} at (314,170) size 121x45 LayoutSVGPath {path} at (314,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (48,2) size 82x43 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x42 + LayoutSVGTextPath {textPath} at (0,0) size 42x81 LayoutSVGInlineText {#text} at (0,0) size 34x35 chunk 1 (end anchor, vertical) text run 1 at (57.02,12.40) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (end anchor, vertical) text run 2 at (63.00,18.00) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (end anchor, vertical) text run 3 at (68.12,22.94) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (end anchor, vertical) text run 4 at (72.41,26.78) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (end anchor, vertical) text run 5 at (75.50,29.28) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x22 + LayoutSVGTSpan {tspan} at (0,0) size 21x19 LayoutSVGInlineText {#text} at (29,11) size 18x21 chunk 1 (end anchor, vertical) text run 1 at (80.17,32.47) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (end anchor, vertical) text run 2 at (86.97,35.51) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 39x36 + LayoutSVGTSpan {tspan} at (0,0) size 36x39 LayoutSVGInlineText {#text} at (42,6) size 39x36 chunk 1 (end anchor, vertical) text run 1 at (92.52,36.20) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (end anchor, vertical) text run 2 at (97.53,35.13) startOffset 1 endOffset 2 height 17.00: "a" @@ -191,14 +191,14 @@ LayoutSVGContainer {use} at (14,270) size 121x45 LayoutSVGPath {path} at (14,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (37,1) size 87x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 86x38 + LayoutSVGTextPath {textPath} at (0,0) size 38x86 LayoutSVGInlineText {#text} at (0,0) size 75x38 chunk 1 (vertical) text run 1 at (51.11,9.39) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (64.70,19.66) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (77.48,30.72) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (93.24,36.15) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (107.64,27.51) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x15 + LayoutSVGTSpan {tspan} at (0,0) size 14x19 LayoutSVGInlineText {#text} at (67,2) size 19x14 chunk 1 (vertical) text run 1 at (121.81,18.34) startOffset 0 endOffset 1 height 17.00: "o" LayoutSVGTSpan {tspan} at (0,0) size 1x1 @@ -217,7 +217,7 @@ LayoutSVGContainer {use} at (164,270) size 121x45 LayoutSVGPath {path} at (164,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (10,-7) size 70x42 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 70x42 + LayoutSVGTextPath {textPath} at (0,0) size 42x70 LayoutSVGInlineText {#text} at (0,18) size 23x23 chunk 1 (middle anchor, vertical) text run 1 at (19.54,25.49) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (middle anchor, vertical) text run 2 at (23.75,21.47) startOffset 3 endOffset 4 height 17.00: "t" @@ -226,7 +226,7 @@ LayoutSVGInlineText {#text} at (6,0) size 24x24 chunk 1 (middle anchor, vertical) text run 1 at (31.03,15.33) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (37.34,11.33) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 43x36 + LayoutSVGTSpan {tspan} at (0,0) size 36x43 LayoutSVGInlineText {#text} at (27,6) size 42x35 chunk 1 (middle anchor, vertical) text run 1 at (42.61,9.32) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (47.77,8.82) startOffset 1 endOffset 2 height 17.00: "a" @@ -270,8 +270,8 @@ LayoutSVGContainer {use} at (39,370) size 92x50 LayoutSVGPath {path} at (39,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (12,4) size 115x46 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 115x46 - LayoutSVGTSpan {tspan} at (0,0) size 31x42 + LayoutSVGTextPath {textPath} at (0,0) size 46x115 + LayoutSVGTSpan {tspan} at (0,0) size 41x32 LayoutSVGInlineText {#text} at (0,4) size 31x41 chunk 1 (vertical) text run 1 at (30.11,46.97) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (31.20,40.47) startOffset 1 endOffset 2 height 17.00: "u" @@ -284,7 +284,7 @@ chunk 1 (vertical) text run 3 at (56.49,15.48) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (63.74,13.56) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (69.32,12.77) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 21x20 + LayoutSVGTSpan {tspan} at (0,0) size 20x21 LayoutSVGInlineText {#text} at (58,8) size 21x19 chunk 1 (vertical) text run 1 at (74.12,12.51) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (80.79,12.78) startOffset 1 endOffset 2 height 17.00: "u" @@ -311,8 +311,8 @@ LayoutSVGContainer {use} at (329,370) size 92x50 LayoutSVGPath {path} at (329,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (18,3) size 108x48 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 108x47 - LayoutSVGTSpan {tspan} at (0,0) size 41x47 + LayoutSVGTextPath {textPath} at (0,0) size 47x108 + LayoutSVGTSpan {tspan} at (0,0) size 46x42 LayoutSVGInlineText {#text} at (0,0) size 41x46 chunk 1 (vertical) text run 1 at (30.19,46.13) startOffset 0 endOffset 1 height 17.00: "p" chunk 1 (vertical) text run 2 at (31.67,38.84) startOffset 1 endOffset 2 height 17.00: "o" @@ -328,7 +328,7 @@ chunk 1 (vertical) text run 3 at (71.20,12.62) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (78.71,12.61) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (84.31,13.22) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 44x41 + LayoutSVGTSpan {tspan} at (0,0) size 42x43 LayoutSVGInlineText {#text} at (64,4) size 43x41 chunk 1 (vertical) text run 1 at (89.83,14.37) startOffset 0 endOffset 1 height 17.00: "n" chunk 1 (vertical) text run 2 at (96.55,16.62) startOffset 1 endOffset 2 height 17.00: "e" @@ -363,7 +363,7 @@ chunk 1 (vertical) text run 10 at (3.50,54.95) startOffset 9 endOffset 10 height 22.67: "t" chunk 1 (vertical) text run 11 at (3.50,60.51) startOffset 10 endOffset 11 height 22.67: "h" chunk 1 (vertical) text run 12 at (3.50,70.51) startOffset 11 endOffset 12 height 22.67: " " - LayoutSVGTextPath {textPath} at (0,0) size 61x42 + LayoutSVGTextPath {textPath} at (0,0) size 42x61 LayoutSVGInlineText {#text} at (24,21) size 60x42 chunk 1 (vertical) text run 1 at (34.40,32.61) startOffset 0 endOffset 1 height 22.67: "o" chunk 1 (vertical) text run 2 at (40.58,24.79) startOffset 1 endOffset 2 height 22.67: "n"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-06-b-expected.txt index 21673a9..04464a01 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 17x68 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (-10.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x17 LayoutSVGInlineText {#text} at (7,67) size 17x34 chunk 1 (vertical) text run 1 at (-3.50,67.20) startOffset 0 endOffset 1 height 33.60: "7" LayoutSVGInlineText {#text} at (0,100) size 15x68 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (26,0) size 17x68 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (69.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x135 + LayoutSVGTSpan {tspan} at (0,0) size 135x27 LayoutSVGInlineText {#text} at (0,67) size 27x135 chunk 1 (vertical) text run 1 at (48.50,67.20) startOffset 0 endOffset 1 height 33.60: "-" chunk 1 (vertical) text run 2 at (48.50,100.80) startOffset 1 endOffset 2 height 33.60: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (16,0) size 17x68 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (169.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x101 + LayoutSVGTSpan {tspan} at (0,0) size 101x17 LayoutSVGInlineText {#text} at (0,67) size 17x101 chunk 1 (vertical) text run 1 at (153.00,67.20) startOffset 0 endOffset 1 height 33.60: "s" chunk 1 (vertical) text run 2 at (153.00,100.80) startOffset 1 endOffset 2 height 33.60: "u" chunk 1 (vertical) text run 3 at (153.00,134.40) startOffset 2 endOffset 3 height 33.60: "b" - LayoutSVGTSpan {tspan} at (0,0) size 16x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (17,168) size 15x34 chunk 1 (vertical) text run 1 at (169.50,168.00) startOffset 0 endOffset 1 height 33.60: "x" LayoutSVGInlineText {#text} at (20,201) size 9x34 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 17x68 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (249.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x169 + LayoutSVGTSpan {tspan} at (0,0) size 169x17 LayoutSVGInlineText {#text} at (16,67) size 17x168 chunk 1 (vertical) text run 1 at (266.00,67.20) startOffset 0 endOffset 1 height 33.60: "s" chunk 1 (vertical) text run 2 at (266.00,100.80) startOffset 1 endOffset 2 height 33.60: "u" chunk 1 (vertical) text run 3 at (266.00,134.40) startOffset 2 endOffset 3 height 33.60: "p" chunk 1 (vertical) text run 4 at (266.00,168.00) startOffset 3 endOffset 4 height 33.60: "e" chunk 1 (vertical) text run 5 at (266.00,201.60) startOffset 4 endOffset 5 height 33.60: "r" - LayoutSVGTSpan {tspan} at (0,0) size 16x34 + LayoutSVGTSpan {tspan} at (0,0) size 35x16 LayoutSVGInlineText {#text} at (0,235) size 15x34 chunk 1 (vertical) text run 1 at (249.50,235.20) startOffset 0 endOffset 1 height 33.60: "x" LayoutSVGInlineText {#text} at (4,268) size 9x34
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/W3C-SVG-1.1/text-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/svg/W3C-SVG-1.1/text-align-06-b-expected.txt index 1cb2fd6..1b6d5545 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/W3C-SVG-1.1/text-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/W3C-SVG-1.1/text-align-06-b-expected.txt
@@ -1,67 +1,67 @@ layer at (0,0) size 480x360 - LayoutView at (0,0) size 480x360 + RenderView at (0,0) size 480x360 layer at (0,0) size 480x360 - LayoutSVGRoot {svg} at (0,0) size 480x360 - LayoutSVGContainer {g} at (0,4) size 472x356 - LayoutSVGText {text} at (0,4) size 472x45 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 472x45 + RenderSVGRoot {svg} at (0,0) size 480x360 + RenderSVGContainer {g} at (0,4) size 472x356 + RenderSVGText {text} at (0,4) size 472x45 contains 1 chunk(s) + RenderSVGInlineText {#text} at (0,0) size 472x45 chunk 1 text run 1 at (0.00,40.00) startOffset 0 endOffset 31 width 472.00: "Test 'baseline-shift' (vertic.)" - LayoutSVGContainer {g} at (82,60) size 294x300 - LayoutSVGContainer {g} at (82,60) size 294x300 [transform={m=((1.00,0.00)(0.00,1.00)) t=(90.00,60.00)}] - LayoutSVGText {text} at (-8,0) size 24x175 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 16x70 + RenderSVGContainer {g} at (82,60) size 294x300 + RenderSVGContainer {g} at (82,60) size 294x300 [transform={m=((1.00,0.00)(0.00,1.00)) t=(90.00,60.00)}] + RenderSVGText {text} at (-8,0) size 24x175 contains 1 chunk(s) + RenderSVGInlineText {#text} at (0,0) size 16x70 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (-10.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x35 - LayoutSVGInlineText {#text} at (6,70) size 17x35 + RenderSVGTSpan {tspan} at (0,0) size 18x35 + RenderSVGInlineText {#text} at (6,70) size 17x35 chunk 1 (vertical) text run 1 at (-3.50,70.00) startOffset 0 endOffset 1 height 35.00: "7" - LayoutSVGInlineText {#text} at (1,105) size 14x70 + RenderSVGInlineText {#text} at (1,105) size 14x70 chunk 1 (vertical) text run 1 at (-10.50,105.00) startOffset 0 endOffset 1 height 35.00: "x" chunk 1 (vertical) text run 2 at (-10.50,140.00) startOffset 1 endOffset 2 height 35.00: "t" - LayoutSVGText {text} at (45,0) size 43x280 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (26,0) size 16x70 + RenderSVGText {text} at (45,0) size 43x280 contains 1 chunk(s) + RenderSVGInlineText {#text} at (26,0) size 16x70 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (69.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x140 - LayoutSVGInlineText {#text} at (0,70) size 27x140 + RenderSVGTSpan {tspan} at (0,0) size 27x140 + RenderSVGInlineText {#text} at (0,70) size 27x140 chunk 1 (vertical) text run 1 at (48.50,70.00) startOffset 0 endOffset 1 height 35.00: "-" chunk 1 (vertical) text run 2 at (48.50,105.00) startOffset 1 endOffset 2 height 35.00: "7" chunk 1 (vertical) text run 3 at (48.50,140.00) startOffset 2 endOffset 3 height 35.00: "0" chunk 1 (vertical) text run 4 at (48.50,175.00) startOffset 3 endOffset 4 height 35.00: "%" - LayoutSVGInlineText {#text} at (27,210) size 14x70 + RenderSVGInlineText {#text} at (27,210) size 14x70 chunk 1 (vertical) text run 1 at (69.50,210.00) startOffset 0 endOffset 1 height 35.00: "x" chunk 1 (vertical) text run 2 at (69.50,245.00) startOffset 1 endOffset 2 height 35.00: "t" - LayoutSVGText {text} at (154,0) size 34x245 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (18,0) size 16x70 + RenderSVGText {text} at (154,0) size 34x245 contains 1 chunk(s) + RenderSVGInlineText {#text} at (18,0) size 16x70 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (169.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x105 - LayoutSVGInlineText {#text} at (0,70) size 17x105 + RenderSVGTSpan {tspan} at (0,0) size 17x105 + RenderSVGInlineText {#text} at (0,70) size 17x105 chunk 1 (vertical) text run 1 at (152.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" chunk 1 (vertical) text run 2 at (152.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" chunk 1 (vertical) text run 3 at (152.00,140.00) startOffset 2 endOffset 3 height 35.00: "b" - LayoutSVGTSpan {tspan} at (0,0) size 14x35 - LayoutSVGInlineText {#text} at (19,175) size 14x35 + RenderSVGTSpan {tspan} at (0,0) size 14x35 + RenderSVGInlineText {#text} at (19,175) size 14x35 chunk 1 (vertical) text run 1 at (169.50,175.00) startOffset 0 endOffset 1 height 35.00: "x" - LayoutSVGInlineText {#text} at (22,210) size 8x35 + RenderSVGInlineText {#text} at (22,210) size 8x35 chunk 1 (vertical) text run 1 at (169.50,210.00) startOffset 0 endOffset 1 height 35.00: "t" - LayoutSVGText {text} at (252,0) size 34x315 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 16x70 + RenderSVGText {text} at (252,0) size 34x315 contains 1 chunk(s) + RenderSVGInlineText {#text} at (0,0) size 16x70 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 35.00: "t" chunk 1 (vertical) text run 2 at (249.50,35.00) startOffset 1 endOffset 2 height 35.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x175 - LayoutSVGInlineText {#text} at (17,70) size 17x175 + RenderSVGTSpan {tspan} at (0,0) size 17x175 + RenderSVGInlineText {#text} at (17,70) size 17x175 chunk 1 (vertical) text run 1 at (267.00,70.00) startOffset 0 endOffset 1 height 35.00: "s" chunk 1 (vertical) text run 2 at (267.00,105.00) startOffset 1 endOffset 2 height 35.00: "u" chunk 1 (vertical) text run 3 at (267.00,140.00) startOffset 2 endOffset 3 height 35.00: "p" chunk 1 (vertical) text run 4 at (267.00,175.00) startOffset 3 endOffset 4 height 35.00: "e" chunk 1 (vertical) text run 5 at (267.00,210.00) startOffset 4 endOffset 5 height 35.00: "r" - LayoutSVGTSpan {tspan} at (0,0) size 14x35 - LayoutSVGInlineText {#text} at (1,245) size 14x35 + RenderSVGTSpan {tspan} at (0,0) size 14x35 + RenderSVGInlineText {#text} at (1,245) size 14x35 chunk 1 (vertical) text run 1 at (249.50,245.00) startOffset 0 endOffset 1 height 35.00: "x" - LayoutSVGInlineText {#text} at (4,280) size 8x35 + RenderSVGInlineText {#text} at (4,280) size 8x35 chunk 1 (vertical) text run 1 at (249.50,280.00) startOffset 0 endOffset 1 height 35.00: "t" - LayoutSVGText {text} at (10,304) size 261x46 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 261x46 + RenderSVGText {text} at (10,304) size 261x46 contains 1 chunk(s) + RenderSVGInlineText {#text} at (0,0) size 261x46 chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 261.00: "$Revision: 1.5 $" - LayoutSVGRect {rect} at (0,0) size 480x360 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00] + RenderSVGRect {rect} at (0,0) size 480x360 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png index 7f3e67a..4d0acc0 100644 --- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/text-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/text-align-06-b-expected.txt index 32cbc41..b5efb67f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/text-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/text-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 17x66 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (-10.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x33 + LayoutSVGTSpan {tspan} at (0,0) size 33x17 LayoutSVGInlineText {#text} at (7,66) size 17x33 chunk 1 (vertical) text run 1 at (-3.50,66.00) startOffset 0 endOffset 1 height 33.00: "7" LayoutSVGInlineText {#text} at (0,99) size 15x66 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (26,0) size 17x66 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (69.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x132 + LayoutSVGTSpan {tspan} at (0,0) size 132x27 LayoutSVGInlineText {#text} at (0,66) size 27x132 chunk 1 (vertical) text run 1 at (48.50,66.00) startOffset 0 endOffset 1 height 33.00: "-" chunk 1 (vertical) text run 2 at (48.50,99.00) startOffset 1 endOffset 2 height 33.00: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (16,0) size 17x66 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (169.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x99 + LayoutSVGTSpan {tspan} at (0,0) size 99x17 LayoutSVGInlineText {#text} at (0,66) size 17x99 chunk 1 (vertical) text run 1 at (153.00,66.00) startOffset 0 endOffset 1 height 33.00: "s" chunk 1 (vertical) text run 2 at (153.00,99.00) startOffset 1 endOffset 2 height 33.00: "u" chunk 1 (vertical) text run 3 at (153.00,132.00) startOffset 2 endOffset 3 height 33.00: "b" - LayoutSVGTSpan {tspan} at (0,0) size 16x33 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (17,165) size 15x33 chunk 1 (vertical) text run 1 at (169.50,165.00) startOffset 0 endOffset 1 height 33.00: "x" LayoutSVGInlineText {#text} at (20,198) size 9x33 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 17x66 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 33.00: "t" chunk 1 (vertical) text run 2 at (249.50,33.00) startOffset 1 endOffset 2 height 33.00: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x165 + LayoutSVGTSpan {tspan} at (0,0) size 166x17 LayoutSVGInlineText {#text} at (16,66) size 17x165 chunk 1 (vertical) text run 1 at (266.00,66.00) startOffset 0 endOffset 1 height 33.00: "s" chunk 1 (vertical) text run 2 at (266.00,99.00) startOffset 1 endOffset 2 height 33.00: "u" chunk 1 (vertical) text run 3 at (266.00,132.00) startOffset 2 endOffset 3 height 33.00: "p" chunk 1 (vertical) text run 4 at (266.00,165.00) startOffset 3 endOffset 4 height 33.00: "e" chunk 1 (vertical) text run 5 at (266.00,198.00) startOffset 4 endOffset 5 height 33.00: "r" - LayoutSVGTSpan {tspan} at (0,0) size 16x33 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (0,231) size 15x33 chunk 1 (vertical) text run 1 at (249.50,231.00) startOffset 0 endOffset 1 height 33.00: "x" LayoutSVGInlineText {#text} at (4,264) size 9x33
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/verticalTextOnPath-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/verticalTextOnPath-expected.txt index 11ea863a..9689c34 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/verticalTextOnPath-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/verticalTextOnPath-expected.txt
@@ -13,14 +13,14 @@ LayoutSVGContainer {use} at (14,70) size 121x45 LayoutSVGPath {path} at (14,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (9,-10) size 81x53 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x53 + LayoutSVGTextPath {textPath} at (0,0) size 53x81 LayoutSVGInlineText {#text} at (0,12) size 34x34 chunk 1 (vertical) text run 1 at (18.25,26.76) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (24.02,21.22) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (29.31,16.66) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (33.75,13.42) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (37.16,11.42) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 22x19 + LayoutSVGTSpan {tspan} at (0,0) size 19x22 LayoutSVGInlineText {#text} at (25,0) size 22x19 chunk 1 (vertical) text run 1 at (42.30,9.40) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (49.21,8.97) startOffset 1 endOffset 2 height 17.00: "n" @@ -47,11 +47,11 @@ LayoutSVGContainer {use} at (164,70) size 121x45 LayoutSVGPath {path} at (164,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (13,5) size 103x34 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 102x34 + LayoutSVGTextPath {textPath} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-13,-5) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 102x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x102 LayoutSVGInlineText {#text} at (0,0) size 102x34 chunk 1 (middle anchor, vertical) text run 1 at (21.14,23.94) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (34.18,13.14) startOffset 1 endOffset 2 height 17.00: "a" @@ -74,11 +74,11 @@ LayoutSVGContainer {use} at (314,70) size 121x45 LayoutSVGPath {path} at (314,69) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (11,3) size 61x31 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 61x31 + LayoutSVGTextPath {textPath} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-11,-3) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 61x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x61 LayoutSVGInlineText {#text} at (0,0) size 61x31 chunk 1 (end anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "P" chunk 1 (end anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: "a" @@ -98,18 +98,18 @@ LayoutSVGContainer {use} at (14,170) size 121x45 LayoutSVGPath {path} at (14,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (67,6) size 69x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 68x39 + LayoutSVGTextPath {textPath} at (0,0) size 39x68 LayoutSVGInlineText {#text} at (0,13) size 37x25 chunk 1 (vertical) text run 1 at (75.96,29.62) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (82.71,33.85) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (89.36,36.03) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (94.80,35.93) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (98.61,34.66) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 22x24 + LayoutSVGTSpan {tspan} at (0,0) size 23x23 LayoutSVGInlineText {#text} at (21,3) size 22x23 chunk 1 (vertical) text run 1 at (103.11,31.73) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (vertical) text run 2 at (108.48,26.78) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 29x25 + LayoutSVGTSpan {tspan} at (0,0) size 25x29 LayoutSVGInlineText {#text} at (39,0) size 29x25 chunk 1 (vertical) text run 1 at (112.82,23.41) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (vertical) text run 2 at (117.46,20.49) startOffset 1 endOffset 2 height 17.00: "a" @@ -129,15 +129,15 @@ LayoutSVGContainer {use} at (164,170) size 121x45 LayoutSVGPath {path} at (164,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (15,-6) size 119x48 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 118x47 + LayoutSVGTextPath {textPath} at (0,0) size 47x118 LayoutSVGInlineText {#text} at (0,11) size 30x24 chunk 1 (middle anchor, vertical) text run 1 at (23.38,21.81) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (middle anchor, vertical) text run 2 at (36.83,11.59) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 34x28 + LayoutSVGTSpan {tspan} at (0,0) size 29x34 LayoutSVGInlineText {#text} at (32,0) size 34x28 chunk 1 (middle anchor, vertical) text run 1 at (53.13,10.12) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (66.22,21.14) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 63x32 + LayoutSVGTSpan {tspan} at (0,0) size 32x64 LayoutSVGInlineText {#text} at (55,15) size 63x31 chunk 1 (middle anchor, vertical) text run 1 at (79.28,31.92) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (95.28,35.82) startOffset 1 endOffset 2 height 17.00: "a" @@ -157,18 +157,18 @@ LayoutSVGContainer {use} at (314,170) size 121x45 LayoutSVGPath {path} at (314,169) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (48,2) size 81x43 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 81x43 + LayoutSVGTextPath {textPath} at (0,0) size 43x81 LayoutSVGInlineText {#text} at (0,0) size 34x35 chunk 1 (end anchor, vertical) text run 1 at (56.60,12.10) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (end anchor, vertical) text run 2 at (62.70,17.69) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (end anchor, vertical) text run 3 at (67.75,22.60) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (end anchor, vertical) text run 4 at (71.76,26.22) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (end anchor, vertical) text run 5 at (74.88,28.79) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x22 + LayoutSVGTSpan {tspan} at (0,0) size 21x19 LayoutSVGInlineText {#text} at (29,11) size 18x21 chunk 1 (end anchor, vertical) text run 1 at (79.38,31.98) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (end anchor, vertical) text run 2 at (85.64,35.09) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 41x37 + LayoutSVGTSpan {tspan} at (0,0) size 37x41 LayoutSVGInlineText {#text} at (40,6) size 41x36 chunk 1 (end anchor, vertical) text run 1 at (90.97,36.19) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (end anchor, vertical) text run 2 at (96.34,35.54) startOffset 1 endOffset 2 height 17.00: "a" @@ -191,14 +191,14 @@ LayoutSVGContainer {use} at (14,270) size 121x45 LayoutSVGPath {path} at (14,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (37,1) size 87x39 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 86x38 + LayoutSVGTextPath {textPath} at (0,0) size 38x86 LayoutSVGInlineText {#text} at (0,0) size 75x38 chunk 1 (vertical) text run 1 at (51.11,9.39) startOffset 0 endOffset 1 height 17.00: "T" chunk 1 (vertical) text run 2 at (64.70,19.66) startOffset 1 endOffset 2 height 17.00: "e" chunk 1 (vertical) text run 3 at (77.48,30.72) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (vertical) text run 4 at (93.24,36.15) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (vertical) text run 5 at (107.64,27.51) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 19x14 + LayoutSVGTSpan {tspan} at (0,0) size 14x19 LayoutSVGInlineText {#text} at (67,2) size 19x14 chunk 1 (vertical) text run 1 at (121.81,18.34) startOffset 0 endOffset 1 height 17.00: "o" LayoutSVGTSpan {tspan} at (0,0) size 1x1 @@ -217,16 +217,16 @@ LayoutSVGContainer {use} at (164,270) size 121x45 LayoutSVGPath {path} at (164,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (10,-6) size 70x41 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 69x41 + LayoutSVGTextPath {textPath} at (0,0) size 41x69 LayoutSVGInlineText {#text} at (0,17) size 23x23 chunk 1 (middle anchor, vertical) text run 1 at (19.33,25.70) startOffset 2 endOffset 3 height 17.00: "x" chunk 1 (middle anchor, vertical) text run 2 at (23.30,21.89) startOffset 3 endOffset 4 height 17.00: "t" chunk 1 (middle anchor, vertical) text run 3 at (26.19,19.27) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 23x23 + LayoutSVGTSpan {tspan} at (0,0) size 24x23 LayoutSVGInlineText {#text} at (5,0) size 23x23 chunk 1 (middle anchor, vertical) text run 1 at (30.48,15.74) startOffset 0 endOffset 1 height 17.00: "o" chunk 1 (middle anchor, vertical) text run 2 at (36.31,11.88) startOffset 1 endOffset 2 height 17.00: "n" - LayoutSVGTSpan {tspan} at (0,0) size 43x35 + LayoutSVGTSpan {tspan} at (0,0) size 35x44 LayoutSVGInlineText {#text} at (26,6) size 43x35 chunk 1 (middle anchor, vertical) text run 1 at (41.36,9.67) startOffset 0 endOffset 1 height 17.00: " " chunk 1 (middle anchor, vertical) text run 2 at (46.74,8.79) startOffset 1 endOffset 2 height 17.00: "a" @@ -246,11 +246,11 @@ LayoutSVGContainer {use} at (314,270) size 121x45 LayoutSVGPath {path} at (314,269) size 122x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100"] LayoutSVGText {text} at (7,6) size 32x32 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 32x31 + LayoutSVGTextPath {textPath} at (0,0) size 31x32 LayoutSVGInlineText {#text} at (-7,-6) size 0x0 LayoutSVGTSpan {tspan} at (0,0) size 1x1 LayoutSVGInlineText {#text} at (-7,-6) size 0x0 - LayoutSVGTSpan {tspan} at (0,0) size 32x31 + LayoutSVGTSpan {tspan} at (0,0) size 31x32 LayoutSVGInlineText {#text} at (0,0) size 32x31 chunk 1 (end anchor, vertical) text run 1 at (16.80,28.20) startOffset 3 endOffset 4 height 17.00: "P" chunk 1 (end anchor, vertical) text run 2 at (22.58,22.56) startOffset 4 endOffset 5 height 17.00: "a" @@ -270,8 +270,8 @@ LayoutSVGContainer {use} at (39,370) size 92x50 LayoutSVGPath {path} at (39,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (12,4) size 114x46 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 114x46 - LayoutSVGTSpan {tspan} at (0,0) size 31x41 + LayoutSVGTextPath {textPath} at (0,0) size 46x114 + LayoutSVGTSpan {tspan} at (0,0) size 41x31 LayoutSVGInlineText {#text} at (0,5) size 31x41 chunk 1 (vertical) text run 1 at (30.12,46.89) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (31.17,40.56) startOffset 1 endOffset 2 height 17.00: "u" @@ -284,7 +284,7 @@ chunk 1 (vertical) text run 3 at (56.35,15.52) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (63.11,13.69) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (68.55,12.84) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 21x19 + LayoutSVGTSpan {tspan} at (0,0) size 20x21 LayoutSVGInlineText {#text} at (57,8) size 20x19 chunk 1 (vertical) text run 1 at (73.55,12.52) startOffset 0 endOffset 1 height 17.00: "s" chunk 1 (vertical) text run 2 at (80.06,12.71) startOffset 1 endOffset 2 height 17.00: "u" @@ -311,8 +311,8 @@ LayoutSVGContainer {use} at (329,370) size 92x50 LayoutSVGPath {path} at (329,369) size 92x52 [transform={m=((0.30,0.00)(0.00,0.50)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 100 C 100 0 400 0 400 100"] LayoutSVGText {text} at (18,3) size 107x48 contains 1 chunk(s) - LayoutSVGTextPath {textPath} at (0,0) size 106x47 - LayoutSVGTSpan {tspan} at (0,0) size 38x46 + LayoutSVGTextPath {textPath} at (0,0) size 47x106 + LayoutSVGTSpan {tspan} at (0,0) size 45x39 LayoutSVGInlineText {#text} at (0,1) size 38x45 chunk 1 (vertical) text run 1 at (30.16,46.38) startOffset 0 endOffset 1 height 17.00: "p" chunk 1 (vertical) text run 2 at (31.45,39.57) startOffset 1 endOffset 2 height 17.00: "o" @@ -328,7 +328,7 @@ chunk 1 (vertical) text run 3 at (68.06,12.90) startOffset 2 endOffset 3 height 17.00: "n" chunk 1 (vertical) text run 4 at (75.05,12.50) startOffset 3 endOffset 4 height 17.00: "d" chunk 1 (vertical) text run 5 at (80.56,12.76) startOffset 4 endOffset 5 height 17.00: " " - LayoutSVGTSpan {tspan} at (0,0) size 44x38 + LayoutSVGTSpan {tspan} at (0,0) size 38x45 LayoutSVGInlineText {#text} at (62,3) size 44x38 chunk 1 (vertical) text run 1 at (86.01,13.52) startOffset 0 endOffset 1 height 17.00: "n" chunk 1 (vertical) text run 2 at (92.80,15.24) startOffset 1 endOffset 2 height 17.00: "e" @@ -363,7 +363,7 @@ chunk 1 (vertical) text run 10 at (3.00,54.67) startOffset 9 endOffset 10 height 22.67: "t" chunk 1 (vertical) text run 11 at (3.00,60.00) startOffset 10 endOffset 11 height 22.67: "h" chunk 1 (vertical) text run 12 at (3.00,69.33) startOffset 11 endOffset 12 height 22.67: " " - LayoutSVGTextPath {textPath} at (0,0) size 58x41 + LayoutSVGTextPath {textPath} at (0,0) size 42x58 LayoutSVGInlineText {#text} at (25,22) size 58x41 chunk 1 (vertical) text run 1 at (34.24,32.91) startOffset 0 endOffset 1 height 22.67: "o" chunk 1 (vertical) text run 2 at (39.86,25.49) startOffset 1 endOffset 2 height 22.67: "n"
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-06-b-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-06-b-expected.txt index 0c34029..fc4c4f3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-06-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-06-b-expected.txt
@@ -12,7 +12,7 @@ LayoutSVGInlineText {#text} at (0,0) size 17x68 chunk 1 (vertical) text run 1 at (-10.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (-10.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x17 LayoutSVGInlineText {#text} at (7,67) size 17x34 chunk 1 (vertical) text run 1 at (-3.50,67.20) startOffset 0 endOffset 1 height 33.60: "7" LayoutSVGInlineText {#text} at (0,100) size 15x68 @@ -22,7 +22,7 @@ LayoutSVGInlineText {#text} at (26,0) size 17x68 chunk 1 (vertical) text run 1 at (69.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (69.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 27x135 + LayoutSVGTSpan {tspan} at (0,0) size 135x27 LayoutSVGInlineText {#text} at (0,67) size 27x135 chunk 1 (vertical) text run 1 at (48.50,67.20) startOffset 0 endOffset 1 height 33.60: "-" chunk 1 (vertical) text run 2 at (48.50,100.80) startOffset 1 endOffset 2 height 33.60: "7" @@ -35,12 +35,12 @@ LayoutSVGInlineText {#text} at (16,0) size 17x68 chunk 1 (vertical) text run 1 at (169.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (169.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 17x101 + LayoutSVGTSpan {tspan} at (0,0) size 101x17 LayoutSVGInlineText {#text} at (0,67) size 17x101 chunk 1 (vertical) text run 1 at (153.00,67.20) startOffset 0 endOffset 1 height 33.60: "s" chunk 1 (vertical) text run 2 at (153.00,100.80) startOffset 1 endOffset 2 height 33.60: "u" chunk 1 (vertical) text run 3 at (153.00,134.40) startOffset 2 endOffset 3 height 33.60: "b" - LayoutSVGTSpan {tspan} at (0,0) size 16x34 + LayoutSVGTSpan {tspan} at (0,0) size 34x15 LayoutSVGInlineText {#text} at (17,168) size 15x34 chunk 1 (vertical) text run 1 at (169.50,168.00) startOffset 0 endOffset 1 height 33.60: "x" LayoutSVGInlineText {#text} at (20,201) size 9x34 @@ -49,14 +49,14 @@ LayoutSVGInlineText {#text} at (0,0) size 17x68 chunk 1 (vertical) text run 1 at (249.50,0.00) startOffset 0 endOffset 1 height 33.60: "t" chunk 1 (vertical) text run 2 at (249.50,33.60) startOffset 1 endOffset 2 height 33.60: "e" - LayoutSVGTSpan {tspan} at (0,0) size 18x169 + LayoutSVGTSpan {tspan} at (0,0) size 169x17 LayoutSVGInlineText {#text} at (16,67) size 17x168 chunk 1 (vertical) text run 1 at (266.00,67.20) startOffset 0 endOffset 1 height 33.60: "s" chunk 1 (vertical) text run 2 at (266.00,100.80) startOffset 1 endOffset 2 height 33.60: "u" chunk 1 (vertical) text run 3 at (266.00,134.40) startOffset 2 endOffset 3 height 33.60: "p" chunk 1 (vertical) text run 4 at (266.00,168.00) startOffset 3 endOffset 4 height 33.60: "e" chunk 1 (vertical) text run 5 at (266.00,201.60) startOffset 4 endOffset 5 height 33.60: "r" - LayoutSVGTSpan {tspan} at (0,0) size 16x34 + LayoutSVGTSpan {tspan} at (0,0) size 35x16 LayoutSVGInlineText {#text} at (0,235) size 15x34 chunk 1 (vertical) text run 1 at (249.50,235.20) startOffset 0 endOffset 1 height 33.60: "x" LayoutSVGInlineText {#text} at (4,268) size 9x34
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/batik/text/verticalText-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/batik/text/verticalText-expected.txt new file mode 100644 index 0000000..7188004 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/batik/text/verticalText-expected.txt
@@ -0,0 +1,277 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 450x500 + LayoutSVGRoot {svg} at (0,0) size 448x498 + LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 + LayoutSVGPath {path} at (14,0) size 317x46 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 0 1000 100 C 1100 200 1200 300 1300 200 C 1400 100 1500 0 1600 100 C 1700 200 1800 300 1900 200 C 2000 100 2100 0 2200 100"] + LayoutSVGContainer {g} at (20,26) size 410x469 + LayoutSVGText {text} at (162,26) size 126x17 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 125x17 + chunk 1 (middle anchor) text run 1 at (162.76,40.00) startOffset 0 endOffset 18 width 124.48: "Vertical Text Test" + LayoutSVGPath {line} at (20,74) size 410x2 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [x1=20.00] [y1=75.00] [x2=430.00] [y2=75.00] + LayoutSVGContainer {g} at (48,73) size 354x377 [opacity=0.50] + LayoutSVGEllipse {circle} at (48,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=50.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (98,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=100.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (148,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=150.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (198,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=200.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (248,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=250.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (298,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=300.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (348,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=350.00] [cy=75.00] [r=2.00] + LayoutSVGEllipse {circle} at (398,73) size 4x4 [fill={[type=SOLID] [color=#FF0000]}] [cx=400.00] [cy=75.00] [r=2.00] + LayoutSVGPath {line} at (49,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=50.00] [y1=75.00] [x2=50.00] [y2=450.00] + LayoutSVGPath {line} at (99,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=100.00] [y1=75.00] [x2=100.00] [y2=450.00] + LayoutSVGPath {line} at (149,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=150.00] [y1=75.00] [x2=150.00] [y2=450.00] + LayoutSVGPath {line} at (199,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=200.00] [y1=75.00] [x2=200.00] [y2=450.00] + LayoutSVGPath {line} at (249,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=250.00] [y1=75.00] [x2=250.00] [y2=450.00] + LayoutSVGPath {line} at (299,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=300.00] [y1=75.00] [x2=300.00] [y2=450.00] + LayoutSVGPath {line} at (349,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=350.00] [y1=75.00] [x2=350.00] [y2=450.00] + LayoutSVGPath {line} at (399,75) size 2x375 [stroke={[type=SOLID] [color=#FF0000]}] [fill={[type=SOLID] [color=#000000]}] [x1=400.00] [y1=75.00] [x2=400.00] [y2=450.00] + LayoutSVGText {text} at (41,75) size 18x158 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x158 + chunk 1 (vertical) text run 1 at (45.50,75.00) startOffset 0 endOffset 1 height 17.00: "W" + chunk 1 (vertical) text run 2 at (45.50,89.00) startOffset 1 endOffset 2 height 17.00: "r" + chunk 1 (vertical) text run 3 at (45.50,94.00) startOffset 2 endOffset 3 height 17.00: "i" + chunk 1 (vertical) text run 4 at (45.50,97.00) startOffset 3 endOffset 4 height 17.00: "t" + chunk 1 (vertical) text run 5 at (45.50,101.00) startOffset 4 endOffset 5 height 17.00: "i" + chunk 1 (vertical) text run 6 at (45.50,104.00) startOffset 5 endOffset 6 height 17.00: "n" + chunk 1 (vertical) text run 7 at (45.50,111.00) startOffset 6 endOffset 7 height 17.00: "g" + chunk 1 (vertical) text run 8 at (45.50,118.00) startOffset 7 endOffset 8 height 17.00: " " + chunk 1 (vertical) text run 9 at (45.50,122.00) startOffset 8 endOffset 9 height 17.00: "t" + chunk 1 (vertical) text run 10 at (45.50,126.00) startOffset 9 endOffset 10 height 17.00: "o" + chunk 1 (vertical) text run 11 at (45.50,133.00) startOffset 10 endOffset 11 height 17.00: "p" + chunk 1 (vertical) text run 12 at (45.50,140.00) startOffset 11 endOffset 12 height 17.00: " " + chunk 1 (vertical) text run 13 at (45.50,144.00) startOffset 12 endOffset 13 height 17.00: "t" + chunk 1 (vertical) text run 14 at (45.50,148.00) startOffset 13 endOffset 14 height 17.00: "o" + chunk 1 (vertical) text run 15 at (45.50,155.00) startOffset 14 endOffset 15 height 17.00: " " + chunk 1 (vertical) text run 16 at (45.50,159.00) startOffset 15 endOffset 16 height 17.00: "b" + chunk 1 (vertical) text run 17 at (45.50,166.00) startOffset 16 endOffset 17 height 17.00: "o" + chunk 1 (vertical) text run 18 at (45.50,173.00) startOffset 17 endOffset 18 height 17.00: "t" + chunk 1 (vertical) text run 19 at (45.50,177.00) startOffset 18 endOffset 19 height 17.00: "t" + chunk 1 (vertical) text run 20 at (45.50,181.00) startOffset 19 endOffset 20 height 17.00: "o" + chunk 1 (vertical) text run 21 at (45.50,188.00) startOffset 20 endOffset 21 height 17.00: "m" + chunk 1 (vertical) text run 22 at (45.50,199.00) startOffset 21 endOffset 22 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 23 at (45.50,216.00) startOffset 22 endOffset 23 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (91,75) size 18x165 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x165 + chunk 1 (vertical) text run 1 at (95.50,75.00) startOffset 0 endOffset 1 height 17.00: "G" + chunk 1 (vertical) text run 2 at (95.50,85.00) startOffset 1 endOffset 2 height 17.00: "l" + chunk 1 (vertical) text run 3 at (95.50,88.00) startOffset 2 endOffset 3 height 17.00: "y" + chunk 1 (vertical) text run 4 at (95.50,95.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (95.50,102.00) startOffset 4 endOffset 5 height 17.00: "h" + chunk 1 (vertical) text run 6 at (95.50,109.00) startOffset 5 endOffset 6 height 17.00: " " + chunk 1 (vertical) text run 7 at (95.50,113.00) startOffset 6 endOffset 7 height 17.00: "O" + chunk 1 (vertical) text run 8 at (95.50,124.00) startOffset 7 endOffset 8 height 17.00: "r" + chunk 1 (vertical) text run 9 at (95.50,129.00) startOffset 8 endOffset 9 height 17.00: "i" + chunk 1 (vertical) text run 10 at (95.50,132.00) startOffset 9 endOffset 10 height 17.00: "e" + chunk 1 (vertical) text run 11 at (95.50,139.00) startOffset 10 endOffset 11 height 17.00: "n" + chunk 1 (vertical) text run 12 at (95.50,146.00) startOffset 11 endOffset 12 height 17.00: "t" + chunk 1 (vertical) text run 13 at (95.50,150.00) startOffset 12 endOffset 13 height 17.00: "a" + chunk 1 (vertical) text run 14 at (95.50,157.00) startOffset 13 endOffset 14 height 17.00: "t" + chunk 1 (vertical) text run 15 at (95.50,161.00) startOffset 14 endOffset 15 height 17.00: "i" + chunk 1 (vertical) text run 16 at (95.50,164.00) startOffset 15 endOffset 16 height 17.00: "o" + chunk 1 (vertical) text run 17 at (95.50,171.00) startOffset 16 endOffset 17 height 17.00: "n" + chunk 1 (vertical) text run 18 at (95.50,178.00) startOffset 17 endOffset 18 height 17.00: ":" + chunk 1 (vertical) text run 19 at (95.50,181.00) startOffset 18 endOffset 19 height 17.00: "a" + chunk 1 (vertical) text run 20 at (95.50,188.00) startOffset 19 endOffset 20 height 17.00: "u" + chunk 1 (vertical) text run 21 at (95.50,195.00) startOffset 20 endOffset 21 height 17.00: "t" + chunk 1 (vertical) text run 22 at (95.50,199.00) startOffset 21 endOffset 22 height 17.00: "o" + chunk 1 (vertical) text run 23 at (95.50,206.00) startOffset 22 endOffset 23 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 24 at (95.50,223.00) startOffset 23 endOffset 24 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (142,75) size 16x357 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 15x357 + chunk 1 (vertical) text run 1 at (145.50,75.00) startOffset 0 endOffset 1 height 17.00: "G" + chunk 1 (vertical) text run 2 at (145.50,92.00) startOffset 1 endOffset 2 height 17.00: "l" + chunk 1 (vertical) text run 3 at (145.50,109.00) startOffset 2 endOffset 3 height 17.00: "y" + chunk 1 (vertical) text run 4 at (145.50,126.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (145.50,143.00) startOffset 4 endOffset 5 height 17.00: "h" + chunk 1 (vertical) text run 6 at (145.50,160.00) startOffset 5 endOffset 6 height 17.00: " " + chunk 1 (vertical) text run 7 at (145.50,177.00) startOffset 6 endOffset 7 height 17.00: "O" + chunk 1 (vertical) text run 8 at (145.50,194.00) startOffset 7 endOffset 8 height 17.00: "r" + chunk 1 (vertical) text run 9 at (145.50,211.00) startOffset 8 endOffset 9 height 17.00: "i" + chunk 1 (vertical) text run 10 at (145.50,228.00) startOffset 9 endOffset 10 height 17.00: "e" + chunk 1 (vertical) text run 11 at (145.50,245.00) startOffset 10 endOffset 11 height 17.00: "n" + chunk 1 (vertical) text run 12 at (145.50,262.00) startOffset 11 endOffset 12 height 17.00: "t" + chunk 1 (vertical) text run 13 at (145.50,279.00) startOffset 12 endOffset 13 height 17.00: "a" + chunk 1 (vertical) text run 14 at (145.50,296.00) startOffset 13 endOffset 14 height 17.00: "t" + chunk 1 (vertical) text run 15 at (145.50,313.00) startOffset 14 endOffset 15 height 17.00: "i" + chunk 1 (vertical) text run 16 at (145.50,330.00) startOffset 15 endOffset 16 height 17.00: "o" + chunk 1 (vertical) text run 17 at (145.50,347.00) startOffset 16 endOffset 17 height 17.00: "n" + chunk 1 (vertical) text run 18 at (145.50,364.00) startOffset 17 endOffset 18 height 17.00: ":" + chunk 1 (vertical) text run 19 at (145.50,381.00) startOffset 18 endOffset 19 height 17.00: "0" + chunk 1 (vertical) text run 20 at (145.50,398.00) startOffset 19 endOffset 20 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 21 at (145.50,415.00) startOffset 20 endOffset 21 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (191,75) size 18x150 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x150 + chunk 1 (vertical) text run 1 at (195.50,75.00) startOffset 0 endOffset 1 height 17.00: "G" + chunk 1 (vertical) text run 2 at (195.50,85.00) startOffset 1 endOffset 2 height 17.00: "l" + chunk 1 (vertical) text run 3 at (195.50,88.00) startOffset 2 endOffset 3 height 17.00: "y" + chunk 1 (vertical) text run 4 at (195.50,95.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (195.50,102.00) startOffset 4 endOffset 5 height 17.00: "h" + chunk 1 (vertical) text run 6 at (195.50,109.00) startOffset 5 endOffset 6 height 17.00: " " + chunk 1 (vertical) text run 7 at (195.50,113.00) startOffset 6 endOffset 7 height 17.00: "O" + chunk 1 (vertical) text run 8 at (195.50,124.00) startOffset 7 endOffset 8 height 17.00: "r" + chunk 1 (vertical) text run 9 at (195.50,129.00) startOffset 8 endOffset 9 height 17.00: "i" + chunk 1 (vertical) text run 10 at (195.50,132.00) startOffset 9 endOffset 10 height 17.00: "e" + chunk 1 (vertical) text run 11 at (195.50,139.00) startOffset 10 endOffset 11 height 17.00: "n" + chunk 1 (vertical) text run 12 at (195.50,146.00) startOffset 11 endOffset 12 height 17.00: "t" + chunk 1 (vertical) text run 13 at (195.50,150.00) startOffset 12 endOffset 13 height 17.00: "a" + chunk 1 (vertical) text run 14 at (195.50,157.00) startOffset 13 endOffset 14 height 17.00: "t" + chunk 1 (vertical) text run 15 at (195.50,161.00) startOffset 14 endOffset 15 height 17.00: "i" + chunk 1 (vertical) text run 16 at (195.50,164.00) startOffset 15 endOffset 16 height 17.00: "o" + chunk 1 (vertical) text run 17 at (195.50,171.00) startOffset 16 endOffset 17 height 17.00: "n" + chunk 1 (vertical) text run 18 at (195.50,178.00) startOffset 17 endOffset 18 height 17.00: ":" + chunk 1 (vertical) text run 19 at (195.50,181.00) startOffset 18 endOffset 19 height 17.00: "9" + chunk 1 (vertical) text run 20 at (195.50,188.00) startOffset 19 endOffset 20 height 17.00: "0" + chunk 1 (vertical) text run 21 at (195.50,195.00) startOffset 20 endOffset 21 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 22 at (195.50,210.00) startOffset 21 endOffset 22 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (242,71) size 16x391 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 15x391 + chunk 1 (vertical) text run 1 at (245.50,75.00) startOffset 0 endOffset 1 height 17.00: "G" + chunk 1 (vertical) text run 2 at (245.50,92.00) startOffset 1 endOffset 2 height 17.00: "l" + chunk 1 (vertical) text run 3 at (245.50,109.00) startOffset 2 endOffset 3 height 17.00: "y" + chunk 1 (vertical) text run 4 at (245.50,126.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (245.50,143.00) startOffset 4 endOffset 5 height 17.00: "h" + chunk 1 (vertical) text run 6 at (245.50,160.00) startOffset 5 endOffset 6 height 17.00: " " + chunk 1 (vertical) text run 7 at (245.50,177.00) startOffset 6 endOffset 7 height 17.00: "O" + chunk 1 (vertical) text run 8 at (245.50,194.00) startOffset 7 endOffset 8 height 17.00: "r" + chunk 1 (vertical) text run 9 at (245.50,211.00) startOffset 8 endOffset 9 height 17.00: "i" + chunk 1 (vertical) text run 10 at (245.50,228.00) startOffset 9 endOffset 10 height 17.00: "e" + chunk 1 (vertical) text run 11 at (245.50,245.00) startOffset 10 endOffset 11 height 17.00: "n" + chunk 1 (vertical) text run 12 at (245.50,262.00) startOffset 11 endOffset 12 height 17.00: "t" + chunk 1 (vertical) text run 13 at (245.50,279.00) startOffset 12 endOffset 13 height 17.00: "a" + chunk 1 (vertical) text run 14 at (245.50,296.00) startOffset 13 endOffset 14 height 17.00: "t" + chunk 1 (vertical) text run 15 at (245.50,313.00) startOffset 14 endOffset 15 height 17.00: "i" + chunk 1 (vertical) text run 16 at (245.50,330.00) startOffset 15 endOffset 16 height 17.00: "o" + chunk 1 (vertical) text run 17 at (245.50,347.00) startOffset 16 endOffset 17 height 17.00: "n" + chunk 1 (vertical) text run 18 at (245.50,364.00) startOffset 17 endOffset 18 height 17.00: ":" + chunk 1 (vertical) text run 19 at (245.50,381.00) startOffset 18 endOffset 19 height 17.00: "1" + chunk 1 (vertical) text run 20 at (245.50,398.00) startOffset 19 endOffset 20 height 17.00: "8" + chunk 1 (vertical) text run 21 at (245.50,415.00) startOffset 20 endOffset 21 height 17.00: "0" + chunk 1 (vertical) text run 22 at (245.50,432.00) startOffset 21 endOffset 22 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 23 at (245.50,449.00) startOffset 22 endOffset 23 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (291,75) size 18x157 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x157 + chunk 1 (vertical) text run 1 at (295.50,75.00) startOffset 0 endOffset 1 height 17.00: "G" + chunk 1 (vertical) text run 2 at (295.50,85.00) startOffset 1 endOffset 2 height 17.00: "l" + chunk 1 (vertical) text run 3 at (295.50,88.00) startOffset 2 endOffset 3 height 17.00: "y" + chunk 1 (vertical) text run 4 at (295.50,95.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (295.50,102.00) startOffset 4 endOffset 5 height 17.00: "h" + chunk 1 (vertical) text run 6 at (295.50,109.00) startOffset 5 endOffset 6 height 17.00: " " + chunk 1 (vertical) text run 7 at (295.50,113.00) startOffset 6 endOffset 7 height 17.00: "O" + chunk 1 (vertical) text run 8 at (295.50,124.00) startOffset 7 endOffset 8 height 17.00: "r" + chunk 1 (vertical) text run 9 at (295.50,129.00) startOffset 8 endOffset 9 height 17.00: "i" + chunk 1 (vertical) text run 10 at (295.50,132.00) startOffset 9 endOffset 10 height 17.00: "e" + chunk 1 (vertical) text run 11 at (295.50,139.00) startOffset 10 endOffset 11 height 17.00: "n" + chunk 1 (vertical) text run 12 at (295.50,146.00) startOffset 11 endOffset 12 height 17.00: "t" + chunk 1 (vertical) text run 13 at (295.50,150.00) startOffset 12 endOffset 13 height 17.00: "a" + chunk 1 (vertical) text run 14 at (295.50,157.00) startOffset 13 endOffset 14 height 17.00: "t" + chunk 1 (vertical) text run 15 at (295.50,161.00) startOffset 14 endOffset 15 height 17.00: "i" + chunk 1 (vertical) text run 16 at (295.50,164.00) startOffset 15 endOffset 16 height 17.00: "o" + chunk 1 (vertical) text run 17 at (295.50,171.00) startOffset 16 endOffset 17 height 17.00: "n" + chunk 1 (vertical) text run 18 at (295.50,178.00) startOffset 17 endOffset 18 height 17.00: ":" + chunk 1 (vertical) text run 19 at (295.50,181.00) startOffset 18 endOffset 19 height 17.00: "2" + chunk 1 (vertical) text run 20 at (295.50,188.00) startOffset 19 endOffset 20 height 17.00: "7" + chunk 1 (vertical) text run 21 at (295.50,195.00) startOffset 20 endOffset 21 height 17.00: "0" + chunk 1 (vertical) text run 22 at (295.50,202.00) startOffset 21 endOffset 22 height 17.00: "\x{753B}" + chunk 1 (vertical) text run 23 at (295.50,217.00) startOffset 22 endOffset 23 height 17.00: "\x{50CF}" + LayoutSVGText {text} at (341,75) size 18x163 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x66 + chunk 1 (vertical) text run 1 at (345.50,75.00) startOffset 0 endOffset 1 height 17.00: "E" + chunk 1 (vertical) text run 2 at (345.50,84.00) startOffset 1 endOffset 2 height 17.00: "m" + chunk 1 (vertical) text run 3 at (345.50,95.00) startOffset 2 endOffset 3 height 17.00: "b" + chunk 1 (vertical) text run 4 at (345.50,102.00) startOffset 3 endOffset 4 height 17.00: "e" + chunk 1 (vertical) text run 5 at (345.50,109.00) startOffset 4 endOffset 5 height 17.00: "d" + chunk 1 (vertical) text run 6 at (345.50,116.00) startOffset 5 endOffset 6 height 17.00: "d" + chunk 1 (vertical) text run 7 at (345.50,123.00) startOffset 6 endOffset 7 height 17.00: "e" + chunk 1 (vertical) text run 8 at (345.50,130.00) startOffset 7 endOffset 8 height 17.00: "d" + chunk 1 (vertical) text run 9 at (345.50,137.00) startOffset 8 endOffset 9 height 17.00: " " + LayoutSVGTSpan {tspan} at (0,0) size 47x17 + LayoutSVGInlineText {#text} at (0,66) size 17x47 + chunk 1 (vertical) text run 1 at (345.50,141.00) startOffset 0 endOffset 1 height 17.00: "<" + chunk 1 (vertical) text run 2 at (345.50,149.00) startOffset 1 endOffset 2 height 17.00: "t" + chunk 1 (vertical) text run 3 at (345.50,153.00) startOffset 2 endOffset 3 height 17.00: "s" + chunk 1 (vertical) text run 4 at (345.50,159.00) startOffset 3 endOffset 4 height 17.00: "p" + chunk 1 (vertical) text run 5 at (345.50,166.00) startOffset 4 endOffset 5 height 17.00: "a" + chunk 1 (vertical) text run 6 at (345.50,173.00) startOffset 5 endOffset 6 height 17.00: "n" + chunk 1 (vertical) text run 7 at (345.50,180.00) startOffset 6 endOffset 7 height 17.00: ">" + LayoutSVGInlineText {#text} at (0,113) size 17x50 + chunk 1 (vertical) text run 1 at (345.50,188.00) startOffset 0 endOffset 1 height 17.00: " " + chunk 1 (vertical) text run 2 at (345.50,192.00) startOffset 1 endOffset 2 height 17.00: "e" + chunk 1 (vertical) text run 3 at (345.50,199.00) startOffset 2 endOffset 3 height 17.00: "l" + chunk 1 (vertical) text run 4 at (345.50,202.00) startOffset 3 endOffset 4 height 17.00: "e" + chunk 1 (vertical) text run 5 at (345.50,209.00) startOffset 4 endOffset 5 height 17.00: "m" + chunk 1 (vertical) text run 6 at (345.50,220.00) startOffset 5 endOffset 6 height 17.00: "e" + chunk 1 (vertical) text run 7 at (345.50,227.00) startOffset 6 endOffset 7 height 17.00: "n" + chunk 1 (vertical) text run 8 at (345.50,234.00) startOffset 7 endOffset 8 height 17.00: "t" + LayoutSVGText {text} at (391,75) size 18x286 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 17x66 + chunk 1 (vertical) text run 1 at (395.50,75.00) startOffset 0 endOffset 1 height 17.00: "E" + chunk 1 (vertical) text run 2 at (395.50,84.00) startOffset 1 endOffset 2 height 17.00: "m" + chunk 1 (vertical) text run 3 at (395.50,95.00) startOffset 2 endOffset 3 height 17.00: "b" + chunk 1 (vertical) text run 4 at (395.50,102.00) startOffset 3 endOffset 4 height 17.00: "e" + chunk 1 (vertical) text run 5 at (395.50,109.00) startOffset 4 endOffset 5 height 17.00: "d" + chunk 1 (vertical) text run 6 at (395.50,116.00) startOffset 5 endOffset 6 height 17.00: "d" + chunk 1 (vertical) text run 7 at (395.50,123.00) startOffset 6 endOffset 7 height 17.00: "e" + chunk 1 (vertical) text run 8 at (395.50,130.00) startOffset 7 endOffset 8 height 17.00: "d" + chunk 1 (vertical) text run 9 at (395.50,137.00) startOffset 8 endOffset 9 height 17.00: " " + LayoutSVGTSpan {tspan} at (0,0) size 170x7 + LayoutSVGInlineText {#text} at (5,66) size 7x170 + chunk 1 (vertical) text run 1 at (395.50,141.00) startOffset 0 endOffset 1 height 17.00: "o" + chunk 1 (vertical) text run 2 at (395.50,158.00) startOffset 1 endOffset 2 height 17.00: "r" + chunk 1 (vertical) text run 3 at (395.50,175.00) startOffset 2 endOffset 3 height 17.00: "i" + chunk 1 (vertical) text run 4 at (395.50,192.00) startOffset 3 endOffset 4 height 17.00: "e" + chunk 1 (vertical) text run 5 at (395.50,209.00) startOffset 4 endOffset 5 height 17.00: "n" + chunk 1 (vertical) text run 6 at (395.50,226.00) startOffset 5 endOffset 6 height 17.00: "t" + chunk 1 (vertical) text run 7 at (395.50,243.00) startOffset 6 endOffset 7 height 17.00: "a" + chunk 1 (vertical) text run 8 at (395.50,260.00) startOffset 7 endOffset 8 height 17.00: "t" + chunk 1 (vertical) text run 9 at (395.50,277.00) startOffset 8 endOffset 9 height 17.00: "e" + chunk 1 (vertical) text run 10 at (395.50,294.00) startOffset 9 endOffset 10 height 17.00: "d" + LayoutSVGInlineText {#text} at (0,236) size 17x50 + chunk 1 (vertical) text run 1 at (395.50,311.00) startOffset 0 endOffset 1 height 17.00: " " + chunk 1 (vertical) text run 2 at (395.50,315.00) startOffset 1 endOffset 2 height 17.00: "e" + chunk 1 (vertical) text run 3 at (395.50,322.00) startOffset 2 endOffset 3 height 17.00: "l" + chunk 1 (vertical) text run 4 at (395.50,325.00) startOffset 3 endOffset 4 height 17.00: "e" + chunk 1 (vertical) text run 5 at (395.50,332.00) startOffset 4 endOffset 5 height 17.00: "m" + chunk 1 (vertical) text run 6 at (395.50,343.00) startOffset 5 endOffset 6 height 17.00: "e" + chunk 1 (vertical) text run 7 at (395.50,350.00) startOffset 6 endOffset 7 height 17.00: "n" + chunk 1 (vertical) text run 8 at (395.50,357.00) startOffset 7 endOffset 8 height 17.00: "t" + LayoutSVGContainer {g} at (52,450) size 319x45 [transform={m=((1.00,0.00)(0.00,1.00)) t=(40.00,450.00)}] + LayoutSVGContainer {use} at (54,450) size 317x45 + LayoutSVGPath {path} at (54,449) size 317x47 [transform={m=((0.15,0.00)(0.00,0.15)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [data="M 100 200 C 200 100 300 0 400 100 C 500 200 600 300 700 200 C 800 100 900 0 1000 100 C 1100 200 1200 300 1300 200 C 1400 100 1500 0 1600 100 C 1700 200 1800 300 1900 200 C 2000 100 2100 0 2200 100"] + LayoutSVGText {text} at (12,1) size 319x40 contains 1 chunk(s) + LayoutSVGTextPath {textPath} at (0,0) size 39x318 + LayoutSVGInlineText {#text} at (0,0) size 318x39 + chunk 1 (vertical) text run 1 at (20.41,24.64) startOffset 0 endOffset 1 height 15.00: "V" + chunk 1 (vertical) text run 2 at (31.65,14.87) startOffset 1 endOffset 2 height 15.00: "e" + chunk 1 (vertical) text run 3 at (45.24,8.86) startOffset 2 endOffset 3 height 15.00: "r" + chunk 1 (vertical) text run 4 at (58.81,13.87) startOffset 3 endOffset 4 height 15.00: "t" + chunk 1 (vertical) text run 5 at (69.75,24.45) startOffset 4 endOffset 5 height 15.00: "i" + chunk 1 (vertical) text run 6 at (81.74,33.36) startOffset 5 endOffset 6 height 15.00: "c" + chunk 1 (vertical) text run 7 at (96.12,35.61) startOffset 6 endOffset 7 height 15.00: "a" + chunk 1 (vertical) text run 8 at (108.26,26.75) startOffset 7 endOffset 8 height 15.00: "l" + chunk 1 (vertical) text run 9 at (119.32,16.65) startOffset 8 endOffset 9 height 15.00: " " + chunk 1 (vertical) text run 10 at (132.31,9.40) startOffset 9 endOffset 10 height 15.00: "t" + chunk 1 (vertical) text run 11 at (146.44,11.99) startOffset 10 endOffset 11 height 15.00: "e" + chunk 1 (vertical) text run 12 at (157.60,22.45) startOffset 11 endOffset 12 height 15.00: "x" + chunk 1 (vertical) text run 13 at (169.20,31.87) startOffset 12 endOffset 13 height 15.00: "t" + chunk 1 (vertical) text run 14 at (183.26,36.15) startOffset 13 endOffset 14 height 15.00: " " + chunk 1 (vertical) text run 15 at (196.10,28.90) startOffset 14 endOffset 15 height 15.00: "o" + chunk 1 (vertical) text run 16 at (206.99,18.58) startOffset 15 endOffset 16 height 15.00: "n" + chunk 1 (vertical) text run 17 at (219.50,10.34) startOffset 16 endOffset 17 height 15.00: " " + chunk 1 (vertical) text run 18 at (234.00,10.53) startOffset 17 endOffset 18 height 15.00: "a" + chunk 1 (vertical) text run 19 at (245.44,20.39) startOffset 18 endOffset 19 height 15.00: " " + chunk 1 (vertical) text run 20 at (256.67,30.15) startOffset 19 endOffset 20 height 15.00: "P" + chunk 1 (vertical) text run 21 at (270.28,36.14) startOffset 20 endOffset 21 height 15.00: "a" + chunk 1 (vertical) text run 22 at (283.84,31.10) startOffset 21 endOffset 22 height 15.00: "t" + chunk 1 (vertical) text run 23 at (294.78,20.53) startOffset 22 endOffset 23 height 15.00: "h" + chunk 1 (vertical) text run 24 at (306.77,11.62) startOffset 23 endOffset 24 height 15.00: "\x{753B}" + chunk 1 (vertical) text run 25 at (321.16,9.40) startOffset 24 endOffset 25 height 15.00: "\x{50CF}" + LayoutSVGInlineText {#text} at (0,0) size 0x0 + LayoutSVGContainer {use} at (0,0) size 448x498 + LayoutSVGContainer {g} at (0,0) size 448x498 + LayoutSVGRect {rect} at (0,0) size 448x498 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=446.00] [height=496.00] + LayoutSVGContainer {g} at (418,466) size 28x30 [transform={m=((1.00,0.00)(0.00,1.00)) t=(418.00,467.00)}] + LayoutSVGViewportContainer {svg} at (418,466) size 28x30 + LayoutSVGPath {path} at (418,468) size 14x19 [fill={[type=SOLID] [color=#6666FF]}] [data="M 172 44 C 137 60 31 135 11 199 C 3 226 33 247 55 232 C 14 306 -1 332 0 356 C 0 370 13 398 44 383 C 52 379 79 358 96 342 C 110 341 120 331 138 314 C 155 328 174 324 190 307 C 212 309 272 229 234 199 C 231 175 204 162 181 181 C 175 179 168 180 163 182 C 185 147 206 100 212 77 C 219 47 188 36 172 44 Z"] + LayoutSVGPath {path} at (432,466) size 14x17 [fill={[type=SOLID] [color=#FF0000]}] [data="M 400 0 C 382 3 351 31 351 31 C 322 54 308 89 323 126 C 310 140 294 170 294 193 C 294 221 314 245 344 222 C 351 230 365 238 381 227 C 376 256 384 275 407 276 C 408 286 420 307 443 293 C 459 283 501 254 522 237 C 547 214 547 143 504 148 C 537 89 501 52 477 64 C 467 68 431 89 425 94 C 424 87 420 82 414 80 C 436 45 436 -5 401 0 Z"] + LayoutSVGPath {path} at (425,484) size 16x12 [fill={[type=SOLID] [color=#33CC33]}] [data="M 275 353 C 229 365 187 396 161 444 C 152 460 167 481 186 477 C 172 501 146 544 171 558 C 199 574 223 550 231 543 C 249 564 281 553 312 526 C 353 540 380 524 415 473 C 423 461 445 430 445 408 C 445 392 430 378 410 387 C 409 375 401 349 357 368 C 347 362 326 363 303 385 C 308 375 300 347 275 353 Z"]
diff --git a/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs-expected.html b/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs-expected.html new file mode 100644 index 0000000..94a0bc8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs-expected.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<svg xmlns="http://www.w3.org/2000/svg" width="800" height="100"> + <desc>Test if auto glyph orientation in vertical flow works for surrogate pairs.</desc> + <style> + @font-face { + font-family:cssot; + src:url(../../third_party/adobe-fonts/CSSFWOrientationTest.otf); + } + text.test { + font-family:cssot; + font-size:50px; + } + </style> + <text y="20">Test pass if the triangle points to the right.</text> + <text class="test" writing-mode="tb" x="90" y="30" glyph-orientation-vertical="90">𑀏</text> + <script> + document.body.offsetLeft; // Kick off loading @font-face + if (window.testRunner) { + testRunner.waitUntilDone(); + document.body.onload = function () { testRunner.notifyDone(); }; + } + </script> +</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs.html b/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs.html new file mode 100644 index 0000000..89ada38 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/text/vertical-surrogate-pairs.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<svg xmlns="http://www.w3.org/2000/svg" width="800" height="100"> + <desc>Test if auto glyph orientation in vertical flow works for surrogate pairs.</desc> + <style> + @font-face { + font-family:cssot; + src:url(../../third_party/adobe-fonts/CSSFWOrientationTest.otf); + } + text.test { + font-family:cssot; + font-size:50px; + } + </style> + <text y="20">Test pass if the triangle points to the right.</text> + <text class="test" writing-mode="tb" x="90" y="30">𑀏</text> + <script> + document.body.offsetLeft; // Kick off loading @font-face + if (window.testRunner) { + testRunner.waitUntilDone(); + document.body.onload = function () { testRunner.notifyDone(); }; + } + </script> +</svg>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index e24e5d25..6aa5999 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -327,23 +327,6 @@ return false; } -static void idleGCTaskInMainThread(double deadlineSeconds) -{ - ASSERT(isMainThread()); - ASSERT(RuntimeEnabledFeatures::v8IdleTasksEnabled()); - bool gcFinished = false; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - - Platform* platform = Platform::current(); - if (deadlineSeconds > platform->monotonicallyIncreasingTime()) - gcFinished = isolate->IdleNotificationDeadline(deadlineSeconds); - - if (gcFinished) - platform->currentThread()->scheduler()->postIdleTaskAfterWakeup(FROM_HERE, WTF::bind<double>(idleGCTaskInMainThread)); - else - platform->currentThread()->scheduler()->postIdleTask(FROM_HERE, WTF::bind<double>(idleGCTaskInMainThread)); -} - static void timerTraceProfilerInMainThread(const char* name, int status) { if (!status) { @@ -412,8 +395,6 @@ if (RuntimeEnabledFeatures::v8IdleTasksEnabled()) { WebScheduler* scheduler = Platform::current()->currentThread()->scheduler(); V8PerIsolateData::enableIdleTasks(isolate, adoptPtr(new V8IdleTaskRunner(scheduler))); - // FIXME: Remove idleGCTaskInMainThread once V8 starts posting idle task explicity. - scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(idleGCTaskInMainThread)); } isolate->SetEventLogger(timerTraceProfilerInMainThread);
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index 0320ed7..b80356d 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -1488,8 +1488,6 @@ 'fetch/ResourceClientWalker.h', 'fetch/ResourceFetcher.cpp', 'fetch/ResourceFetcher.h', - 'fetch/ResourceLoadPriorityOptimizer.cpp', - 'fetch/ResourceLoadPriorityOptimizer.h', 'fetch/ResourceLoader.cpp', 'fetch/ResourceLoader.h', 'fetch/ResourceLoaderOptions.h',
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 8d4a1d84..aaec7b836 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -52,7 +52,7 @@ if (ruleType == StyleRule::Viewport) { parseSuccess = (RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(context.mode())) - && parser.parseViewportProperty(resolvedProperty, important); + && parser.parseViewportDescriptor(resolvedProperty, important); } else if (ruleType == StyleRule::FontFace) { parseSuccess = parser.parseFontFaceDescriptor(resolvedProperty); } else { @@ -258,11 +258,9 @@ return nullptr; } -static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless = UnitlessQuirk::Forbid) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange& range, ValueRange valueRange) { const CSSParserToken& token = range.peek(); - if (token.type() == DimensionToken || token.type() == NumberToken) - return consumeLength(range, cssParserMode, valueRange, unitless); if (token.type() == PercentageToken) { if (valueRange == ValueRangeNonNegative && token.numericValue() < 0) return nullptr; @@ -270,6 +268,21 @@ } CalcParser calcParser(range, valueRange); if (const CSSCalcValue* calculation = calcParser.value()) { + if (calculation->category() == CalcPercent) + return calcParser.consumeValue(); + } + return nullptr; +} + +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless = UnitlessQuirk::Forbid) +{ + const CSSParserToken& token = range.peek(); + if (token.type() == DimensionToken || token.type() == NumberToken) + return consumeLength(range, cssParserMode, valueRange, unitless); + if (token.type() == PercentageToken) + return consumePercent(range, valueRange); + CalcParser calcParser(range, valueRange); + if (const CSSCalcValue* calculation = calcParser.value()) { if (calculation->category() == CalcLength || calculation->category() == CalcPercent || calculation->category() == CalcPercentLength) return calcParser.consumeValue(); } @@ -908,6 +921,96 @@ return true; } +static PassRefPtrWillBeRawPtr<CSSValue> consumeSingleViewportDescriptor(CSSParserTokenRange& range, CSSPropertyID propId, CSSParserMode cssParserMode) +{ + CSSValueID id = range.peek().id(); + switch (propId) { + case CSSPropertyMinWidth: + case CSSPropertyMaxWidth: + case CSSPropertyMinHeight: + case CSSPropertyMaxHeight: + if (id == CSSValueAuto || id == CSSValueInternalExtendToZoom) + return consumeIdent(range); + return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative); + case CSSPropertyMinZoom: + case CSSPropertyMaxZoom: + case CSSPropertyZoom: { + if (id == CSSValueAuto) + return consumeIdent(range); + RefPtrWillBeRawPtr<CSSValue> parsedValue = consumeNumber(range, ValueRangeNonNegative); + if (parsedValue) + return parsedValue.release(); + return consumePercent(range, ValueRangeNonNegative); + } + case CSSPropertyUserZoom: + if (id == CSSValueZoom || id == CSSValueFixed) + return consumeIdent(range); + break; + case CSSPropertyOrientation: + if (id == CSSValueAuto || id == CSSValuePortrait || id == CSSValueLandscape) + return consumeIdent(range); + break; + default: + ASSERT_NOT_REACHED(); + break; + } + + return nullptr; +} + +bool CSSPropertyParser::parseViewportDescriptor(CSSPropertyID propId, bool important) +{ + ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); + + m_range.consumeWhitespace(); + + switch (propId) { + case CSSPropertyWidth: { + RefPtrWillBeRawPtr<CSSValue> minWidth = consumeSingleViewportDescriptor(m_range, CSSPropertyMinWidth, m_context.mode()); + if (!minWidth) + return false; + RefPtrWillBeRawPtr<CSSValue> maxWidth = minWidth; + if (!m_range.atEnd()) + maxWidth = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxWidth, m_context.mode()); + if (!maxWidth || !m_range.atEnd()) + return false; + addProperty(CSSPropertyMinWidth, minWidth.release(), important); + addProperty(CSSPropertyMaxWidth, maxWidth.release(), important); + return true; + } + case CSSPropertyHeight: { + RefPtrWillBeRawPtr<CSSValue> minHeight = consumeSingleViewportDescriptor(m_range, CSSPropertyMinHeight, m_context.mode()); + if (!minHeight) + return false; + RefPtrWillBeRawPtr<CSSValue> maxHeight = minHeight; + if (!m_range.atEnd()) + maxHeight = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxHeight, m_context.mode()); + if (!maxHeight || !m_range.atEnd()) + return false; + addProperty(CSSPropertyMinHeight, minHeight.release(), important); + addProperty(CSSPropertyMaxHeight, maxHeight.release(), important); + return true; + } + case CSSPropertyMinWidth: + case CSSPropertyMaxWidth: + case CSSPropertyMinHeight: + case CSSPropertyMaxHeight: + case CSSPropertyMinZoom: + case CSSPropertyMaxZoom: + case CSSPropertyZoom: + case CSSPropertyUserZoom: + case CSSPropertyOrientation: { + RefPtrWillBeRawPtr<CSSValue> parsedValue = consumeSingleViewportDescriptor(m_range, propId, m_context.mode()); + if (!parsedValue || !m_range.atEnd()) + return false; + addProperty(propId, parsedValue.release(), important); + return true; + } + default: + return false; + } +} + bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, bool important) { m_range.consumeWhitespace();
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h index 4f35673..7a1ab9e 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -100,8 +100,7 @@ bool inShorthand() const { return m_inParseShorthand; } bool inQuirksMode() const { return isQuirksModeBehavior(m_context.mode()); } - bool parseViewportProperty(CSSPropertyID propId, bool important); - bool parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important); + bool parseViewportDescriptor(CSSPropertyID propId, bool important); bool parseFontFaceDescriptor(CSSPropertyID); KURL completeURL(const String& url) const;
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp index 8f66df3..6c21acf 100644 --- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -83,15 +83,7 @@ if (m_currentShorthand) { Vector<StylePropertyShorthand, 4> shorthands; getMatchingShorthandsForLonghand(propId, &shorthands); - // Viewport descriptors have width and height as shorthands, but it doesn't - // make sense for CSSProperties.in to consider them as such. The shorthand - // index is only used by the inspector and doesn't affect viewport - // descriptors. - if (shorthands.isEmpty()) - ASSERT(m_currentShorthand == CSSPropertyWidth || m_currentShorthand == CSSPropertyHeight); - else - setFromShorthand = true; - + setFromShorthand = true; if (shorthands.size() > 1) shorthandIndex = indexOfShorthandForLonghand(m_currentShorthand, shorthands); } @@ -6535,87 +6527,6 @@ return true; } -bool CSSPropertyParser::parseViewportProperty(CSSPropertyID propId, bool important) -{ - ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); - - CSSParserValue* value = m_valueList->current(); - if (!value) - return false; - - CSSValueID id = value->id; - bool validPrimitive = false; - - switch (propId) { - case CSSPropertyMinWidth: // auto | extend-to-zoom | <length> | <percentage> - case CSSPropertyMaxWidth: - case CSSPropertyMinHeight: - case CSSPropertyMaxHeight: - if (id == CSSValueAuto || id == CSSValueInternalExtendToZoom) - validPrimitive = true; - else - validPrimitive = validUnit(value, FLength | FPercent | FNonNeg); - break; - case CSSPropertyWidth: // shorthand - return parseViewportShorthand(propId, CSSPropertyMinWidth, CSSPropertyMaxWidth, important); - case CSSPropertyHeight: - return parseViewportShorthand(propId, CSSPropertyMinHeight, CSSPropertyMaxHeight, important); - case CSSPropertyMinZoom: // auto | <number> | <percentage> - case CSSPropertyMaxZoom: - case CSSPropertyZoom: - if (id == CSSValueAuto) - validPrimitive = true; - else - validPrimitive = validUnit(value, FNumber | FPercent | FNonNeg); - break; - case CSSPropertyUserZoom: // zoom | fixed - if (id == CSSValueZoom || id == CSSValueFixed) - validPrimitive = true; - break; - case CSSPropertyOrientation: // auto | portrait | landscape - if (id == CSSValueAuto || id == CSSValuePortrait || id == CSSValueLandscape) - validPrimitive = true; - default: - break; - } - - RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; - if (validPrimitive) { - parsedValue = parseValidPrimitive(id, value); - m_valueList->next(); - } - - if (parsedValue) { - if (!m_valueList->current() || inShorthand()) { - addProperty(propId, parsedValue.release(), important); - return true; - } - } - - return false; -} - -bool CSSPropertyParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important) -{ - ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); - unsigned numValues = m_valueList->size(); - - if (numValues > 2) - return false; - - ShorthandScope scope(this, propId); - - if (!parseViewportProperty(first, important)) - return false; - - // If just one value is supplied, the second value - // is implicitly initialized with the first value. - if (numValues == 1) - m_valueList->previous(); - - return parseViewportProperty(second, important); -} - template <typename CharacterType> static CSSPropertyID unresolvedCSSPropertyID(const CharacterType* propertyName, unsigned length) {
diff --git a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp index 19a728b3..1cac912 100644 --- a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp +++ b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp
@@ -12,16 +12,18 @@ namespace blink { -#if ENABLE(ASSERT) +// TODO(bokan): Enabling these asserts in release temporarily to track down +// crbug.com/519752. Leaving the #if's commented in case I get hit by a bus +// before reverting. +// #if ENABLE(ASSERT) static unsigned checkConnectedSubframeCountIsConsistent(Node&); -#endif +// #endif void ChildFrameDisconnector::disconnect(DisconnectPolicy policy) { -#if ENABLE(ASSERT) +// #if ENABLE(ASSERT) checkConnectedSubframeCountIsConsistent(root()); -#endif - +// #endif if (!root().connectedSubframeCount()) return; @@ -72,7 +74,7 @@ collectFrameOwners(*root); } -#if ENABLE(ASSERT) +// #if ENABLE(ASSERT) static unsigned checkConnectedSubframeCountIsConsistent(Node& node) { unsigned count = 0; @@ -92,15 +94,15 @@ // If we undercount there's possibly a security bug since we'd leave frames // in subtrees outside the document. - ASSERT(node.connectedSubframeCount() >= count); + RELEASE_ASSERT(node.connectedSubframeCount() >= count); // If we overcount it's safe, but not optimal because it means we'll traverse // through the document in ChildFrameDisconnector looking for frames that have // already been disconnected. - ASSERT(node.connectedSubframeCount() == count); + RELEASE_ASSERT(node.connectedSubframeCount() == count); return count; } -#endif +// #endif }
diff --git a/third_party/WebKit/Source/core/dom/DOMMatrix.cpp b/third_party/WebKit/Source/core/dom/DOMMatrix.cpp index bb32a9c..76811ec 100644 --- a/third_party/WebKit/Source/core/dom/DOMMatrix.cpp +++ b/third_party/WebKit/Source/core/dom/DOMMatrix.cpp
@@ -34,8 +34,7 @@ if (!other->is2D()) m_is2D = false; - TransformationMatrix& matrix = *m_matrix; - *m_matrix = matrix * other->matrix(); + *m_matrix *= other->matrix(); return this; }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index a8de8a5..15359a4fb 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -2958,9 +2958,9 @@ m_baseTarget = target ? *target : nullAtom; } -String Document::userAgent(const KURL& url) const +String Document::userAgent() const { - return frame() ? frame()->loader().userAgent(url) : String(); + return frame() ? frame()->loader().userAgent() : String(); } void Document::disableEval(const String& errorMessage)
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index cf8a131..8792af4f 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -526,7 +526,7 @@ KURL completeURL(const String&) const; KURL completeURLWithOverride(const String&, const KURL& baseURLOverride) const; - String userAgent(const KURL&) const final; + String userAgent() const final; void disableEval(const String& errorMessage) final; CSSStyleSheet& elementSheet();
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.h b/third_party/WebKit/Source/core/dom/ExecutionContext.h index c26e5c6..ee4af7d 100644 --- a/third_party/WebKit/Source/core/dom/ExecutionContext.h +++ b/third_party/WebKit/Source/core/dom/ExecutionContext.h
@@ -87,7 +87,7 @@ KURL completeURL(const String& url) const; virtual void disableEval(const String& errorMessage) = 0; virtual LocalDOMWindow* executingWindow() { return 0; } - virtual String userAgent(const KURL&) const = 0; + virtual String userAgent() const = 0; virtual void postTask(const WebTraceLocation&, PassOwnPtr<ExecutionContextTask>) = 0; // Executes the task on context's thread asynchronously. virtual double timerAlignmentInterval() const = 0;
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index 6d51b6b..3312861 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -2190,7 +2190,8 @@ void Node::incrementConnectedSubframeCount(unsigned amount) { - ASSERT(isContainerNode()); + // TODO(bokan): Temporarily made RELEASE_ASSERT to trackdown crbug.com/519752. + RELEASE_ASSERT(isContainerNode()); ensureRareData().incrementConnectedSubframeCount(amount); }
diff --git a/third_party/WebKit/Source/core/dom/NodeRareData.h b/third_party/WebKit/Source/core/dom/NodeRareData.h index 2f43c45b..be0e3e1 100644 --- a/third_party/WebKit/Source/core/dom/NodeRareData.h +++ b/third_party/WebKit/Source/core/dom/NodeRareData.h
@@ -85,8 +85,9 @@ void incrementConnectedSubframeCount(unsigned amount); void decrementConnectedSubframeCount(unsigned amount) { - ASSERT(m_connectedFrameCount); - ASSERT(amount <= m_connectedFrameCount); + // TODO(bokan): Temporarily made RELEASE_ASSERT to trackdown crbug.com/519752. + RELEASE_ASSERT(m_connectedFrameCount); + RELEASE_ASSERT(amount <= m_connectedFrameCount); m_connectedFrameCount -= amount; }
diff --git a/third_party/WebKit/Source/core/events/PointerIdManager.cpp b/third_party/WebKit/Source/core/events/PointerIdManager.cpp index 09bf74d2..a0342b72 100644 --- a/third_party/WebKit/Source/core/events/PointerIdManager.cpp +++ b/third_party/WebKit/Source/core/events/PointerIdManager.cpp
@@ -7,6 +7,12 @@ namespace blink { +namespace { + +inline int toInt(WebPointerProperties::PointerType t) { return static_cast<int>(t); } + +} // namespace + PointerIdManager::PointerIdManager() { clear(); @@ -19,34 +25,34 @@ void PointerIdManager::clear() { - for (int type = 0; type < static_cast<int>(PointerTypeLastEntry); type++) { + for (int type = 0; type <= toInt(WebPointerProperties::PointerType::LastEntry); type++) { m_ids[type].clear(); m_hasPrimaryId[type] = false; } } -void PointerIdManager::add(PointerType type, unsigned id) +void PointerIdManager::add(WebPointerProperties::PointerType type, unsigned id) { - if (m_ids[type].isEmpty()) - m_hasPrimaryId[type] = true; - m_ids[type].add(id); + if (m_ids[toInt(type)].isEmpty()) + m_hasPrimaryId[toInt(type)] = true; + m_ids[toInt(type)].add(id); } -void PointerIdManager::remove(PointerType type, unsigned id) +void PointerIdManager::remove(WebPointerProperties::PointerType type, unsigned id) { if (isPrimary(type, id)) { - m_ids[type].removeFirst(); - m_hasPrimaryId[type] = false; + m_ids[toInt(type)].removeFirst(); + m_hasPrimaryId[toInt(type)] = false; } else { // Note that simply counting the number of ids instead of storing all of them is not enough. // When id is absent, remove() should be a no-op. - m_ids[type].remove(id); + m_ids[toInt(type)].remove(id); } } -bool PointerIdManager::isPrimary(PointerType type, unsigned id) +bool PointerIdManager::isPrimary(WebPointerProperties::PointerType type, unsigned id) { - return m_hasPrimaryId[type] && m_ids[type].first() == id; + return m_hasPrimaryId[toInt(type)] && m_ids[toInt(type)].first() == id; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/events/PointerIdManager.h b/third_party/WebKit/Source/core/events/PointerIdManager.h index 53f860a..0eba3f48b 100644 --- a/third_party/WebKit/Source/core/events/PointerIdManager.h +++ b/third_party/WebKit/Source/core/events/PointerIdManager.h
@@ -5,6 +5,7 @@ #ifndef PointerIdManager_h #define PointerIdManager_h +#include "public/platform/WebPointerProperties.h" #include "wtf/Allocator.h" #include "wtf/ListHashSet.h" @@ -16,25 +17,17 @@ class PointerIdManager { DISALLOW_ALLOCATION(); public: - // TODO(mustaq): Move this enum to PointerEvent.h? Change the spec to use enums? - enum PointerType { - PointerTypeUnknown = 0, - PointerTypeMouse, - PointerTypePen, - PointerTypeTouch, - PointerTypeLastEntry // Must be the last entry in the list - }; - PointerIdManager(); ~PointerIdManager(); void clear(); - void add(PointerType, unsigned); - void remove(PointerType, unsigned); - bool isPrimary(PointerType, unsigned); + void add(WebPointerProperties::PointerType, unsigned); + void remove(WebPointerProperties::PointerType, unsigned); + bool isPrimary(WebPointerProperties::PointerType, unsigned); private: - ListHashSet<unsigned> m_ids[PointerTypeLastEntry]; - bool m_hasPrimaryId[PointerTypeLastEntry]; + // TODO(crbug.com/537319): Switch to /one/ set of ids to guarantee uniqueness. + ListHashSet<unsigned> m_ids[static_cast<int>(WebPointerProperties::PointerType::LastEntry) + 1]; + bool m_hasPrimaryId[static_cast<int>(WebPointerProperties::PointerType::LastEntry) + 1]; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.h b/third_party/WebKit/Source/core/fetch/FetchContext.h index 243bf2b..22869f1 100644 --- a/third_party/WebKit/Source/core/fetch/FetchContext.h +++ b/third_party/WebKit/Source/core/fetch/FetchContext.h
@@ -105,8 +105,8 @@ virtual void addClientHintsIfNecessary(FetchRequest&); virtual void addCSPHeaderIfNecessary(Resource::Type, FetchRequest&); - virtual bool fetchIncreasePriorities() const { return false; } - virtual ResourceLoadPriority modifyPriorityForExperiments(ResourceLoadPriority priority, Resource::Type, const FetchRequest&) { return priority; } + virtual ResourceLoadPriority modifyPriorityForExperiments(ResourceLoadPriority priority, Resource::Type, const FetchRequest&, ResourcePriority::VisibilityStatus) { return priority; } + virtual WebTaskRunner* loadingTaskRunner() const { return nullptr; } protected:
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp index f54a0dc..5c9e2694 100644 --- a/third_party/WebKit/Source/core/fetch/Resource.cpp +++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -941,10 +941,25 @@ void Resource::didChangePriority(ResourceLoadPriority loadPriority, int intraPriorityValue) { + m_resourceRequest.setPriority(loadPriority, intraPriorityValue); if (m_loader) m_loader->didChangePriority(loadPriority, intraPriorityValue); } +ResourcePriority Resource::priorityFromClients() +{ + ResourcePriority priority; + ResourceClientWalker<ResourceClient> walker(m_clients); + while (ResourceClient* c = walker.next()) { + ResourcePriority nextPriority = c->computeResourcePriority(); + if (nextPriority.visibility == ResourcePriority::NotVisible) + continue; + priority.visibility = ResourcePriority::Visible; + priority.intraPriorityValue += nextPriority.intraPriorityValue; + } + return priority; +} + Resource::ResourceCallback* Resource::ResourceCallback::callbackHandler() { DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<ResourceCallback>, callbackHandler, (adoptPtrWillBeNoop(new ResourceCallback)));
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h index 2dbe604..4614d1f 100644 --- a/third_party/WebKit/Source/core/fetch/Resource.h +++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -129,6 +129,7 @@ void setOptions(const ResourceLoaderOptions& options) { m_options = options; } void didChangePriority(ResourceLoadPriority, int intraPriorityValue); + ResourcePriority priorityFromClients(); void addClient(ResourceClient*); void removeClient(ResourceClient*);
diff --git a/third_party/WebKit/Source/core/fetch/ResourceClient.h b/third_party/WebKit/Source/core/fetch/ResourceClient.h index ef33798..d9c1a07 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceClient.h +++ b/third_party/WebKit/Source/core/fetch/ResourceClient.h
@@ -26,6 +26,7 @@ #define ResourceClient_h #include "core/CoreExport.h" +#include "platform/network/ResourceLoadPriority.h" #include "wtf/FastAllocBase.h" #include "wtf/Forward.h" @@ -50,6 +51,8 @@ static ResourceClientType expectedType() { return BaseResourceType; } virtual ResourceClientType resourceClientType() const { return expectedType(); } + virtual ResourcePriority computeResourcePriority() const { return ResourcePriority(); } + protected: ResourceClient() { } };
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp index bea44b3..08399713 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -86,7 +86,7 @@ return ResourceLoadPriorityUnresolved; } -ResourceLoadPriority ResourceFetcher::loadPriority(Resource::Type type, const FetchRequest& request) +ResourceLoadPriority ResourceFetcher::loadPriority(Resource::Type type, const FetchRequest& request, ResourcePriority::VisibilityStatus visibility) { // TODO(yoav): Change it here so that priority can be changed even after it was resolved. if (request.priority() != ResourceLoadPriorityUnresolved) @@ -96,7 +96,7 @@ if (request.options().synchronousPolicy == RequestSynchronously) return ResourceLoadPriorityHighest; - return context().modifyPriorityForExperiments(typeToPriority(type), type, request); + return context().modifyPriorityForExperiments(typeToPriority(type), type, request, visibility); } static void populateResourceTiming(ResourceTimingInfo* info, Resource* resource, bool clearLoadTimings) @@ -380,16 +380,14 @@ resource->setIdentifier(createUniqueIdentifier()); if (!request.forPreload() || policy != Use) { - ResourceLoadPriority priority = loadPriority(factory.type(), request); + ResourceLoadPriority priority = loadPriority(factory.type(), request, ResourcePriority::NotVisible); // When issuing another request for a resource that is already in-flight make // sure to not demote the priority of the in-flight request. If the new request // isn't at the same priority as the in-flight request, only allow promotions. // This can happen when a visible image's priority is increased and then another // reference to the image is parsed (which would be at a lower priority). - if (priority > resource->resourceRequest().priority()) { - resource->mutableResourceRequest().setPriority(priority); + if (priority > resource->resourceRequest().priority()) resource->didChangePriority(priority, 0); - } } if (resourceNeedsLoad(resource.get(), request, policy)) { @@ -868,12 +866,6 @@ context().dispatchDidFinishLoading(resource->identifier(), finishTime, encodedDataLength); } -void ResourceFetcher::didChangeLoadingPriority(const Resource* resource, ResourceLoadPriority loadPriority, int intraPriorityValue) -{ - TRACE_EVENT_ASYNC_STEP_INTO1("blink.net", "Resource", resource, "ChangePriority", "priority", loadPriority); - context().dispatchDidChangeResourcePriority(resource->identifier(), loadPriority, intraPriorityValue); -} - void ResourceFetcher::didFailLoading(const Resource* resource, const ResourceError& error) { TRACE_EVENT_ASYNC_END0("blink.net", "Resource", resource); @@ -1011,6 +1003,28 @@ return true; } +void ResourceFetcher::updateAllImageResourcePriorities() +{ + if (!m_loaders) + return; + + TRACE_EVENT0("blink", "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities"); + for (const auto& loader : m_loaders->hashSet()) { + Resource* resource = loader->cachedResource(); + if (!resource->isImage()) + continue; + + ResourcePriority resourcePriority = resource->priorityFromClients(); + ResourceLoadPriority resourceLoadPriority = loadPriority(Resource::Image, FetchRequest(resource->resourceRequest(), FetchInitiatorInfo()), resourcePriority.visibility); + if (resourceLoadPriority == resource->resourceRequest().priority()) + continue; + + resource->didChangePriority(resourceLoadPriority, resourcePriority.intraPriorityValue); + TRACE_EVENT_ASYNC_STEP_INTO1("blink.net", "Resource", resource, "ChangePriority", "priority", resourceLoadPriority); + context().dispatchDidChangeResourcePriority(resource->identifier(), resourceLoadPriority, resourcePriority.intraPriorityValue); + } +} + #if PRELOAD_DEBUG void ResourceFetcher::printPreloadStats() {
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h index 26cdfdc..d082cf7 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -110,7 +110,6 @@ void didLoadResource(); void redirectReceived(Resource*, const ResourceResponse&); void didFinishLoading(Resource*, double finishTime, int64_t encodedDataLength); - void didChangeLoadingPriority(const Resource*, ResourceLoadPriority, int intraPriorityValue); void didFailLoading(const Resource*, const ResourceError&); void willSendRequest(unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse, const FetchInitiatorInfo&); void didReceiveResponse(const Resource*, const ResourceResponse&); @@ -132,7 +131,7 @@ void acceptDataFromThreadedReceiver(unsigned long identifier, const char* data, int dataLength, int encodedDataLength); - ResourceLoadPriority loadPriority(Resource::Type, const FetchRequest&); + ResourceLoadPriority loadPriority(Resource::Type, const FetchRequest&, ResourcePriority::VisibilityStatus = ResourcePriority::NotVisible); enum ResourceLoadStartType { ResourceLoadingFromNetwork, @@ -149,6 +148,8 @@ WebTaskRunner* loadingTaskRunner(); + void updateAllImageResourcePriorities(); + private: friend class ResourceCacheValidationSuppressor;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.cpp deleted file mode 100644 index a787e14..0000000 --- a/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.cpp +++ /dev/null
@@ -1,132 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/fetch/ResourceLoadPriorityOptimizer.h" - -#include "core/fetch/ResourceLoader.h" -#include "core/layout/LayoutObject.h" -#include "platform/TraceEvent.h" - -#include "wtf/Vector.h" - -namespace blink { - -ResourceLoadPriorityOptimizer* ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer() -{ - DEFINE_STATIC_LOCAL(ResourceLoadPriorityOptimizer, s_renderLoadOptimizer, ()); - return &s_renderLoadOptimizer; -} - -ResourceLoadPriorityOptimizer::ResourceAndVisibility::ResourceAndVisibility(ImageResource* image, VisibilityStatus visibilityStatus, uint32_t screenArea) - : imageResource(image) - , status(visibilityStatus) - , screenArea(screenArea) -{ -} - -ResourceLoadPriorityOptimizer::ResourceAndVisibility::~ResourceAndVisibility() -{ -} - -ResourceLoadPriorityOptimizer::ResourceLoadPriorityOptimizer() -{ -} - -ResourceLoadPriorityOptimizer::~ResourceLoadPriorityOptimizer() -{ -} - -void ResourceLoadPriorityOptimizer::addLayoutObject(LayoutObject* layoutObject) -{ - m_objects.add(layoutObject); - layoutObject->setHasPendingResourceUpdate(true); -} - -void ResourceLoadPriorityOptimizer::removeLayoutObject(LayoutObject* layoutObject) -{ - if (!layoutObject->hasPendingResourceUpdate()) - return; - m_objects.remove(layoutObject); - layoutObject->setHasPendingResourceUpdate(false); -} - -void ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities() -{ - TRACE_EVENT0("blink", "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities"); - - m_imageResources.clear(); - - Vector<LayoutObject*> objectsToRemove; - for (const auto& layoutObject : m_objects) { - if (!layoutObject->updateImageLoadingPriorities()) - objectsToRemove.append(layoutObject); - } - m_objects.removeAll(objectsToRemove); - - updateImageResourcesWithLoadPriority(); -} - -void ResourceLoadPriorityOptimizer::updateImageResourcesWithLoadPriority() -{ - for (const auto& resource : m_imageResources) { - ResourceLoadPriority priority = resource.value->status == Visible ? - ResourceLoadPriorityLow : ResourceLoadPriorityVeryLow; - - if (resource.value->imageResource->loader() && resource.value->imageResource->loader()->shouldUseIncreasedPriorities()) { - priority = resource.value->status == Visible ? - ResourceLoadPriorityHigh : ResourceLoadPriorityLow; - } - - if (priority != resource.value->imageResource->resourceRequest().priority()) { - resource.value->imageResource->mutableResourceRequest().setPriority(priority, resource.value->screenArea); - resource.value->imageResource->didChangePriority(priority, resource.value->screenArea); - } - } - m_imageResources.clear(); -} - -void ResourceLoadPriorityOptimizer::notifyImageResourceVisibility(ImageResource* img, VisibilityStatus status, const LayoutRect& screenRect) -{ - if (!img || img->isLoaded()) - return; - - int screenArea = 0; - if (!screenRect.isEmpty() && status == Visible) - screenArea += static_cast<uint32_t>(screenRect.width() * screenRect.height()); - - ImageResourceMap::AddResult result = m_imageResources.add(img->identifier(), adoptPtr(new ResourceAndVisibility(img, status, screenArea))); - if (!result.isNewEntry && status == Visible) { - result.storedValue->value->status = Visible; - result.storedValue->value->screenArea += screenArea; - } -} - -}
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.h b/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.h deleted file mode 100644 index 17e7d8c..0000000 --- a/third_party/WebKit/Source/core/fetch/ResourceLoadPriorityOptimizer.h +++ /dev/null
@@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ResourceLoadPriorityOptimizer_h -#define ResourceLoadPriorityOptimizer_h - -#include "core/fetch/ImageResource.h" -#include "core/fetch/ResourcePtr.h" -#include "platform/geometry/LayoutRect.h" - -#include "wtf/HashMap.h" -#include "wtf/HashSet.h" -#include "wtf/OwnPtr.h" - -namespace blink { - -class ResourceLoadPriorityOptimizer { - WTF_MAKE_FAST_ALLOCATED(ResourceLoadPriorityOptimizer); - WTF_MAKE_NONCOPYABLE(ResourceLoadPriorityOptimizer); -public: - enum VisibilityStatus { - NotVisible, - Visible, - }; - void notifyImageResourceVisibility(ImageResource*, VisibilityStatus, const LayoutRect&); - void updateAllImageResourcePriorities(); - void addLayoutObject(LayoutObject*); - void removeLayoutObject(LayoutObject*); - - static ResourceLoadPriorityOptimizer* resourceLoadPriorityOptimizer(); - -private: - ResourceLoadPriorityOptimizer(); - ~ResourceLoadPriorityOptimizer(); - - void updateImageResourcesWithLoadPriority(); - - struct ResourceAndVisibility { - ResourceAndVisibility(ImageResource*, VisibilityStatus, uint32_t); - ~ResourceAndVisibility(); - ResourcePtr<ImageResource> imageResource; - VisibilityStatus status; - int screenArea; - }; - - typedef HashMap<unsigned long, OwnPtr<ResourceAndVisibility>, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> ImageResourceMap; - ImageResourceMap m_imageResources; - - typedef HashSet<LayoutObject*> LayoutObjectSet; - LayoutObjectSet m_objects; -}; - -} - -#endif
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp index 935c7e8..fdb7702 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -207,16 +207,9 @@ void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, int intraPriorityValue) { - if (m_loader) { - m_fetcher->didChangeLoadingPriority(m_resource, loadPriority, intraPriorityValue); - ASSERT(m_state != Terminated); + ASSERT(m_state != Terminated); + if (m_loader) m_loader->didChangePriority(static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue); - } -} - -bool ResourceLoader::shouldUseIncreasedPriorities() -{ - return m_fetcher->context().fetchIncreasePriorities(); } void ResourceLoader::cancelIfNotFinishing()
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.h b/third_party/WebKit/Source/core/fetch/ResourceLoader.h index 4712255a..5077de7a 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceLoader.h +++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.h
@@ -69,7 +69,6 @@ void releaseResources(); void didChangePriority(ResourceLoadPriority, int intraPriorityValue); - bool shouldUseIncreasedPriorities(); // WebURLLoaderClient void willFollowRedirect(WebURLLoader*, WebURLRequest&, const WebURLResponse& redirectResponse) override;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoaderSet.h b/third_party/WebKit/Source/core/fetch/ResourceLoaderSet.h index a344bf7..7834c90 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceLoaderSet.h +++ b/third_party/WebKit/Source/core/fetch/ResourceLoaderSet.h
@@ -50,6 +50,7 @@ void cancelAll(); void setAllDefersLoading(bool); int size() const { return m_set.size(); } + const SetType& hashSet() const { return m_set; } private: SetType m_set;
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index abb627e..462fb0f 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -39,7 +39,6 @@ #include "core/editing/RenderedPosition.h" #include "core/editing/markers/DocumentMarkerController.h" #include "core/fetch/ResourceFetcher.h" -#include "core/fetch/ResourceLoadPriorityOptimizer.h" #include "core/frame/FrameHost.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -838,7 +837,7 @@ layoutFromRootObject(*layoutView()); } - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities(); + m_frame->document()->fetcher()->updateAllImageResourcePriorities(); lifecycle().advanceTo(DocumentLifecycle::AfterPerformLayout); @@ -1526,9 +1525,8 @@ void FrameView::didScrollTimerFired(Timer<FrameView>*) { - if (m_frame->document() && m_frame->document()->layoutView()) { - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities(); - } + if (m_frame->document() && m_frame->document()->layoutView()) + m_frame->document()->fetcher()->updateAllImageResourcePriorities(); } void FrameView::updateLayersAndCompositingAfterScrollIfNeeded()
diff --git a/third_party/WebKit/Source/core/frame/Navigator.cpp b/third_party/WebKit/Source/core/frame/Navigator.cpp index 3d1e566..379afd2a 100644 --- a/third_party/WebKit/Source/core/frame/Navigator.cpp +++ b/third_party/WebKit/Source/core/frame/Navigator.cpp
@@ -70,7 +70,7 @@ if (!m_frame || !m_frame->page()) return String(); - return m_frame->loader().userAgent(m_frame->document()->url()); + return m_frame->loader().userAgent(); } bool Navigator::cookieEnabled() const
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 0d96fea..23201c6 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -838,6 +838,9 @@ CredentialManagerGetWithoutUI = 962, CredentialManagerStore = 963, CredentialManagerRequireUserMediation = 964, + RequestAutocomplete = 965, + CastOverlayClicked = 966, + CastOverlayShown = 967, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.idl b/third_party/WebKit/Source/core/html/HTMLFormElement.idl index cbd2500..d9e9d4c 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLFormElement.idl
@@ -44,5 +44,5 @@ boolean checkValidity(); boolean reportValidity(); - [RuntimeEnabled=RequestAutocomplete] void requestAutocomplete(); + [RuntimeEnabled=RequestAutocomplete, MeasureAs=RequestAutocomplete] void requestAutocomplete(); };
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp index c5e86452..7cba88e 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp
@@ -123,10 +123,11 @@ void HTMLFrameOwnerElement::setContentFrame(Frame& frame) { + // TODO(bokan): Temporarily made RELEASE_ASSERT to trackdown crbug.com/519752. // Make sure we will not end up with two frames referencing the same owner element. - ASSERT(!m_contentFrame || m_contentFrame->owner() != this); + RELEASE_ASSERT(!m_contentFrame || m_contentFrame->owner() != this); // Disconnected frames should not be allowed to load. - ASSERT(inDocument()); + RELEASE_ASSERT(inDocument()); m_contentFrame = &frame; for (ContainerNode* node = this; node; node = node->parentOrShadowHostNode()) @@ -167,9 +168,15 @@ HTMLFrameOwnerElement::~HTMLFrameOwnerElement() { +#if !ENABLE(OILPAN) + // TODO(bokan): Temporarily made RELEASE_ASSERT to trackdown crbug.com/519752. // An owner must by now have been informed of detachment // when the frame was closed. - ASSERT(!m_contentFrame); + if (m_contentFrame) { + RELEASE_ASSERT(m_contentFrame->owner() == this); + } + RELEASE_ASSERT(!m_contentFrame); +#endif } Document* HTMLFrameOwnerElement::contentDocument() const
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp index 3e92482..51b92074 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -81,7 +81,7 @@ #endif -void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebTaskRunner* loadingTaskRunner) +void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, PassOwnPtr<WebTaskRunner> loadingTaskRunner) { new BackgroundHTMLParser(reference, config, loadingTaskRunner); // Caller must free by calling stop(). @@ -93,7 +93,7 @@ { } -BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebTaskRunner* loadingTaskRunner) +BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, PassOwnPtr<WebTaskRunner> loadingTaskRunner) : m_weakFactory(reference, this) , m_token(adoptPtr(new HTMLToken)) , m_tokenizer(HTMLTokenizer::create(config->options)) @@ -106,7 +106,7 @@ , m_xssAuditor(config->xssAuditor.release()) , m_preloadScanner(config->preloadScanner.release()) , m_decoder(config->decoder.release()) - , m_loadingTaskRunner(adoptPtr(loadingTaskRunner->clone())) + , m_loadingTaskRunner(loadingTaskRunner) , m_startingScript(false) { ASSERT(m_outstandingTokenLimit > 0);
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h index f07ad2ed..d3f7c8e3 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
@@ -63,7 +63,7 @@ size_t pendingTokenLimit; }; - static void start(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebTaskRunner*); + static void start(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, PassOwnPtr<WebTaskRunner>); struct Checkpoint { WTF_MAKE_FAST_ALLOCATED(CheckPoint); @@ -90,7 +90,7 @@ void forcePlaintextForTextDocument(); private: - BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebTaskRunner*); + BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, PassOwnPtr<WebTaskRunner>); ~BackgroundHTMLParser(); void appendDecodedBytes(const String&);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 07a2709..80f5c23 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -804,7 +804,7 @@ ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::start, reference.release(), config.release(), - AllowCrossThreadAccess(m_loadingTaskRunner.get()))); + adoptPtr(m_loadingTaskRunner->clone()))); } void HTMLDocumentParser::stopBackgroundParser()
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp index da8ec30..18447841 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -32,6 +32,7 @@ #include "bindings/core/v8/ExceptionStatePlaceholder.h" #include "core/InputTypeNames.h" +#include "core/dom/ClientRect.h" #include "core/dom/DOMTokenList.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/MouseEvent.h" @@ -50,10 +51,12 @@ using namespace HTMLNames; -// This is the duration from mediaControls.css -static const double fadeOutDuration = 0.3; +namespace { -static bool isUserInteractionEvent(Event* event) +// This is the duration from mediaControls.css +const double fadeOutDuration = 0.3; + +bool isUserInteractionEvent(Event* event) { const AtomicString& type = event->type(); return type == EventTypeNames::mousedown @@ -65,7 +68,7 @@ } // Sliders (the volume control and timeline) need to capture some additional events used when dragging the thumb. -static bool isUserInteractionEventForSlider(Event* event, LayoutObject* layoutObject) +bool isUserInteractionEventForSlider(Event* event, LayoutObject* layoutObject) { // It is unclear if this can be converted to isUserInteractionEvent(), since // mouse* events seem to be eaten during a drag anyway. crbug.com/516416 . @@ -83,6 +86,16 @@ || type == EventTypeNames::mousemove; } +Element* elementFromCenter(Element& element) +{ + ClientRect* clientRect = element.getBoundingClientRect(); + int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2); + int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); + + return element.document().elementFromPoint(centerX , centerY); +} + +} // anonymous namespace MediaControlPanelElement::MediaControlPanelElement(MediaControls& mediaControls) : MediaControlDivElement(mediaControls, MediaControlsPanel) @@ -552,6 +565,10 @@ void MediaControlCastButtonElement::defaultEventHandler(Event* event) { if (event->type() == EventTypeNames::click) { + if (m_isOverlayButton && !m_clickUseCounted) { + m_clickUseCounted = true; + UseCounter::count(document(), UseCounter::CastOverlayClicked); + } if (mediaElement().isPlayingRemotely()) { mediaElement().requestRemotePlaybackControl(); } else { @@ -585,6 +602,23 @@ } } +void MediaControlCastButtonElement::tryShowOverlay() +{ + ASSERT(m_isOverlayButton); + + setIsWanted(true); + if (elementFromCenter(*this) != &mediaElement()) { + setIsWanted(false); + return; + } + + ASSERT(isWanted()); + if (!m_showUseCounted) { + m_showUseCounted = true; + UseCounter::count(document(), UseCounter::CastOverlayShown); + } +} + bool MediaControlCastButtonElement::keepEventInNode(Event* event) { return isUserInteractionEvent(event);
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h index 1d284d0..6f124c6 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
@@ -190,6 +190,10 @@ void setIsPlayingRemotely(bool); + // This will show a cast button if it is not covered by another element. + // This MUST be called for cast button elements that are overlay elements. + void tryShowOverlay(); + private: explicit MediaControlCastButtonElement(MediaControls&, bool isOverlayButton); @@ -198,6 +202,11 @@ bool keepEventInNode(Event*) override; bool m_isOverlayButton; + + // UseCounter related boolean. They are used to prevent counting something + // twice for the same media element. + bool m_clickUseCounted = false; + bool m_showUseCounted = false; }; // ----------------------------
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp index 3d590fab..00262c4 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp
@@ -457,23 +457,6 @@ BatchedControlUpdate batch(this); } -static Element* elementFromCenter(Element& element) -{ - ClientRect* clientRect = element.getBoundingClientRect(); - int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2); - int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); - - return element.document().elementFromPoint(centerX , centerY); -} - -void MediaControls::tryShowOverlayCastButton() -{ - // The element needs to be shown to have its dimensions and position. - m_overlayCastButton->setIsWanted(true); - if (elementFromCenter(*m_overlayCastButton) != &mediaElement()) - m_overlayCastButton->setIsWanted(false); -} - void MediaControls::refreshCastButtonVisibility() { refreshCastButtonVisibilityWithoutUpdate(); @@ -497,7 +480,7 @@ // non-cast changes (e.g., resize) occur. If the panel button // is shown, however, compute...() will take control of the // overlay cast button if it needs to hide it from the panel. - tryShowOverlayCastButton(); + m_overlayCastButton->tryShowOverlay(); m_castButton->setIsWanted(false); } else if (mediaElement().shouldShowControls()) { m_overlayCastButton->setIsWanted(false); @@ -508,7 +491,7 @@ if ( !RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() && m_fullScreenButton->getBoundingClientRect()->right() > m_panel->getBoundingClientRect()->right()) { m_castButton->setIsWanted(false); - tryShowOverlayCastButton(); + m_overlayCastButton->tryShowOverlay(); } } } else { @@ -519,7 +502,7 @@ void MediaControls::showOverlayCastButton() { - tryShowOverlayCastButton(); + m_overlayCastButton->tryShowOverlay(); resetHideMediaControlsTimer(); } @@ -711,8 +694,12 @@ // Special case for cast: if we want a cast button but dropped it, then // show the overlay cast button instead. - if (m_castButton->isWanted()) - m_overlayCastButton->setIsWanted(droppedCastButton); + if (m_castButton->isWanted()) { + if (droppedCastButton) + m_overlayCastButton->tryShowOverlay(); + else + m_overlayCastButton->setIsWanted(false); + } } void MediaControls::setAllowHiddenVolumeControls(bool allow)
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControls.h b/third_party/WebKit/Source/core/html/shadow/MediaControls.h index baa36f9..2d4fb968 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControls.h +++ b/third_party/WebKit/Source/core/html/shadow/MediaControls.h
@@ -109,10 +109,6 @@ void stopHideMediaControlsTimer(); void resetHideMediaControlsTimer(); - // Attempts to show the overlay cast button. If it is covered by another - // element in the page, it will be hidden. - void tryShowOverlayCastButton(); - void panelWidthChangedTimerFired(Timer<MediaControls>*); // Hide elements that don't fit, and show those things that we want which
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index d2cf3d5b..7b6d4d7 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -3537,34 +3537,17 @@ } } -PointerIdManager::PointerType pointerTypeForWebPointPointerType(WebPointerProperties::PointerType type) -{ - // TODO(e_hakkinen): Simplify this by changing PointerIdManager to use - // WebPointerProperties::PointerType instead of defining its own enum. - switch (type) { - case WebPointerProperties::PointerTypeUnknown: - return PointerIdManager::PointerTypeUnknown; - case WebPointerProperties::PointerTypeTouch: - return PointerIdManager::PointerTypeTouch; - case WebPointerProperties::PointerTypePen: - return PointerIdManager::PointerTypePen; - case WebPointerProperties::PointerTypeMouse: - return PointerIdManager::PointerTypeMouse; - } - ASSERT_NOT_REACHED(); - return PointerIdManager::PointerTypeUnknown; -} - +// TODO(mustaq): Move to WebPointerProperties? static const char* pointerTypeNameForWebPointPointerType(WebPointerProperties::PointerType type) { switch (type) { - case WebPointerProperties::PointerTypeUnknown: + case WebPointerProperties::PointerType::Unknown: return ""; - case WebPointerProperties::PointerTypeTouch: + case WebPointerProperties::PointerType::Touch: return "touch"; - case WebPointerProperties::PointerTypePen: + case WebPointerProperties::PointerType::Pen: return "pen"; - case WebPointerProperties::PointerTypeMouse: + case WebPointerProperties::PointerType::Mouse: return "mouse"; } ASSERT_NOT_REACHED(); @@ -3601,7 +3584,7 @@ bool pointerReleasedOrCancelled = pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled; - const PointerIdManager::PointerType pointerType = pointerTypeForWebPointPointerType(point.pointerProperties().pointerType); + const WebPointerProperties::PointerType pointerType = point.pointerProperties().pointerType; const String& pointerTypeStr = pointerTypeNameForWebPointPointerType(point.pointerProperties().pointerType); if (pointState == PlatformTouchPoint::TouchPressed) @@ -3666,7 +3649,7 @@ EventTypeNames::pointercancel, pointerEventInit); touchInfo.touchTarget->dispatchEvent(pointerEvent.get()); - m_pointerIdManager.remove(PointerIdManager::PointerTypeTouch, pointerId); + m_pointerIdManager.remove(WebPointerProperties::PointerType::Touch, pointerId); } }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp index a934625..86d58872 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp
@@ -47,7 +47,7 @@ InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, int contextGroupId) : InspectorBaseAgent<InspectorDebuggerAgent, InspectorFrontend::Debugger>("Debugger") - , m_v8DebuggerAgent(V8DebuggerAgent::create(injectedScriptManager, debugger, this, contextGroupId)) + , m_v8DebuggerAgent(V8DebuggerAgent::create(injectedScriptManager, debugger, contextGroupId)) { } @@ -74,6 +74,7 @@ void InspectorDebuggerAgent::disable(ErrorString* errorString) { + setTrackingAsyncCalls(false); m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); m_instrumentingAgents->setInspectorDebuggerAgent(nullptr); m_v8DebuggerAgent->disable(errorString); @@ -192,12 +193,12 @@ m_v8DebuggerAgent->evaluateOnCallFrame(errorString, inCallFrameId, inExpression, inObjectGroup, inIncludeCommandLineAPI, inDoNotPauseOnExceptionsAndMuteConsole, inReturnByValue, inGeneratePreview, outResult, optOutWasThrown, optOutExceptionDetails); } -void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& inExpression, const String& inSourceURL, bool inPersistScript, const int* inExecutionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* optOutScriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) +void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& inExpression, const String& inSourceURL, bool inPersistScript, int inExecutionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* optOutScriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) { m_v8DebuggerAgent->compileScript(errorString, inExpression, inSourceURL, inPersistScript, inExecutionContextId, optOutScriptId, optOutExceptionDetails); } -void InspectorDebuggerAgent::runScript(ErrorString* errorString, const String& inScriptId, const int* inExecutionContextId, const String* inObjectGroup, const bool* inDoNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& outResult, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) +void InspectorDebuggerAgent::runScript(ErrorString* errorString, const String& inScriptId, int inExecutionContextId, const String* inObjectGroup, const bool* inDoNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& outResult, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) { Optional<MuteConsoleScope<InspectorDebuggerAgent>> muteScope; if (asBool(inDoNotPauseOnExceptionsAndMuteConsole)) @@ -228,6 +229,7 @@ void InspectorDebuggerAgent::setAsyncCallStackDepth(ErrorString* errorString, int inMaxDepth) { m_v8DebuggerAgent->setAsyncCallStackDepth(errorString, inMaxDepth); + setTrackingAsyncCalls(m_v8DebuggerAgent->trackingAsyncCalls()); } void InspectorDebuggerAgent::enablePromiseTracker(ErrorString* errorString, const bool* inCaptureStacks) @@ -260,17 +262,6 @@ m_v8DebuggerAgent->removeAsyncOperationBreakpoint(errorString, inOperationId); } -// V8DebuggerAgent::Client implementation. -void InspectorDebuggerAgent::asyncCallTrackingStateChanged(bool tracking) -{ - m_asyncCallTracker->asyncCallTrackingStateChanged(tracking); -} - -void InspectorDebuggerAgent::resetAsyncOperations() -{ - m_asyncCallTracker->resetAsyncOperations(); -} - bool InspectorDebuggerAgent::isPaused() { return m_v8DebuggerAgent->isPaused(); @@ -327,6 +318,14 @@ m_v8DebuggerAgent->restore(); ErrorString errorString; enable(&errorString); + setTrackingAsyncCalls(m_v8DebuggerAgent->trackingAsyncCalls()); +} + +void InspectorDebuggerAgent::setTrackingAsyncCalls(bool tracking) +{ + m_asyncCallTracker->asyncCallTrackingStateChanged(tracking); + if (!tracking) + m_asyncCallTracker->resetAsyncOperations(); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h index 20331959..93f5813b 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h
@@ -38,8 +38,7 @@ class CORE_EXPORT InspectorDebuggerAgent : public InspectorBaseAgent<InspectorDebuggerAgent, InspectorFrontend::Debugger> - , public InspectorBackendDispatcher::DebuggerCommandHandler - , public V8DebuggerAgent::Client { + , public InspectorBackendDispatcher::DebuggerCommandHandler { public: ~InspectorDebuggerAgent() override; DECLARE_VIRTUAL_TRACE(); @@ -69,8 +68,8 @@ void getCollectionEntries(ErrorString*, const String& inObjectId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CollectionEntry>>& outEntries) override; void setPauseOnExceptions(ErrorString*, const String& inState) override; void evaluateOnCallFrame(ErrorString*, const String& inCallFrameId, const String& inExpression, const String* inObjectGroup, const bool* inIncludeCommandLineAPI, const bool* inDoNotPauseOnExceptionsAndMuteConsole, const bool* inReturnByValue, const bool* inGeneratePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& outResult, TypeBuilder::OptOutput<bool>* optOutWasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) override; - void compileScript(ErrorString*, const String& inExpression, const String& inSourceURL, bool inPersistScript, const int* inExecutionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* optOutScriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) override; - void runScript(ErrorString*, const String& inScriptId, const int* inExecutionContextId, const String* inObjectGroup, const bool* inDoNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& outResult, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) override; + void compileScript(ErrorString*, const String& inExpression, const String& inSourceURL, bool inPersistScript, int inExecutionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* optOutScriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) override; + void runScript(ErrorString*, const String& inScriptId, int inExecutionContextId, const String* inObjectGroup, const bool* inDoNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& outResult, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& optOutExceptionDetails) override; void setVariableValue(ErrorString*, int inScopeNumber, const String& inVariableName, const RefPtr<JSONObject>& inNewValue, const String* inCallFrameId, const String* inFunctionObjectId) override; void getStepInPositions(ErrorString*, const String& inCallFrameId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location>>& optOutStepInPositions) override; void getBacktrace(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>>& outCallFrames, RefPtr<TypeBuilder::Debugger::StackTrace>& optOutAsyncStackTrace) override; @@ -83,10 +82,6 @@ void setAsyncOperationBreakpoint(ErrorString*, int inOperationId) override; void removeAsyncOperationBreakpoint(ErrorString*, int inOperationId) override; - // V8DebuggerAgent::Client implementation. - void asyncCallTrackingStateChanged(bool tracking) override; - void resetAsyncOperations() override; - // Called by InspectorInstrumentation. bool isPaused(); PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> currentAsyncStackTraceForConsole(); @@ -110,6 +105,9 @@ OwnPtr<V8DebuggerAgent> m_v8DebuggerAgent; OwnPtrWillBeMember<AsyncCallTracker> m_asyncCallTracker; + +private: + void setTrackingAsyncCalls(bool); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.cpp index 35f8656..e55594f9 100644 --- a/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.cpp
@@ -36,6 +36,7 @@ #include "core/dom/Document.h" #include "core/frame/FrameConsole.h" #include "core/frame/LocalFrame.h" +#include "core/inspector/AsyncCallTracker.h" #include "core/inspector/InjectedScript.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/InspectorPageAgent.h" @@ -59,6 +60,7 @@ PageDebuggerAgent::PageDebuggerAgent(MainThreadDebugger* mainThreadDebugger, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager) : InspectorDebuggerAgent(injectedScriptManager, mainThreadDebugger->debugger(), mainThreadDebugger->contextGroupId(pageAgent->inspectedFrame())) , m_pageAgent(pageAgent) + , m_injectedScriptManager(injectedScriptManager) { } @@ -69,6 +71,7 @@ DEFINE_TRACE(PageDebuggerAgent) { visitor->trace(m_pageAgent); + visitor->trace(m_injectedScriptManager); InspectorDebuggerAgent::trace(visitor); } @@ -112,12 +115,6 @@ FrameConsole::unmute(); } -InjectedScript PageDebuggerAgent::defaultInjectedScript() -{ - ScriptState* scriptState = ScriptState::forMainWorld(m_pageAgent->inspectedFrame()); - return m_v8DebuggerAgent->injectedScriptManager()->injectedScriptFor(scriptState); -} - void PageDebuggerAgent::didStartProvisionalLoad(LocalFrame* frame) { if (frame == m_pageAgent->inspectedFrame()) { @@ -131,12 +128,13 @@ // FIXME: what about nested objects? if (frame != m_pageAgent->inspectedFrame()) return; + m_asyncCallTracker->resetAsyncOperations(); m_v8DebuggerAgent->reset(); } -void PageDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails) +void PageDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, int executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails) { - InjectedScript injectedScript = m_v8DebuggerAgent->injectedScriptForEval(errorString, executionContextId); + InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForId(executionContextId); if (injectedScript.isEmpty()) { *errorString = "Inspected frame has gone"; return; @@ -152,9 +150,9 @@ m_compiledScriptURLs.set(scriptId->getValue(), sourceURL); } -void PageDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails) +void PageDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, int executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails) { - InjectedScript injectedScript = m_v8DebuggerAgent->injectedScriptForEval(errorString, executionContextId); + InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForId(executionContextId); if (injectedScript.isEmpty()) { *errorString = "Inspected frame has gone"; return; @@ -169,7 +167,6 @@ InspectorDebuggerAgent::runScript(errorString, scriptId, executionContextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, result, exceptionDetails); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data()); - } } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.h index e352f3c..4d05696 100644 --- a/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/PageDebuggerAgent.h
@@ -56,22 +56,22 @@ void enable(ErrorString*) final; void disable(ErrorString*) final; void restore() final; - void compileScript(ErrorString*, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>*, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; - void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, const int* executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; + void compileScript(ErrorString*, const String& expression, const String& sourceURL, bool persistScript, int executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>*, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; + void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, int executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; void didStartProvisionalLoad(LocalFrame*); void didClearDocumentOfWindowObject(LocalFrame*); private: + PageDebuggerAgent(MainThreadDebugger*, InspectorPageAgent*, InjectedScriptManager*); void muteConsole() override; void unmuteConsole() override; // V8DebuggerAgent::Client implemntation. - InjectedScript defaultInjectedScript() override; bool canExecuteScripts() const; - PageDebuggerAgent(MainThreadDebugger*, InspectorPageAgent*, InjectedScriptManager*); RawPtrWillBeMember<InspectorPageAgent> m_pageAgent; + RawPtrWillBeMember<InjectedScriptManager> m_injectedScriptManager; HashMap<String, String> m_compiledScriptURLs; };
diff --git a/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.cpp index 4bf3d44a..90528b8 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.cpp
@@ -59,11 +59,6 @@ InspectorDebuggerAgent::trace(visitor); } -InjectedScript WorkerDebuggerAgent::defaultInjectedScript() -{ - return m_v8DebuggerAgent->injectedScriptManager()->injectedScriptFor(m_inspectedWorkerGlobalScope->script()->scriptState()); -} - void WorkerDebuggerAgent::muteConsole() { // We don't need to mute console for workers.
diff --git a/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.h index 2d174a9..263b72f 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/WorkerDebuggerAgent.h
@@ -50,7 +50,6 @@ WorkerDebuggerAgent(WorkerThreadDebugger*, WorkerGlobalScope*, InjectedScriptManager*); // V8DebuggerAgent::Client implemntation. - InjectedScript defaultInjectedScript() override; void muteConsole() override; void unmuteConsole() override;
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h index 993ea4e..95b3bbc 100644 --- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h
@@ -24,15 +24,6 @@ class CORE_EXPORT V8DebuggerAgent { public: - class CORE_EXPORT Client { - public: - virtual ~Client() { } - virtual InjectedScript defaultInjectedScript() = 0; - - virtual void asyncCallTrackingStateChanged(bool tracking) = 0; - virtual void resetAsyncOperations() = 0; - }; - // FIXME: remove this enum from public interface once InjectedScriptHost is moved to the implementation. enum BreakpointSource { UserBreakpointSource, @@ -42,8 +33,8 @@ static const char backtraceObjectGroup[]; - // FIXME: injected script management should be an implementation details. This method should only accept client. - static PassOwnPtr<V8DebuggerAgent> create(InjectedScriptManager*, V8Debugger*, V8DebuggerAgent::Client*, int contextGroupId); + // FIXME: injected script management should be an implementation details. + static PassOwnPtr<V8DebuggerAgent> create(InjectedScriptManager*, V8Debugger*, int contextGroupId); virtual ~V8DebuggerAgent() { } // Protocol methods. @@ -71,8 +62,8 @@ virtual void getCollectionEntries(ErrorString*, const String& in_objectId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CollectionEntry>>& out_entries) = 0; virtual void setPauseOnExceptions(ErrorString*, const String& in_state) = 0; virtual void evaluateOnCallFrame(ErrorString*, const String& in_callFrameId, const String& in_expression, const String* in_objectGroup, const bool* in_includeCommandLineAPI, const bool* in_doNotPauseOnExceptionsAndMuteConsole, const bool* in_returnByValue, const bool* in_generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_result, TypeBuilder::OptOutput<bool>* opt_out_wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0; - virtual void compileScript(ErrorString*, const String& in_expression, const String& in_sourceURL, bool in_persistScript, const int* in_executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* opt_out_scriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0; - virtual void runScript(ErrorString*, const String& in_scriptId, const int* in_executionContextId, const String* in_objectGroup, const bool* in_doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0; + virtual void compileScript(ErrorString*, const String& in_expression, const String& in_sourceURL, bool in_persistScript, int in_executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* opt_out_scriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0; + virtual void runScript(ErrorString*, const String& in_scriptId, int in_executionContextId, const String* in_objectGroup, const bool* in_doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0; virtual void setVariableValue(ErrorString*, int in_scopeNumber, const String& in_variableName, const RefPtr<JSONObject>& in_newValue, const String* in_callFrameId, const String* in_functionObjectId) = 0; virtual void getStepInPositions(ErrorString*, const String& in_callFrameId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location>>& opt_out_stepInPositions) = 0; virtual void getBacktrace(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>>& out_callFrames, RefPtr<TypeBuilder::Debugger::StackTrace>& opt_out_asyncStackTrace) = 0; @@ -115,9 +106,6 @@ virtual void traceAsyncCallbackCompleted() = 0; virtual void traceAsyncOperationCompleted(int operationId) = 0; virtual bool trackingAsyncCalls() const = 0; - - virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) = 0; - virtual InjectedScriptManager* injectedScriptManager() = 0; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp index dde11db..ced658e 100644 --- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp +++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp
@@ -122,15 +122,14 @@ return jsCallFrame ? toScriptCallStack(jsCallFrame.get()) : nullptr; } -PassOwnPtr<V8DebuggerAgent> V8DebuggerAgent::create(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, V8DebuggerAgentImpl::Client* client, int contextGroupId) +PassOwnPtr<V8DebuggerAgent> V8DebuggerAgent::create(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, int contextGroupId) { - return adoptPtr(new V8DebuggerAgentImpl(injectedScriptManager, static_cast<V8DebuggerImpl*>(debugger), client, contextGroupId)); + return adoptPtr(new V8DebuggerAgentImpl(injectedScriptManager, static_cast<V8DebuggerImpl*>(debugger), contextGroupId)); } -V8DebuggerAgentImpl::V8DebuggerAgentImpl(InjectedScriptManager* injectedScriptManager, V8DebuggerImpl* debugger, V8DebuggerAgentImpl::Client* client, int contextGroupId) +V8DebuggerAgentImpl::V8DebuggerAgentImpl(InjectedScriptManager* injectedScriptManager, V8DebuggerImpl* debugger, int contextGroupId) : m_injectedScriptManager(injectedScriptManager) , m_debugger(debugger) - , m_client(client) , m_contextGroupId(contextGroupId) , m_enabled(false) , m_state(nullptr) @@ -263,7 +262,6 @@ } else { m_maxAsyncCallStackDepth = depth; } - m_client->asyncCallTrackingStateChanged(m_maxAsyncCallStackDepth); m_v8AsyncCallTracker->asyncCallTrackingStateChanged(m_maxAsyncCallStackDepth); } @@ -915,19 +913,11 @@ injectedScript.evaluateOnCallFrame(errorString, callStack, isAsync, callFrameId, expression, objectGroup ? *objectGroup : "", asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), &result, wasThrown, &exceptionDetails); } -InjectedScript V8DebuggerAgentImpl::injectedScriptForEval(ErrorString* errorString, const int* executionContextId) -{ - InjectedScript injectedScript = executionContextId ? m_injectedScriptManager->injectedScriptForId(*executionContextId) : m_client->defaultInjectedScript(); - if (injectedScript.isEmpty()) - *errorString = "Execution context with given id not found."; - return injectedScript; -} - -void V8DebuggerAgentImpl::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails) +void V8DebuggerAgentImpl::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, int executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails) { if (!checkEnabled(errorString)) return; - InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId); + InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForId(executionContextId); if (injectedScript.isEmpty() || !injectedScript.scriptState()->contextIsValid()) { *errorString = "Inspected frame has gone"; return; @@ -954,11 +944,11 @@ *scriptId = scriptValueId; } -void V8DebuggerAgentImpl::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails) +void V8DebuggerAgentImpl::runScript(ErrorString* errorString, const ScriptId& scriptId, int executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails) { if (!checkEnabled(errorString)) return; - InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId); + InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForId(executionContextId); if (injectedScript.isEmpty()) { *errorString = "Inspected frame has gone"; return; @@ -1292,7 +1282,6 @@ { clearCurrentAsyncOperation(); clearStepIntoAsync(); - m_client->resetAsyncOperations(); m_v8AsyncCallTracker->resetAsyncOperations(); m_asyncOperations.clear(); m_asyncOperationNotifications.clear();
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h index af64e28..b70eaf8 100644 --- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h +++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h
@@ -47,7 +47,7 @@ WTF_MAKE_NONCOPYABLE(V8DebuggerAgentImpl); WTF_MAKE_FAST_ALLOCATED(V8DebuggerAgentImpl); public: - V8DebuggerAgentImpl(InjectedScriptManager*, V8DebuggerImpl*, V8DebuggerAgent::Client*, int contextGroupId); + V8DebuggerAgentImpl(InjectedScriptManager*, V8DebuggerImpl*, int contextGroupId); ~V8DebuggerAgentImpl() override; DECLARE_TRACE(); @@ -96,8 +96,8 @@ RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) final; - void compileScript(ErrorString*, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>*, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; - void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, const int* executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; + void compileScript(ErrorString*, const String& expression, const String& sourceURL, bool persistScript, int executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>*, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; + void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, int executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>&) override; void setVariableValue(ErrorString*, int in_scopeNumber, const String& in_variableName, const RefPtr<JSONObject>& in_newValue, const String* in_callFrame, const String* in_functionObjectId) final; void skipStackFrames(ErrorString*, const String* pattern, const bool* skipContentScripts) final; void setAsyncCallStackDepth(ErrorString*, int depth) final; @@ -132,8 +132,6 @@ // PromiseTracker::Listener void didUpdatePromise(InspectorFrontend::Debugger::EventType::Enum, PassRefPtr<TypeBuilder::Debugger::PromiseDetails>) final; - InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) override; - InjectedScriptManager* injectedScriptManager() override { return m_injectedScriptManager; } void reset() override; private: @@ -194,7 +192,6 @@ RawPtrWillBeWeakPersistent<InjectedScriptManager> m_injectedScriptManager; V8DebuggerImpl* m_debugger; - V8DebuggerAgent::Client* m_client; int m_contextGroupId; bool m_enabled; InspectorState* m_state;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index dc1db87f..60b6fea 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -34,7 +34,6 @@ #include "core/editing/EditingUtilities.h" #include "core/editing/Editor.h" #include "core/editing/FrameSelection.h" -#include "core/fetch/ResourceLoadPriorityOptimizer.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -159,38 +158,6 @@ } } -static void appendImageIfNotNull(WillBeHeapVector<RawPtrWillBeMember<ImageResource>>& imageResources, const StyleImage* styleImage) -{ - if (styleImage && styleImage->cachedImage()) { - ImageResource* imageResource = styleImage->cachedImage(); - if (imageResource && !imageResource->isLoaded()) - imageResources.append(styleImage->cachedImage()); - } -} - -static void appendLayers(WillBeHeapVector<RawPtrWillBeMember<ImageResource>>& images, const FillLayer& styleLayer) -{ - for (const FillLayer* layer = &styleLayer; layer; layer = layer->next()) - appendImageIfNotNull(images, layer->image()); -} - -static void appendImagesFromStyle(WillBeHeapVector<RawPtrWillBeMember<ImageResource>>& images, const ComputedStyle& blockStyle) -{ - appendLayers(images, blockStyle.backgroundLayers()); - appendLayers(images, blockStyle.maskLayers()); - - const ContentData* contentData = blockStyle.contentData(); - if (contentData && contentData->isImage()) - appendImageIfNotNull(images, toImageContentData(contentData)->image()); - if (blockStyle.boxReflect()) - appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image()); - appendImageIfNotNull(images, blockStyle.listStyleImage()); - appendImageIfNotNull(images, blockStyle.borderImageSource()); - appendImageIfNotNull(images, blockStyle.maskBoxImageSource()); - if (blockStyle.shapeOutside()) - appendImageIfNotNull(images, blockStyle.shapeOutside()->image()); -} - void LayoutBlock::removeFromGlobalMaps() { if (gPercentHeightDescendantsMap) @@ -330,15 +297,6 @@ // It's possible for our border/padding to change, but for the overall logical width of the block to // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true. m_widthAvailableToChildrenChanged |= oldStyle && diff.needsFullLayout() && needsLayout() && borderOrPaddingLogicalWidthChanged(*oldStyle, newStyle); - - // If the style has unloaded images, want to notify the ResourceLoadPriorityOptimizer so that - // network priorities can be set. - WillBeHeapVector<RawPtrWillBeMember<ImageResource>> images; - appendImagesFromStyle(images, newStyle); - if (images.isEmpty()) - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeLayoutObject(this); - else - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addLayoutObject(this); } void LayoutBlock::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& childPaintInvalidationState) @@ -947,39 +905,6 @@ invalidateBackgroundObscurationStatus(); } -bool LayoutBlock::updateImageLoadingPriorities() -{ - WillBeHeapVector<RawPtrWillBeMember<ImageResource>> images; - appendImagesFromStyle(images, styleRef()); - - if (images.isEmpty()) - return false; - - LayoutRect viewBounds = viewRect(); - LayoutRect objectBounds(absoluteContentBox()); - // The object bounds might be empty right now, so intersects will fail since it doesn't deal - // with empty rects. Use LayoutRect::contains in that case. - bool isVisible; - if (!objectBounds.isEmpty()) - isVisible = viewBounds.intersects(objectBounds); - else - isVisible = viewBounds.contains(objectBounds); - - ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ? - ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer::NotVisible; - - LayoutRect screenArea; - if (!objectBounds.isEmpty()) { - screenArea = viewBounds; - screenArea.intersect(objectBounds); - } - - for (auto imageResource : images) - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageResourceVisibility(imageResource, status, screenArea); - - return true; -} - bool LayoutBlock::widthAvailableToChildrenHasChanged() { bool widthAvailableToChildrenHasChanged = m_widthAvailableToChildrenChanged; @@ -2287,7 +2212,7 @@ return -1; } -int LayoutBlock::inlineBlockBaseline(LineDirectionMode direction) const +int LayoutBlock::inlineBlockBaseline(LineDirectionMode lineDirection) const { // CSS2.1 states that the baseline of an 'inline-block' is: // the baseline of the last line box in the normal flow, unless it has @@ -2295,19 +2220,11 @@ // value other than 'visible', in which case the baseline is the bottom // margin edge. - // TODO(jchaffraix): A lot of sub-classes overriding this funtion want to - // ignore overflow for baseline computation. Expose a function to do so and - // merge this function with lastLineBoxBaseline. - if (!style()->isOverflowVisible()) { + if (!style()->isOverflowVisible() && !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) { // We are not calling LayoutBox::baselinePosition here because the caller should add the margin-top/margin-right, not us. - return direction == HorizontalLine ? size().height() + marginBottom() : size().width() + marginLeft(); + return lineDirection == HorizontalLine ? size().height() + marginBottom() : size().width() + marginLeft(); } - return lastLineBoxBaseline(direction); -} - -int LayoutBlock::lastLineBoxBaseline(LineDirectionMode lineDirection) const -{ if (isWritingModeRoot() && !isRubyRun()) return -1;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.h b/third_party/WebKit/Source/core/layout/LayoutBlock.h index 258716b..daa2faa 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.h +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.h
@@ -279,7 +279,6 @@ void dirtyForLayoutFromPercentageHeightDescendants(SubtreeLayoutScope&); void layout() override; - bool updateImageLoadingPriorities() final; enum PositionedLayoutBehavior { DefaultLayout, @@ -312,7 +311,12 @@ int firstLineBoxBaseline() const override; int inlineBlockBaseline(LineDirectionMode) const override; - int lastLineBoxBaseline(LineDirectionMode) const; + + // This function disables the 'overflow' check in inlineBlockBaseline. + // For 'inline-block', CSS says that the baseline is the bottom margin edge + // if 'overflow' is not visible. But some descendant classes want to ignore + // this condition. + virtual bool shouldIgnoreOverflowPropertyForInlineBlockBaseline() const { return false; } void updateHitTestResult(HitTestResult&, const LayoutPoint&) override;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 7dd1549..9bbf9b1 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -416,6 +416,8 @@ // TODO(robhogan): We should exclude blocks that create formatting contexts, not just out of flow or floating blocks. if (child->isLayoutBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) { LayoutBlockFlow* block = toLayoutBlockFlow(child); + if (!block->containsFloats()) + continue; lowestBlock = block; if (oldHeight <= newHeight || block->lowestFloatLogicalBottom() + block->logicalTop() <= newHeight) break; @@ -423,6 +425,8 @@ addedOverhangingFloats = true; } } + // If we have no overhanging floats we still pass a record of the lowest non-overhanging float up the tree so we can enclose it if + // we are a formatting context and allow siblings to avoid it if they have negative margin and find themselves in its vicinity. if (!addedOverhangingFloats) addLowestFloatFromChildren(lowestBlock); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index ad71db13..2852e51 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -1356,6 +1356,31 @@ invalidatePaintOfLayerRectsForImage(image, style()->maskLayers(), false); } +ResourcePriority LayoutBox::computeResourcePriority() const +{ + LayoutRect viewBounds = viewRect(); + LayoutRect objectBounds = LayoutRect(absoluteContentBox()); + + // The object bounds might be empty right now, so intersects will fail since it doesn't deal + // with empty rects. Use LayoutRect::contains in that case. + bool isVisible; + if (!objectBounds.isEmpty()) + isVisible = viewBounds.intersects(objectBounds); + else + isVisible = viewBounds.contains(objectBounds); + + LayoutRect screenRect; + if (!objectBounds.isEmpty()) { + screenRect = viewBounds; + screenRect.intersect(objectBounds); + } + + int screenArea = 0; + if (!screenRect.isEmpty() && isVisible) + screenArea = static_cast<uint32_t>(screenRect.width() * screenRect.height()); + return ResourcePriority(isVisible ? ResourcePriority::Visible : ResourcePriority::NotVisible, screenArea); +} + bool LayoutBox::invalidatePaintOfLayerRectsForImage(WrappedImagePtr image, const FillLayer& layers, bool drawingBackground) { if (drawingBackground && (isDocumentElement() || backgroundStolenForBeingBody()))
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index bff4e10..7bdeb24 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -700,6 +700,7 @@ virtual void paintBoxDecorationBackground(const PaintInfo&, const LayoutPoint&) const; virtual void paintMask(const PaintInfo&, const LayoutPoint&) const; void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override; + ResourcePriority computeResourcePriority() const final; void logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& logicalTop, LogicalExtentComputedValues&);
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 9a6b052..a92026e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -1233,7 +1233,7 @@ } if (isColumnFlow()) - setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight()); + setLogicalHeight(std::max(logicalHeight(), mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight())); if (style()->flexDirection() == FlowColumnReverse) { // We have to do an extra pass for column-reverse to reposition the flex items since the start depends
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp index 4910b33..b93b61cc 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -230,9 +230,11 @@ WTF_MAKE_NONCOPYABLE(GridSizingData); STACK_ALLOCATED(); public: - GridSizingData(size_t gridColumnCount, size_t gridRowCount) + GridSizingData(size_t gridColumnCount, size_t gridRowCount, const LayoutUnit& freeSpaceForColumns, const LayoutUnit& freeSpaceForRows) : columnTracks(gridColumnCount) , rowTracks(gridRowCount) + , freeSpaceForColumns(freeSpaceForColumns) + , freeSpaceForRows(freeSpaceForRows) { } @@ -244,6 +246,12 @@ Vector<GridTrack*> filteredTracks; Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; Vector<GridTrack*> growBeyondGrowthLimitsTracks; + + LayoutUnit& freeSpaceForDirection(GridTrackSizingDirection direction) { return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; } + +private: + LayoutUnit freeSpaceForColumns; + LayoutUnit freeSpaceForRows; }; struct GridItemsSpanGroupRange { @@ -363,9 +371,8 @@ { const_cast<LayoutGrid*>(this)->placeItemsOnGrid(); - GridSizingData sizingData(gridColumnCount(), gridRowCount()); - LayoutUnit availableLogicalSpace = 0; - const_cast<LayoutGrid*>(this)->computeUsedBreadthOfGridTracks(ForColumns, sizingData, availableLogicalSpace); + GridSizingData sizingData(gridColumnCount(), gridRowCount(), 0, 0); + const_cast<LayoutGrid*>(this)->computeUsedBreadthOfGridTracks(ForColumns, sizingData); for (const auto& column : sizingData.columnTracks) { const LayoutUnit& minTrackBreadth = column.baseSize(); @@ -394,8 +401,9 @@ return track.baseSize() / std::max<double>(1, flexFactor); } -void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& freeSpace) +void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData) { + LayoutUnit& freeSpace = sizingData.freeSpaceForDirection(direction); const LayoutUnit initialFreeSpace = freeSpace; Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks; Vector<size_t> flexibleSizedTracksIndex; @@ -1275,8 +1283,9 @@ m_gridIsDirty = true; } -void LayoutGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit availableSpace) +void LayoutGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection direction, GridSizingData& sizingData) { + LayoutUnit& availableSpace = sizingData.freeSpaceForDirection(direction); if (availableSpace <= 0 || (direction == ForColumns && styleRef().justifyContentDistribution() != ContentDistributionStretch) || (direction == ForRows && styleRef().alignContentDistribution() != ContentDistributionStretch)) @@ -1303,6 +1312,7 @@ LayoutUnit baseSize = track->baseSize() + sizeToIncrease; track->setBaseSize(baseSize); } + availableSpace = 0; } void LayoutGrid::layoutGridItems() @@ -1316,16 +1326,16 @@ availableSpaceForColumns -= guttersSize(ForColumns, gridColumnCount()); availableSpaceForRows -= guttersSize(ForRows, gridRowCount()); - GridSizingData sizingData(gridColumnCount(), gridRowCount()); - computeUsedBreadthOfGridTracks(ForColumns, sizingData, availableSpaceForColumns); + GridSizingData sizingData(gridColumnCount(), gridRowCount(), availableSpaceForColumns, availableSpaceForRows); + computeUsedBreadthOfGridTracks(ForColumns, sizingData); ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks)); - computeUsedBreadthOfGridTracks(ForRows, sizingData, availableSpaceForRows); + computeUsedBreadthOfGridTracks(ForRows, sizingData); ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks)); - applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData, availableSpaceForColumns); - applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData, availableSpaceForRows); + applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData); + applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData); - populateGridPositions(sizingData, availableSpaceForColumns, availableSpaceForRows); + populateGridPositions(sizingData); m_gridItemsOverflowingGridArea.resize(0); for (LayoutBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { @@ -1518,7 +1528,7 @@ return finalTrackPosition - initialTrackPosition + tracks[span.resolvedFinalPosition.toInt()].baseSize(); } -void LayoutGrid::populateGridPositions(GridSizingData& sizingData, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows) +void LayoutGrid::populateGridPositions(GridSizingData& sizingData) { // Since we add alignment offsets and track gutters, grid lines are not always adjacent. Hence we will have to // assume from now on that we just store positions of the initial grid lines of each track, @@ -1530,7 +1540,7 @@ unsigned numberOfLines = numberOfTracks + 1; unsigned lastLine = numberOfLines - 1; unsigned nextToLastLine = numberOfLines - 2; - ContentAlignmentData offset = computeContentPositionAndDistributionOffset(ForColumns, availableSpaceForColumns, numberOfTracks); + ContentAlignmentData offset = computeContentPositionAndDistributionOffset(ForColumns, sizingData.freeSpaceForDirection(ForColumns), numberOfTracks); LayoutUnit trackGap = guttersSize(ForColumns, 2); m_columnPositions.resize(numberOfLines); m_columnPositions[0] = borderAndPaddingStart() + offset.positionOffset; @@ -1542,7 +1552,7 @@ numberOfLines = numberOfTracks + 1; lastLine = numberOfLines - 1; nextToLastLine = numberOfLines - 2; - offset = computeContentPositionAndDistributionOffset(ForRows, availableSpaceForRows, numberOfTracks); + offset = computeContentPositionAndDistributionOffset(ForRows, sizingData.freeSpaceForDirection(ForRows), numberOfTracks); trackGap = guttersSize(ForRows, 2); m_rowPositions.resize(numberOfLines); m_rowPositions[0] = borderAndPaddingBefore() + offset.positionOffset; @@ -1930,7 +1940,7 @@ } -static ContentAlignmentData contentDistributionOffset(LayoutUnit availableFreeSpace, ContentPosition& fallbackPosition, ContentDistributionType distribution, unsigned numberOfGridTracks) +static ContentAlignmentData contentDistributionOffset(const LayoutUnit& availableFreeSpace, ContentPosition& fallbackPosition, ContentDistributionType distribution, unsigned numberOfGridTracks) { if (distribution != ContentDistributionDefault && fallbackPosition == ContentPositionAuto) fallbackPosition = resolveContentDistributionFallback(distribution); @@ -1962,7 +1972,7 @@ return {}; } -ContentAlignmentData LayoutGrid::computeContentPositionAndDistributionOffset(GridTrackSizingDirection direction, LayoutUnit availableFreeSpace, unsigned numberOfGridTracks) const +ContentAlignmentData LayoutGrid::computeContentPositionAndDistributionOffset(GridTrackSizingDirection direction, const LayoutUnit& availableFreeSpace, unsigned numberOfGridTracks) const { bool isRowAxis = direction == ForColumns; ContentPosition position = isRowAxis ? styleRef().justifyContentPosition() : styleRef().alignContentPosition();
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h index 76ebe36..9cfa669 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.h +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -108,7 +108,7 @@ class GridIterator; struct GridSizingData; bool gridElementIsShrinkToFit(); - void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace); + void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&); LayoutUnit computeUsedBreadthOfMinLength(GridTrackSizingDirection, const GridLength&) const; LayoutUnit computeUsedBreadthOfMaxLength(GridTrackSizingDirection, const GridLength&, LayoutUnit usedBreadth) const; LayoutUnit computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirection, const Length&) const; @@ -129,7 +129,7 @@ void prepareChildForPositionedLayout(LayoutBox&); void layoutPositionedObjects(bool relayoutChildren, PositionedLayoutBehavior = DefaultLayout); void offsetAndBreadthForPositionedChild(const LayoutBox&, GridTrackSizingDirection, LayoutUnit& offset, LayoutUnit& breadth); - void populateGridPositions(GridSizingData&, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows); + void populateGridPositions(GridSizingData&); typedef struct GridItemsSpanGroupRange GridItemsSpanGroupRange; LayoutUnit currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, LayoutBox&, GridTrackSizingDirection, Vector<GridTrack>& columnTracks); @@ -151,14 +151,14 @@ GridAxisPosition rowAxisPositionForChild(const LayoutBox&) const; LayoutUnit rowAxisOffsetForChild(const LayoutBox&) const; LayoutUnit columnAxisOffsetForChild(const LayoutBox&) const; - ContentAlignmentData computeContentPositionAndDistributionOffset(GridTrackSizingDirection, LayoutUnit availableFreeSpace, unsigned numberOfGridTracks) const; + ContentAlignmentData computeContentPositionAndDistributionOffset(GridTrackSizingDirection, const LayoutUnit& availableFreeSpace, unsigned numberOfGridTracks) const; LayoutPoint findChildLogicalPosition(const LayoutBox&, GridSizingData&) const; GridCoordinate cachedGridCoordinate(const LayoutBox&) const; LayoutUnit gridAreaBreadthForChild(const LayoutBox& child, GridTrackSizingDirection, const Vector<GridTrack>&) const; LayoutUnit gridAreaBreadthForChildIncludingAlignmentOffsets(const LayoutBox&, GridTrackSizingDirection, const GridSizingData&) const; - void applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection, GridSizingData&, LayoutUnit availableSpace); + void applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection, GridSizingData&); void paintChildren(const PaintInfo&, const LayoutPoint&) const override;
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImage.cpp index dad06f9..6b30ef9 100644 --- a/third_party/WebKit/Source/core/layout/LayoutImage.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
@@ -31,7 +31,6 @@ #include "core/HTMLNames.h" #include "core/editing/FrameSelection.h" #include "core/fetch/ImageResource.h" -#include "core/fetch/ResourceLoadPriorityOptimizer.h" #include "core/fetch/ResourceLoader.h" #include "core/frame/LocalFrame.h" #include "core/html/HTMLAreaElement.h" @@ -57,7 +56,6 @@ , m_isGeneratedContent(false) , m_imageDevicePixelRatio(1.0f) { - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addLayoutObject(this); } LayoutImage* LayoutImage::createAnonymous(Document* document) @@ -307,36 +305,6 @@ updateInnerContentRect(); } -bool LayoutImage::updateImageLoadingPriorities() -{ - if (!m_imageResource || !m_imageResource->cachedImage() || m_imageResource->cachedImage()->isLoaded()) - return false; - - LayoutRect viewBounds = viewRect(); - LayoutRect objectBounds = LayoutRect(absoluteContentBox()); - - // The object bounds might be empty right now, so intersects will fail since it doesn't deal - // with empty rects. Use LayoutRect::contains in that case. - bool isVisible; - if (!objectBounds.isEmpty()) - isVisible = viewBounds.intersects(objectBounds); - else - isVisible = viewBounds.contains(objectBounds); - - ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ? - ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer::NotVisible; - - LayoutRect screenArea; - if (!objectBounds.isEmpty()) { - screenArea = viewBounds; - screenArea.intersect(objectBounds); - } - - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageResourceVisibility(m_imageResource->cachedImage(), status, screenArea); - - return true; -} - void LayoutImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const { LayoutReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.h b/third_party/WebKit/Source/core/layout/LayoutImage.h index c94f70e..540b7ad 100644 --- a/third_party/WebKit/Source/core/layout/LayoutImage.h +++ b/third_party/WebKit/Source/core/layout/LayoutImage.h
@@ -88,7 +88,6 @@ void paint(const PaintInfo&, const LayoutPoint&) const final; void layout() override; - bool updateImageLoadingPriorities() final; bool isOfType(LayoutObjectType type) const override { return type == LayoutObjectLayoutImage || LayoutReplaced::isOfType(type); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index dabbee1..dd976b7 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -37,7 +37,6 @@ #include "core/editing/EditingUtilities.h" #include "core/editing/FrameSelection.h" #include "core/editing/TextAffinity.h" -#include "core/fetch/ResourceLoadPriorityOptimizer.h" #include "core/fetch/ResourceLoader.h" #include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h" #include "core/frame/EventHandlerRegistry.h" @@ -850,6 +849,24 @@ } } +LayoutObject* LayoutObject::containerForAbsolutePosition(const LayoutBoxModelObject* paintInvalidationContainer, bool* paintInvalidationContainerSkipped) const +{ + // We technically just want our containing block, but + // we may not have one if we're part of an uninstalled + // subtree. We'll climb as high as we can though. + for (LayoutObject* object = parent(); object; object = object->parent()) { + if (object->style()->position() != StaticPosition) + return object; + + if (object->canContainFixedPositionObjects()) + return object; + + if (paintInvalidationContainerSkipped && object == paintInvalidationContainer) + *paintInvalidationContainerSkipped = true; + } + return nullptr; +} + LayoutBlock* LayoutObject::containerForFixedPosition(const LayoutBoxModelObject* paintInvalidationContainer, bool* paintInvalidationContainerSkipped) const { ASSERT(!paintInvalidationContainerSkipped || !*paintInvalidationContainerSkipped); @@ -868,25 +885,16 @@ LayoutBlock* LayoutObject::containingBlockForAbsolutePosition() const { - LayoutObject* o = parent(); - while (o) { - if (o->style()->position() != StaticPosition && (!o->isInline() || o->isReplaced())) - break; + LayoutObject* o = containerForAbsolutePosition(); - if (o->canContainFixedPositionObjects()) - break; - - // For relpositioned inlines, we return the nearest non-anonymous enclosing block. We don't try - // to return the inline itself. This allows us to avoid having a positioned objects - // list in all LayoutInlines and lets us return a strongly-typed LayoutBlock* result - // from this method. The container() method can actually be used to obtain the - // inline directly. - if (o->style()->hasInFlowPosition() && o->isInline() && !o->isReplaced()) { - o = o->containingBlock(); - break; - } - - o = o->parent(); + // For relpositioned inlines, we return the nearest non-anonymous enclosing block. We don't try + // to return the inline itself. This allows us to avoid having a positioned objects + // list in all LayoutInlines and lets us return a strongly-typed LayoutBlock* result + // from this method. The container() method can actually be used to obtain the + // inline directly. + if (o && o->isInline() && !o->isReplaced()) { + ASSERT(o->style()->hasInFlowPosition()); + o = o->containingBlock(); } if (o && !o->isLayoutBlock()) @@ -2417,23 +2425,10 @@ if (pos == FixedPosition) return containerForFixedPosition(paintInvalidationContainer, paintInvalidationContainerSkipped); - if (pos == AbsolutePosition) { - // We technically just want our containing block, but - // we may not have one if we're part of an uninstalled - // subtree. We'll climb as high as we can though. - while (o) { - if (o->style()->position() != StaticPosition) - break; + if (pos == AbsolutePosition) + return containerForAbsolutePosition(paintInvalidationContainer, paintInvalidationContainerSkipped); - if (o->canContainFixedPositionObjects()) - break; - - if (paintInvalidationContainerSkipped && o == paintInvalidationContainer) - *paintInvalidationContainerSkipped = true; - - o = o->parent(); - } - } else if (isColumnSpanAll()) { + if (isColumnSpanAll()) { LayoutObject* multicolContainer = spannerPlaceholder()->container(); if (paintInvalidationContainerSkipped && paintInvalidationContainer) { // We jumped directly from the spanner to the multicol container. Need to check if @@ -2545,7 +2540,6 @@ removeShapeImageClient(m_style->shapeOutside()); } - ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeLayoutObject(this); if (frameView()) setIsSlowRepaintObject(false);
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index aab292f0..6ee0b9bd 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1475,6 +1475,8 @@ LayoutRect previousSelectionRectForPaintInvalidation() const; void setPreviousSelectionRectForPaintInvalidation(const LayoutRect&); + LayoutObject* containerForAbsolutePosition(const LayoutBoxModelObject* paintInvalidationContainer = nullptr, bool* paintInvalidationContainerSkipped = nullptr) const; + const LayoutBoxModelObject* enclosingCompositedContainer() const; LayoutFlowThread* locateFlowThreadContainingBlock() const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.h b/third_party/WebKit/Source/core/layout/LayoutText.h index 3717650..ac8a721 100644 --- a/third_party/WebKit/Source/core/layout/LayoutText.h +++ b/third_party/WebKit/Source/core/layout/LayoutText.h
@@ -114,6 +114,7 @@ UChar characterAt(unsigned) const; UChar uncheckedCharacterAt(unsigned) const; UChar operator[](unsigned i) const { return uncheckedCharacterAt(i); } + UChar32 codepointAt(unsigned) const; unsigned textLength() const { return m_text.length(); } // non virtual implementation of length() void positionLineBox(InlineBox*); @@ -266,6 +267,15 @@ return uncheckedCharacterAt(i); } +inline UChar32 LayoutText::codepointAt(unsigned i) const +{ + UChar32 character = characterAt(i); + if (!U16_IS_LEAD(character)) + return character; + UChar trail = characterAt(i + 1); + return U16_IS_TRAIL(trail) ? U16_GET_SUPPLEMENTARY(character, trail) : character; +} + inline float LayoutText::hyphenWidth(const Font& font, TextDirection direction) { const ComputedStyle& style = styleRef();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.h b/third_party/WebKit/Source/core/layout/LayoutTextControl.h index 54b352c..1ea4935 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControl.h +++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.h
@@ -70,7 +70,7 @@ // We need to override this function because we don't want overflow:hidden on an <input> // to affect the baseline calculation. This is necessary because we are an inline-block // element as an implementation detail which would normally be affected by this. - int inlineBlockBaseline(LineDirectionMode direction) const override { return lastLineBoxBaseline(direction); } + bool shouldIgnoreOverflowPropertyForInlineBlockBaseline() const override { return true; } bool isOfType(LayoutObjectType type) const override { return type == LayoutObjectTextControl || LayoutBlockFlow::isOfType(type); } @@ -105,7 +105,8 @@ return LayoutBlock::baselinePosition(baseline, firstLine, direction, position); } int firstLineBoxBaseline() const override { return LayoutBlock::firstLineBoxBaseline(); } - int inlineBlockBaseline(LineDirectionMode direction) const override { return lastLineBoxBaseline(direction); } + int inlineBlockBaseline(LineDirectionMode direction) const override { return LayoutBlock::inlineBlockBaseline(direction); } + bool shouldIgnoreOverflowPropertyForInlineBlockBaseline() const override { return true; } };
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.h b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.h index cd2284e..6e99885 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.h +++ b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.h
@@ -88,7 +88,7 @@ class LayoutTextControlInnerBlock : public LayoutBlockFlow { public: LayoutTextControlInnerBlock(Element* element) : LayoutBlockFlow(element) { } - int inlineBlockBaseline(LineDirectionMode direction) const override { return lastLineBoxBaseline(direction); } + bool shouldIgnoreOverflowPropertyForInlineBlockBaseline() const override { return true; } private: bool isIntrinsicallyScrollable(ScrollbarOrientation orientation) const override
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp index 2729668..53c6565 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp +++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -375,8 +375,8 @@ return logicalLeft; } -// TODO(wkorman): needsWordSpacing doesn't need to be a reference in the below. Review all params for ref-required. -LayoutUnit InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, +// TODO(wkorman): needsWordSpacing may not need to be a reference in the below. Seek a test case. +void InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, LayoutUnit& logicalLeft, LayoutUnit& minLogicalLeft, LayoutUnit& maxLogicalRight, bool& needsWordSpacing) { for (InlineBox* curr = firstChild; curr && curr != lastChild; curr = curr->nextOnLine()) { @@ -425,8 +425,16 @@ } else if (!curr->layoutObject().isListMarker() || toLayoutListMarker(curr->layoutObject()).isInside()) { // The box can have a different writing-mode than the overall line, so this is a bit complicated. // Just get all the physical margin and overflow values by hand based off |isHorizontal|. - LayoutUnit logicalLeftMargin = isHorizontal() ? curr->boxModelObject().marginLeft() : curr->boxModelObject().marginTop(); - LayoutUnit logicalRightMargin = isHorizontal() ? curr->boxModelObject().marginRight() : curr->boxModelObject().marginBottom(); + LineLayoutBoxModel box = curr->boxModelObject(); + LayoutUnit logicalLeftMargin; + LayoutUnit logicalRightMargin; + if (isHorizontal()) { + logicalLeftMargin = box.marginLeft(); + logicalRightMargin = box.marginRight(); + } else { + logicalLeftMargin = box.marginTop(); + logicalRightMargin = box.marginBottom(); + } logicalLeft += logicalLeftMargin; curr->setLogicalLeft(logicalLeft); @@ -441,7 +449,6 @@ } } } - return logicalLeft; } FontBaseline InlineFlowBox::dominantBaseline() const
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h index 5b88903..8ee280a 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h +++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
@@ -176,15 +176,6 @@ void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, LayoutObject* logicallyLastRunLayoutObject); LayoutUnit getFlowSpacingLogicalWidth(); LayoutUnit placeBoxesInInlineDirection(LayoutUnit logicalLeft, bool& needsWordSpacing); - LayoutUnit placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, - LayoutUnit& logicalLeft, LayoutUnit& minLogicalLeft, LayoutUnit& maxLogicalRight, bool& needsWordSpacing); - void beginPlacingBoxRangesInInlineDirection(LayoutUnit logicalLeft) { setLogicalLeft(logicalLeft); } - void endPlacingBoxRangesInInlineDirection(LayoutUnit logicalLeft, LayoutUnit logicalRight, LayoutUnit minLogicalLeft, LayoutUnit maxLogicalRight) - { - setLogicalWidth(logicalRight - logicalLeft); - if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight)) - clearKnownToHaveNoOverflow(); - } void computeLogicalBoxHeights(RootInlineBox*, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom, int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&); void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom); @@ -290,6 +281,16 @@ void setIsFirstAfterPageBreak(bool isFirstAfterPageBreak) { m_isFirstAfterPageBreak = isFirstAfterPageBreak; } private: + void placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, + LayoutUnit& logicalLeft, LayoutUnit& minLogicalLeft, LayoutUnit& maxLogicalRight, bool& needsWordSpacing); + void beginPlacingBoxRangesInInlineDirection(LayoutUnit logicalLeft) { setLogicalLeft(logicalLeft); } + void endPlacingBoxRangesInInlineDirection(LayoutUnit logicalLeft, LayoutUnit logicalRight, LayoutUnit minLogicalLeft, LayoutUnit maxLogicalRight) + { + setLogicalWidth(logicalRight - logicalLeft); + if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight)) + clearKnownToHaveNoOverflow(); + } + void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow); void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow); void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
diff --git a/third_party/WebKit/Source/core/layout/line/RootInlineBox.cpp b/third_party/WebKit/Source/core/layout/line/RootInlineBox.cpp index 87a8bcf..f1e29306 100644 --- a/third_party/WebKit/Source/core/layout/line/RootInlineBox.cpp +++ b/third_party/WebKit/Source/core/layout/line/RootInlineBox.cpp
@@ -428,7 +428,7 @@ LayoutUnit RootInlineBox::selectionBottom() const { - LayoutUnit selectionBottom = m_selectionBottom; + LayoutUnit selectionBottom = lineLayoutItem().document().inNoQuirksMode() ? m_selectionBottom : m_lineBottom; if (m_hasAnnotationsAfter) selectionBottom += !lineLayoutItem().style()->isFlippedLinesWritingMode() ? computeUnderAnnotationAdjustment(m_lineBottom) : computeOverAnnotationAdjustment(m_lineBottom);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp index 1ef639c..c0d3983c 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
@@ -24,11 +24,7 @@ #include "config.h" #include "core/layout/svg/LayoutSVGResourceFilter.h" -#include "core/dom/ElementTraversal.h" #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" -#include "platform/graphics/GraphicsContext.h" -#include "platform/graphics/filters/SourceGraphic.h" -#include "third_party/skia/include/core/SkPicture.h" namespace blink { @@ -36,13 +32,13 @@ { #if ENABLE(OILPAN) visitor->trace(filter); - visitor->trace(builder); + visitor->trace(nodeMap); #endif } void FilterData::dispose() { - builder = nullptr; + nodeMap = nullptr; filter = nullptr; } @@ -99,34 +95,6 @@ markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } -PassRefPtrWillBeRawPtr<SVGFilterBuilder> LayoutSVGResourceFilter::buildPrimitives(Filter* filter) -{ - SVGFilterElement* filterElement = toSVGFilterElement(element()); - FloatRect referenceBox = filter->referenceBox(); - - // Add effects to the builder - RefPtrWillBeRawPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter->sourceGraphic()); - for (SVGElement* element = Traversal<SVGElement>::firstChild(*filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { - if (!element->isFilterEffect() || !element->layoutObject()) - continue; - - SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); - RefPtrWillBeRawPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); - if (!effect) { - builder->clearEffects(); - return nullptr; - } - builder->appendEffectToEffectReferences(effect, effectElement->layoutObject()); - effectElement->setStandardAttributes(effect.get()); - effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->currentValue()->enumValue(), referenceBox)); - effect->setOperatingColorSpace( - effectElement->layoutObject()->style()->svgStyle().colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); - builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect); - } - filter->setLastEffect(builder->lastEffect()); - return builder.release(); -} - FloatRect LayoutSVGResourceFilter::resourceBoundingBox(const LayoutObject* object) { if (SVGFilterElement* element = toSVGFilterElement(this->element())) @@ -137,27 +105,25 @@ void LayoutSVGResourceFilter::primitiveAttributeChanged(LayoutObject* object, const QualifiedName& attribute) { - FilterMap::iterator it = m_filter.begin(); - FilterMap::iterator end = m_filter.end(); SVGFilterPrimitiveStandardAttributes* primitive = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node()); - for (; it != end; ++it) { - FilterData* filterData = it->value.get(); + for (auto& filter : m_filter) { + FilterData* filterData = filter.value.get(); if (filterData->m_state != FilterData::ReadyToPaint) continue; - SVGFilterBuilder* builder = filterData->builder.get(); - FilterEffect* effect = builder->effectByRenderer(object); + SVGFilterGraphNodeMap* nodeMap = filterData->nodeMap.get(); + FilterEffect* effect = nodeMap->effectByRenderer(object); if (!effect) continue; // Since all effects shares the same attribute value, all // or none of them will be changed. if (!primitive->setFilterEffectAttribute(effect, attribute)) return; - builder->clearResultsRecursive(effect); + nodeMap->invalidateDependentEffects(effect); // Issue paint invalidations for the image on the screen. - markClientForInvalidation(it->key, PaintInvalidation); + markClientForInvalidation(filter.key, PaintInvalidation); } markAllClientLayersForInvalidation(); }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.h index 83a32238..fd77cab 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.h
@@ -60,7 +60,7 @@ DECLARE_TRACE(); RefPtrWillBeMember<Filter> filter; - RefPtrWillBeMember<SVGFilterBuilder> builder; + RefPtrWillBeMember<SVGFilterGraphNodeMap> nodeMap; FilterDataState m_state; private: @@ -82,8 +82,6 @@ FloatRect resourceBoundingBox(const LayoutObject*); - PassRefPtrWillBeRawPtr<SVGFilterBuilder> buildPrimitives(Filter*); - SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(element())->filterUnits()->currentValue()->enumValue(); } SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(element())->primitiveUnits()->currentValue()->enumValue(); }
diff --git a/third_party/WebKit/Source/core/layout/svg/ReferenceFilterBuilder.cpp b/third_party/WebKit/Source/core/layout/svg/ReferenceFilterBuilder.cpp index 0c08e16..c26e496 100644 --- a/third_party/WebKit/Source/core/layout/svg/ReferenceFilterBuilder.cpp +++ b/third_party/WebKit/Source/core/layout/svg/ReferenceFilterBuilder.cpp
@@ -28,16 +28,11 @@ #include "config.h" #include "core/layout/svg/ReferenceFilterBuilder.h" -#include "core/css/CSSPrimitiveValue.h" -#include "core/css/CSSPrimitiveValueMappings.h" -#include "core/css/StylePropertySet.h" #include "core/dom/Element.h" -#include "core/dom/ElementTraversal.h" #include "core/fetch/DocumentResource.h" #include "core/layout/LayoutBox.h" -#include "core/layout/svg/LayoutSVGResourceFilter.h" #include "core/svg/SVGDocumentExtensions.h" -#include "core/svg/SVGFilterPrimitiveStandardAttributes.h" +#include "core/svg/SVGFilterElement.h" #include "core/svg/graphics/filters/SVGFilterBuilder.h" #include "platform/graphics/filters/Filter.h" #include "platform/graphics/filters/SourceGraphic.h" @@ -69,26 +64,6 @@ documentResourceReferences->remove(filterOperation); } -// Returns the color-interpolation-filters property of the element. -static EColorInterpolation colorInterpolationForElement(SVGElement& element, EColorInterpolation parentColorInterpolation) -{ - if (const LayoutObject* layoutObject = element.layoutObject()) - return layoutObject->styleRef().svgStyle().colorInterpolationFilters(); - - // No layout has been performed, try to determine the property value - // "manually" (used by external SVG files.) - if (const StylePropertySet* propertySet = element.presentationAttributeStyle()) { - RefPtrWillBeRawPtr<CSSValue> cssValue = propertySet->getPropertyCSSValue(CSSPropertyColorInterpolationFilters); - if (cssValue && cssValue->isPrimitiveValue()) { - const CSSPrimitiveValue& primitiveValue = *((CSSPrimitiveValue*)cssValue.get()); - return static_cast<EColorInterpolation>(primitiveValue); - } - } - // 'auto' is the default (per Filter Effects), but since the property is - // inherited, propagate the parent's value. - return parentColorInterpolation; -} - PassRefPtrWillBeRawPtr<Filter> ReferenceFilterBuilder::build(float zoom, Element* element, FilterEffect* previousEffect, const ReferenceFilterOperation& filterOperation) { TreeScope* treeScope = &element->treeScope(); @@ -129,26 +104,11 @@ RefPtrWillBeRawPtr<Filter> result(Filter::create(referenceBox, filterRegion, zoom, unitScaling)); if (!previousEffect) previousEffect = result->sourceGraphic(); - RefPtrWillBeRawPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect); - EColorInterpolation filterColorInterpolation = colorInterpolationForElement(filterElement, CI_AUTO); + SVGFilterBuilder builder(previousEffect); + builder.buildGraph(result.get(), filterElement, referenceBox); - for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { - if (!element->isFilterEffect()) - continue; - - SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); - RefPtrWillBeRawPtr<FilterEffect> effect = effectElement->build(builder.get(), result.get()); - if (!effect) - continue; - - effectElement->setStandardAttributes(effect.get()); - effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), referenceBox)); - EColorInterpolation colorInterpolation = colorInterpolationForElement(*effectElement, filterColorInterpolation); - effect->setOperatingColorSpace(colorInterpolation == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); - builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect); - } - result->setLastEffect(builder->lastEffect()); + result->setLastEffect(builder.lastEffect()); return result.release(); }
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp index 81c1c29..6e92261 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -63,8 +63,10 @@ #include "core/svg/SVGRadialGradientElement.h" #include "core/svg/SVGRectElement.h" #include "core/svg/SVGStopElement.h" +#include "core/svg/graphics/filters/SVGFilterBuilder.h" #include "platform/graphics/DashArray.h" #include "platform/graphics/GraphicsTypes.h" +#include "platform/graphics/filters/SourceGraphic.h" #include <math.h> #include <memory> @@ -511,10 +513,10 @@ // Creating a placeholder filter which is passed to the builder. FloatRect dummyRect; RefPtrWillBeRawPtr<Filter> dummyFilter = Filter::create(dummyRect, dummyRect, 1, Filter::BoundingBox); - if (RefPtrWillBeRawPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) { - if (FilterEffect* lastEffect = builder->lastEffect()) - lastEffect->externalRepresentation(ts, indent + 1); - } + SVGFilterBuilder builder(dummyFilter->sourceGraphic()); + builder.buildGraph(dummyFilter.get(), toSVGFilterElement(*filter->element()), dummyRect); + if (FilterEffect* lastEffect = builder.lastEffect()) + lastEffect->externalRepresentation(ts, indent + 1); } else if (resource->resourceType() == ClipperResourceType) { writeNameValuePair(ts, "clipPathUnits", toLayoutSVGResourceClipper(resource)->clipPathUnits()); ts << "\n";
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp index bfcbb00d..3822998 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
@@ -386,7 +386,7 @@ float angle = SVGTextLayoutAttributes::isEmptyValue(data.rotate) ? 0 : data.rotate; // Calculate glyph orientation angle. - UChar currentCharacter = text.characterAt(m_visualMetricsIterator.characterOffset()); + UChar32 currentCharacter = text.codepointAt(m_visualMetricsIterator.characterOffset()); float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, svgStyle, currentCharacter); // Calculate glyph advance & x/y orientation shifts.
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.cpp index 29408f96..09ca768 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.cpp
@@ -148,14 +148,13 @@ } } -float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGComputedStyle& style, const UChar& character) const +float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGComputedStyle& style, const UChar32 character) const { switch (isVerticalText ? style.glyphOrientationVertical() : style.glyphOrientationHorizontal()) { case GO_AUTO: { // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees. // Text which is not fullwidth will be set with a glyph-orientation of 90-degrees. - unsigned unicodeRange = findCharUnicodeRange(character); - if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic) + if (!Character::isUprightInMixedVertical(character)) return 90; return 0;
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.h b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.h index d5f9083..9c0a769 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.h +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngineBaseline.h
@@ -42,7 +42,7 @@ float calculateBaselineShift(const ComputedStyle&) const; float calculateAlignmentBaselineShift(bool isVerticalText, const LayoutObject* textLayoutObject) const; - float calculateGlyphOrientationAngle(bool isVerticalText, const SVGComputedStyle&, const UChar& character) const; + float calculateGlyphOrientationAngle(bool isVerticalText, const SVGComputedStyle&, const UChar32 character) const; float calculateGlyphAdvanceAndOrientation(bool isVerticalText, const SVGTextMetrics&, float angle, float& xOrientationShift, float& yOrientationShift) const; private:
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h index 731829e7..1048eae 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.h +++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -220,7 +220,7 @@ PassRefPtrWillBeRawPtr<DocumentLoader> createDocumentLoader(LocalFrame*, const ResourceRequest&, const SubstituteData&) override; - String userAgent(const KURL&) override { return ""; } + String userAgent() override { return ""; } String doNotTrackValue() override { return String(); }
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 644098b..ff2440b7 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -678,12 +678,7 @@ UseCounter::count(frame(), UseCounter::ClientHintsViewportWidth); } -bool FrameFetchContext::fetchIncreasePriorities() const -{ - return frame()->settings() && frame()->settings()->fetchIncreasePriorities(); -} - -ResourceLoadPriority FrameFetchContext::modifyPriorityForExperiments(ResourceLoadPriority priority, Resource::Type type, const FetchRequest& request) +ResourceLoadPriority FrameFetchContext::modifyPriorityForExperiments(ResourceLoadPriority priority, Resource::Type type, const FetchRequest& request, ResourcePriority::VisibilityStatus visibility) { // An image fetch is used to distinguish between "early" and "late" scripts in a document if (type == Resource::Image) @@ -712,11 +707,18 @@ // of "layout-blocking" resources and provide a boost to resources that are needed // as soon as possible for something currently on the screen. int modifiedPriority = static_cast<int>(priority); - if (fetchIncreasePriorities()) { + if (frame()->settings()->fetchIncreasePriorities()) { if (type == Resource::CSSStyleSheet || type == Resource::Script || type == Resource::Font || type == Resource::Image) modifiedPriority++; } + // Always give visible resources a bump, and an additional bump if generally increasing priorities. + if (visibility == ResourcePriority::Visible) { + modifiedPriority++; + if (frame()->settings()->fetchIncreasePriorities()) + modifiedPriority++; + } + if (frame()->settings()->fetchIncreaseFontPriority() && type == Resource::Font) modifiedPriority++; @@ -725,7 +727,7 @@ if (frame()->settings()->fetchDeferLateScripts() && request.forPreload() && m_imageFetched) modifiedPriority--; // Parser-blocking scripts. - if (fetchIncreasePriorities() && !request.forPreload()) + if (frame()->settings()->fetchIncreasePriorities() && !request.forPreload()) modifiedPriority++; }
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h index a71afae..c2cbc75 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -102,8 +102,7 @@ void addClientHintsIfNecessary(FetchRequest&) override; void addCSPHeaderIfNecessary(Resource::Type, FetchRequest&) override; - bool fetchIncreasePriorities() const override; - ResourceLoadPriority modifyPriorityForExperiments(ResourceLoadPriority, Resource::Type, const FetchRequest&) override; + ResourceLoadPriority modifyPriorityForExperiments(ResourceLoadPriority, Resource::Type, const FetchRequest&, ResourcePriority::VisibilityStatus) override; void countClientHintsDPR() override; void countClientHintsResourceWidth() override;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp index 00394f8..19213d5a 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -436,57 +436,63 @@ settings->setFEtchIncreasePriorities(false); // Base case, no priority change. Note that this triggers m_imageFetched, which will matter for setFetchDeferLateScripts() case below. - EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityLow, Resource::Image, request)); + EXPECT_EQ(ResourceLoadPriorityVeryLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Image, request, ResourcePriority::NotVisible)); + + // Image visibility should increase priority + EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Image, request, ResourcePriority::Visible)); // Font priority with and without fetchIncreaseFontPriority() - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request, ResourcePriority::NotVisible)); settings->setFEtchIncreaseFontPriority(true); - EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request)); + EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request, ResourcePriority::NotVisible)); // Basic script cases - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request)); - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request, ResourcePriority::NotVisible)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest, ResourcePriority::NotVisible)); // Enable deferring late scripts. Preload priority should drop. settings->setFEtchDeferLateScripts(true); - EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest)); + EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest, ResourcePriority::NotVisible)); // Enable increasing priority of async scripts. - EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest)); + EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest, ResourcePriority::NotVisible)); settings->setFEtchIncreaseAsyncScriptPriority(true); - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest, ResourcePriority::NotVisible)); // Enable increased priorities for the remainder. settings->setFEtchIncreasePriorities(true); + // Re-test image priority based on visibility with increased priorities + EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Image, request, ResourcePriority::NotVisible)); + EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Image, request, ResourcePriority::Visible)); + // Re-test font priority with increased prioriries settings->setFEtchIncreaseFontPriority(false); - EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request)); + EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request, ResourcePriority::NotVisible)); settings->setFEtchIncreaseFontPriority(true); - EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request)); + EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Font, request, ResourcePriority::NotVisible)); // Re-test basic script cases and deferring late script case with increased prioriries - settings->setFEtchIncreasePriorities(true); settings->setFEtchDeferLateScripts(false); - EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request)); - EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest)); + EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request, ResourcePriority::NotVisible)); + EXPECT_EQ(ResourceLoadPriorityHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest, ResourcePriority::NotVisible)); // Re-test deferring late scripts. settings->setFEtchDeferLateScripts(true); - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, preloadRequest, ResourcePriority::NotVisible)); // Re-test increasing priority of async scripts. Should ignore general incraesed priorities. settings->setFEtchIncreaseAsyncScriptPriority(false); - EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest)); + EXPECT_EQ(ResourceLoadPriorityLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest, ResourcePriority::NotVisible)); settings->setFEtchIncreaseAsyncScriptPriority(true); - EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest)); + EXPECT_EQ(ResourceLoadPriorityMedium, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, deferredRequest, ResourcePriority::NotVisible)); // Ensure we don't go out of bounds settings->setFEtchIncreasePriorities(true); - EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::Script, request)); + EXPECT_EQ(ResourceLoadPriorityVeryHigh, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::Script, request, ResourcePriority::NotVisible)); settings->setFEtchIncreasePriorities(false); settings->setFEtchDeferLateScripts(true); - EXPECT_EQ(ResourceLoadPriorityVeryLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Script, preloadRequest)); + EXPECT_EQ(ResourceLoadPriorityVeryLow, fetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryLow, Resource::Script, preloadRequest, ResourcePriority::NotVisible)); } TEST_F(FrameFetchContextTest, ModifyPriorityForLowPriorityIframes) @@ -497,13 +503,13 @@ FrameFetchContext* childFetchContext = createChildFrame(); // No low priority iframes, expect default values. - EXPECT_EQ(ResourceLoadPriorityVeryHigh, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::MainResource, request)); - EXPECT_EQ(ResourceLoadPriorityMedium, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request)); + EXPECT_EQ(ResourceLoadPriorityVeryHigh, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::MainResource, request, ResourcePriority::NotVisible)); + EXPECT_EQ(ResourceLoadPriorityMedium, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request, ResourcePriority::NotVisible)); // Low priority iframes enabled, everything should be low priority settings->setLowPriorityIframes(true); - EXPECT_EQ(ResourceLoadPriorityVeryLow, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::MainResource, request)); - EXPECT_EQ(ResourceLoadPriorityVeryLow, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request)); + EXPECT_EQ(ResourceLoadPriorityVeryLow, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityVeryHigh, Resource::MainResource, request, ResourcePriority::NotVisible)); + EXPECT_EQ(ResourceLoadPriorityVeryLow, childFetchContext->modifyPriorityForExperiments(ResourceLoadPriorityMedium, Resource::Script, request, ResourcePriority::NotVisible)); } } // namespace
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index c3abf16..3c711ab 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1172,9 +1172,9 @@ documentLoader()->initialScrollState().didRestoreFromHistory = true; } -String FrameLoader::userAgent(const KURL& url) const +String FrameLoader::userAgent() const { - String userAgent = client()->userAgent(url); + String userAgent = client()->userAgent(); InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent); return userAgent; } @@ -1372,7 +1372,7 @@ void FrameLoader::applyUserAgent(ResourceRequest& request) { - String userAgent = this->userAgent(request.url()); + String userAgent = this->userAgent(); ASSERT(!userAgent.isNull()); request.setHTTPUserAgent(AtomicString(userAgent)); }
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h index 81e75d5..2fe9002 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -132,7 +132,7 @@ void receivedFirstData(); - String userAgent(const KURL&) const; + String userAgent() const; void dispatchDidClearWindowObjectInMainWorld(); void dispatchDidClearDocumentOfWindowObject();
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h index 72155e46..d044f5b6 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h +++ b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
@@ -136,7 +136,7 @@ virtual PassRefPtrWillBeRawPtr<DocumentLoader> createDocumentLoader(LocalFrame*, const ResourceRequest&, const SubstituteData&) = 0; - virtual String userAgent(const KURL&) = 0; + virtual String userAgent() = 0; virtual String doNotTrackValue() = 0;
diff --git a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h index abae03e..a1e835ac 100644 --- a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h +++ b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h
@@ -93,7 +93,7 @@ public: TestDisplayItem(const DisplayItemClientWrapper& client, Type type) : DisplayItem(client, type, sizeof(*this)) { } - void replay(GraphicsContext&) final { ASSERT_NOT_REACHED(); } + void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); } void appendToWebDisplayItemList(WebDisplayItemList*) const final { ASSERT_NOT_REACHED(); } };
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h index a9a83600..7e9ca9b 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.h +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -90,21 +90,58 @@ }; // PaintLayer is an old object that handles lots of unrelated operations. -// We want it to die at some point and be replaced by more focused objects. -// Removing a lot of unneeded complexity. Complex painting operations (opacity, -// clipping, filters, reflections, ...), hardware acceleration (through -// PaintLayerCompositor), scrolling (through PaintLayerScrollableArea) along -// with some optimizations are all handled by PaintLayer. // -// The class is central to painting and hit-testing: it implements the painting -// order through PaintLayerStackingNode and handle lots of complex graphics -// operations LayoutObjects don't handle (e.g. 'filter' and 'opacity'). +// We want it to die at some point and be replaced by more focused objects, +// which would remove (or at least compartimentalize) a lot of complexity. +// See the STATUS OF PAINTLAYER section below. +// +// The class is central to painting and hit-testing. That's because it handles +// a lot of tasks (we included ones done by associated satellite objects for +// historical reasons): +// - Complex painting operations (opacity, clipping, filters, reflections, ...). +// - hardware acceleration (through PaintLayerCompositor). +// - scrolling (through PaintLayerScrollableArea). +// - some performance optimizations. // // The compositing code is also based on PaintLayer. The entry to it is the // PaintLayerCompositor, which fills |m_compositedLayerMapping| for hardware // accelerated layers. // // TODO(jchaffraix): Expand the documentation about hardware acceleration. +// +// +// ***** SELF-PAINTING LAYER ***** +// One important concept about PaintLayer is "self-painting" +// (m_isSelfPaintingLayer). +// PaintLayer started as the implementation of a stacking context. This meant +// that we had to use PaintLayer's painting order (the code is now in +// PaintLayerPainter and PaintLayerStackingNode) instead of the LayoutObject's +// children order. Over the years, as more operations were handled by +// PaintLayer, some LayoutObjects that were not stacking context needed to have +// a PaintLayer for bookkeeping reasons. One such example is the overflow hidden +// case that wanted hardware acceleration and thus had to allocate a PaintLayer +// to get it. However overflow hidden is something LayoutObject can paint +// without a PaintLayer, which includes a lot of painting overhead. Thus the +// self-painting flag was introduced. The flag is a band-aid solution done for +// performance reason only. It just brush over the underlying problem, which is +// that its design doesn't match the system's requirements anymore. +// +// +// ***** STATUS OF PAINTLAYER ***** +// We would like to remove this class in the future. The reasons for the removal +// are: +// - it has been a dumping ground for features for too long. +// - it is the wrong level of abstraction, bearing no correspondence to any CSS +// concept. +// +// Its features need to be migrated to helper objects. This was started with the +// introduction of satellite objects: PaintLayer*. Those helper objects then +// need to be moved to the appropriate LayoutObject class, probably to a rare +// data field to avoid growing all the LayoutObjects. +// +// A good example of this is PaintLayerScrollableArea, which can only happen +// be instanciated for LayoutBoxes. With the current design, it's hard to know +// that by reading the code. class CORE_EXPORT PaintLayer { WTF_MAKE_NONCOPYABLE(PaintLayer); public:
diff --git a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp index bb7a3f9..f54c0ce6 100644 --- a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp +++ b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp
@@ -122,31 +122,32 @@ } OwnPtrWillBeRawPtr<FilterData> filterData = FilterData::create(); - FloatRect targetBoundingBox = object.objectBoundingBox(); + FloatRect referenceBox = object.objectBoundingBox(); SVGFilterElement* filterElement = toSVGFilterElement(m_filter.element()); - FloatRect filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox); + FloatRect filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), referenceBox); if (filterRegion.isEmpty()) return nullptr; // Create the SVGFilter object. bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; Filter::UnitScaling unitScaling = primitiveBoundingBoxMode ? Filter::BoundingBox : Filter::UserSpace; - filterData->filter = Filter::create(targetBoundingBox, filterRegion, 1, unitScaling); + filterData->filter = Filter::create(referenceBox, filterRegion, 1, unitScaling); + filterData->nodeMap = SVGFilterGraphNodeMap::create(); IntRect sourceRegion = enclosingIntRect(intersection(filterRegion, object.strokeBoundingBox())); filterData->filter->sourceGraphic()->setSourceRect(sourceRegion); // Create all relevant filter primitives. - filterData->builder = m_filter.buildPrimitives(filterData->filter.get()); - if (!filterData->builder) - return nullptr; + SVGFilterBuilder builder(filterData->filter->sourceGraphic(), filterData->nodeMap.get()); + builder.buildGraph(filterData->filter.get(), *filterElement, referenceBox); - FilterEffect* lastEffect = filterData->filter->lastEffect(); + FilterEffect* lastEffect = builder.lastEffect(); if (!lastEffect) return nullptr; lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion); + filterData->filter->setLastEffect(lastEffect); FilterData* data = filterData.get(); // TODO(pdr): Can this be moved out of painter?
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp index a032ced..36e291a 100644 --- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp +++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
@@ -20,12 +20,68 @@ #include "config.h" #include "core/svg/graphics/filters/SVGFilterBuilder.h" +#include "core/css/CSSPrimitiveValue.h" +#include "core/css/CSSPrimitiveValueMappings.h" +#include "core/css/StylePropertySet.h" +#include "core/dom/ElementTraversal.h" +#include "core/layout/LayoutObject.h" +#include "core/svg/SVGFilterElement.h" +#include "core/svg/SVGFilterPrimitiveStandardAttributes.h" +#include "platform/graphics/filters/Filter.h" #include "platform/graphics/filters/SourceAlpha.h" #include "platform/graphics/filters/SourceGraphic.h" namespace blink { -SVGFilterBuilder::SVGFilterBuilder(PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic) +void SVGFilterGraphNodeMap::addBuiltinEffect(FilterEffect* effect) +{ + m_effectReferences.add(effect, FilterEffectSet()); +} + +void SVGFilterGraphNodeMap::addPrimitive(LayoutObject* object, PassRefPtrWillBeRawPtr<FilterEffect> prpEffect) +{ + RefPtrWillBeRawPtr<FilterEffect> effect = prpEffect; + + // The effect must be a newly created filter effect. + ASSERT(!m_effectReferences.contains(effect)); + ASSERT(object && !m_effectRenderer.contains(object)); + m_effectReferences.add(effect, FilterEffectSet()); + + unsigned numberOfInputEffects = effect->inputEffects().size(); + + // Add references from the inputs of this effect to the effect itself, to + // allow determining what effects needs to be invalidated when a certain + // effect changes. + for (unsigned i = 0; i < numberOfInputEffects; ++i) + effectReferences(effect->inputEffect(i)).add(effect.get()); + + m_effectRenderer.add(object, effect.get()); +} + +void SVGFilterGraphNodeMap::invalidateDependentEffects(FilterEffect* effect) +{ + if (!effect->hasImageFilter()) + return; + + effect->clearResult(); + + FilterEffectSet& effectReferences = this->effectReferences(effect); + for (FilterEffect* effectReference : effectReferences) + invalidateDependentEffects(effectReference); +} + +DEFINE_TRACE(SVGFilterGraphNodeMap) +{ +#if ENABLE(OILPAN) + visitor->trace(m_effectRenderer); + visitor->trace(m_effectReferences); +#endif +} + +SVGFilterBuilder::SVGFilterBuilder( + PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic, + PassRefPtrWillBeRawPtr<SVGFilterGraphNodeMap> nodeMap) + : m_nodeMap(nodeMap) { RefPtrWillBeRawPtr<FilterEffect> sourceGraphicRef = sourceGraphic; m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphicRef); @@ -33,15 +89,56 @@ addBuiltinEffects(); } -DEFINE_TRACE(SVGFilterBuilder) +void SVGFilterBuilder::addBuiltinEffects() { -#if ENABLE(OILPAN) - visitor->trace(m_builtinEffects); - visitor->trace(m_namedEffects); - visitor->trace(m_effectRenderer); - visitor->trace(m_effectReferences); - visitor->trace(m_lastEffect); -#endif + if (!m_nodeMap) + return; + for (const auto& entry : m_builtinEffects) + m_nodeMap->addBuiltinEffect(entry.value.get()); +} + +// Returns the color-interpolation-filters property of the element. +static EColorInterpolation colorInterpolationForElement(SVGElement& element, EColorInterpolation parentColorInterpolation) +{ + if (const LayoutObject* layoutObject = element.layoutObject()) + return layoutObject->styleRef().svgStyle().colorInterpolationFilters(); + + // No layout has been performed, try to determine the property value + // "manually" (used by external SVG files.) + if (const StylePropertySet* propertySet = element.presentationAttributeStyle()) { + RefPtrWillBeRawPtr<CSSValue> cssValue = propertySet->getPropertyCSSValue(CSSPropertyColorInterpolationFilters); + if (cssValue && cssValue->isPrimitiveValue()) { + const CSSPrimitiveValue& primitiveValue = *((CSSPrimitiveValue*)cssValue.get()); + return static_cast<EColorInterpolation>(primitiveValue); + } + } + // 'auto' is the default (per Filter Effects), but since the property is + // inherited, propagate the parent's value. + return parentColorInterpolation; +} + +void SVGFilterBuilder::buildGraph(Filter* filter, SVGFilterElement& filterElement, const FloatRect& referenceBox) +{ + EColorInterpolation filterColorInterpolation = colorInterpolationForElement(filterElement, CI_AUTO); + + for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { + if (!element->isFilterEffect()) + continue; + + SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); + RefPtrWillBeRawPtr<FilterEffect> effect = effectElement->build(this, filter); + if (!effect) + continue; + + if (m_nodeMap && effectElement->layoutObject()) + m_nodeMap->addPrimitive(effectElement->layoutObject(), effect); + effectElement->setStandardAttributes(effect.get()); + effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), referenceBox)); + EColorInterpolation colorInterpolation = colorInterpolationForElement(*effectElement, filterColorInterpolation); + effect->setOperatingColorSpace(colorInterpolation == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); + + add(AtomicString(effectElement->result()->currentValue()->value()), effect); + } } void SVGFilterBuilder::add(const AtomicString& id, PassRefPtrWillBeRawPtr<FilterEffect> effect) @@ -74,42 +171,4 @@ return m_builtinEffects.get(SourceGraphic::effectName()); } -void SVGFilterBuilder::appendEffectToEffectReferences(PassRefPtrWillBeRawPtr<FilterEffect> prpEffect, LayoutObject* object) -{ - RefPtrWillBeRawPtr<FilterEffect> effect = prpEffect; - - // The effect must be a newly created filter effect. - ASSERT(!m_effectReferences.contains(effect)); - ASSERT(object && !m_effectRenderer.contains(object)); - m_effectReferences.add(effect, FilterEffectSet()); - - unsigned numberOfInputEffects = effect->inputEffects().size(); - - // It is not possible to add the same value to a set twice. - for (unsigned i = 0; i < numberOfInputEffects; ++i) - effectReferences(effect->inputEffect(i)).add(effect.get()); - m_effectRenderer.add(object, effect.get()); -} - -void SVGFilterBuilder::clearEffects() -{ - m_lastEffect = nullptr; - m_namedEffects.clear(); - m_effectReferences.clear(); - m_effectRenderer.clear(); - addBuiltinEffects(); -} - -void SVGFilterBuilder::clearResultsRecursive(FilterEffect* effect) -{ - if (!effect->hasImageFilter()) - return; - - effect->clearResult(); - - FilterEffectSet& effectReferences = this->effectReferences(effect); - for (FilterEffect* effectReference : effectReferences) - clearResultsRecursive(effectReference); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h index 9328bde..6cfd03c 100644 --- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h +++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h
@@ -31,23 +31,23 @@ namespace blink { +class FloatRect; class LayoutObject; +class SVGFilterElement; -class SVGFilterBuilder final : public RefCountedWillBeGarbageCollectedFinalized<SVGFilterBuilder> { +// A map from LayoutObject -> FilterEffect and FilterEffect -> dependent (downstream) FilterEffects ("reverse DAG"). +// Used during invalidations from changes to the primitives (graph nodes). +class SVGFilterGraphNodeMap final : public RefCountedWillBeGarbageCollectedFinalized<SVGFilterGraphNodeMap> { public: - typedef WillBeHeapHashSet<RawPtrWillBeMember<FilterEffect>> FilterEffectSet; - - static PassRefPtrWillBeRawPtr<SVGFilterBuilder> create(PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic) + static PassRefPtrWillBeRawPtr<SVGFilterGraphNodeMap> create() { - return adoptRefWillBeNoop(new SVGFilterBuilder(sourceGraphic)); + return adoptRefWillBeNoop(new SVGFilterGraphNodeMap); } - void add(const AtomicString& id, PassRefPtrWillBeRawPtr<FilterEffect>); + typedef WillBeHeapHashSet<RawPtrWillBeMember<FilterEffect>> FilterEffectSet; - FilterEffect* getEffectById(const AtomicString& id) const; - FilterEffect* lastEffect() const { return m_lastEffect.get(); } - - void appendEffectToEffectReferences(PassRefPtrWillBeRawPtr<FilterEffect>, LayoutObject*); + void addBuiltinEffect(FilterEffect*); + void addPrimitive(LayoutObject*, PassRefPtrWillBeRawPtr<FilterEffect>); inline FilterEffectSet& effectReferences(FilterEffect* effect) { @@ -59,30 +59,42 @@ // Required to change the attributes of a filter during an svgAttributeChanged. inline FilterEffect* effectByRenderer(LayoutObject* object) { return m_effectRenderer.get(object); } - void clearEffects(); - void clearResultsRecursive(FilterEffect*); + void invalidateDependentEffects(FilterEffect*); DECLARE_TRACE(); private: - SVGFilterBuilder(PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic); + SVGFilterGraphNodeMap() = default; - inline void addBuiltinEffects() - { - for (const auto& entry : m_builtinEffects) - m_effectReferences.add(entry.value, FilterEffectSet()); - } + // The value is a list, which contains those filter effects, + // which depends on the key filter effect. + WillBeHeapHashMap<RefPtrWillBeMember<FilterEffect>, FilterEffectSet> m_effectReferences; + WillBeHeapHashMap<LayoutObject*, RawPtrWillBeMember<FilterEffect>> m_effectRenderer; +}; + +class SVGFilterBuilder { + STACK_ALLOCATED(); +public: + SVGFilterBuilder( + PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic, + PassRefPtrWillBeRawPtr<SVGFilterGraphNodeMap> = nullptr); + + void buildGraph(Filter*, SVGFilterElement&, const FloatRect&); + + FilterEffect* getEffectById(const AtomicString& id) const; + FilterEffect* lastEffect() const { return m_lastEffect.get(); } + +private: + void add(const AtomicString& id, PassRefPtrWillBeRawPtr<FilterEffect>); + void addBuiltinEffects(); typedef WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<FilterEffect>> NamedFilterEffectMap; NamedFilterEffectMap m_builtinEffects; NamedFilterEffectMap m_namedEffects; - // The value is a list, which contains those filter effects, - // which depends on the key filter effect. - WillBeHeapHashMap<RefPtrWillBeMember<FilterEffect>, FilterEffectSet> m_effectReferences; - WillBeHeapHashMap<LayoutObject*, RawPtrWillBeMember<FilterEffect>> m_effectRenderer; RefPtrWillBeMember<FilterEffect> m_lastEffect; + RefPtrWillBeMember<SVGFilterGraphNodeMap> m_nodeMap; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/testing/NullExecutionContext.h b/third_party/WebKit/Source/core/testing/NullExecutionContext.h index cc995631..9cb49be3 100644 --- a/third_party/WebKit/Source/core/testing/NullExecutionContext.h +++ b/third_party/WebKit/Source/core/testing/NullExecutionContext.h
@@ -22,7 +22,7 @@ NullExecutionContext(); void disableEval(const String&) override { } - String userAgent(const KURL&) const override { return String(); } + String userAgent() const override { return String(); } void postTask(const WebTraceLocation&, PassOwnPtr<ExecutionContextTask>) override;
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp index 254bdf5..b369a06 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
@@ -102,7 +102,7 @@ WorkerThreadStartMode startMode = DontPauseWorkerGlobalScopeOnStart; if (InspectorInstrumentation::shouldPauseDedicatedWorkerOnStart(executionContext())) startMode = PauseWorkerGlobalScopeOnStart; - m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), executionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), startMode); + m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), executionContext()->userAgent(), m_scriptLoader->script(), startMode); InspectorInstrumentation::scriptImported(executionContext(), m_scriptLoader->identifier(), m_scriptLoader->script()); } m_contentSecurityPolicy = m_scriptLoader->releaseContentSecurityPolicy();
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index d7efd1a..dadf25db 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -137,7 +137,7 @@ return KURL(m_url, url); } -String WorkerGlobalScope::userAgent(const KURL&) const +String WorkerGlobalScope::userAgent() const { return m_userAgent; }
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h index b7ffa07..51da5e3 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -78,7 +78,7 @@ const KURL& url() const { return m_url; } KURL completeURL(const String&) const; - String userAgent(const KURL&) const final; + String userAgent() const final; void disableEval(const String& errorMessage) final; WorkerScriptController* script() { return m_script.get(); }
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi index 5385346..9264d5d 100644 --- a/third_party/WebKit/Source/devtools/devtools.gypi +++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -787,6 +787,7 @@ 'front_end/Images/responsiveDesign_2x.png', 'front_end/Images/searchNext.png', 'front_end/Images/searchPrev.png', + 'front_end/Images/securityPropertyInfo.svg', 'front_end/Images/securityPropertyInsecure.svg', 'front_end/Images/securityPropertySecure.svg', 'front_end/Images/securityPropertyWarning.svg',
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInfo.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInfo.svg new file mode 100644 index 0000000..edb6b07 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInfo.svg
@@ -0,0 +1,6 @@ +<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> + <g fill="none" fill-rule="evenodd"> + <rect fill="#7f7f7f" x="1" y="1" width="14" height="14" rx="2"/> + <path d="m8.75 12.481l-1.5.019v-6.188h1.5v6.169m-.75-7.481c-.414 0-.75-.336-.75-.75 0-.414.336-.75.75-.75.415 0 .75.336.75.75 0 .414-.335.75-.75.75" fill="#fff"/> + </g> +</svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInsecure.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInsecure.svg index a759a87..c32312b 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInsecure.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyInsecure.svg
@@ -1,67 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="48px" - height="48px" - viewBox="0 0 48 48" - version="1.1" - id="svg2" - inkscape:version="0.91 r13725" - sodipodi:docname="securityPropertyInsecure.svg"> - <metadata - id="metadata13"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10000" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1173" - inkscape:window-height="1491" - id="namedview11" - showgrid="true" - inkscape:snap-global="true" - inkscape:zoom="6.9532167" - inkscape:cx="24" - inkscape:cy="21.966102" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="0" - inkscape:current-layer="svg2"> - <inkscape:grid - type="xygrid" - id="grid4143" /> - </sodipodi:namedview> - <defs - id="defs4" /> - <path - style="fill:#d8463c;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" - d="m 10,33 9,-9 -9,-9 5,-5 9,9 9,-9 5,5 -9,9 9,9 -5,5 -9,-9 -9,9 z" - id="path4145" - inkscape:connector-curvature="0" /> - <g - id="Page-1" - stroke="none" - stroke-width="1" - fill="none" - fill-rule="evenodd" /> -</svg> +<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"> + <path d="m 10 33 9 -9 -9 -9 5 -5 9 9 9 -9 5 5 -9 9 9 9 -5 5 -9 -9 -9 9 z" fill="#d8463c" fill-rule="evenodd"/> +</svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertySecure.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertySecure.svg index 51f66be..01b9bfd 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertySecure.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertySecure.svg
@@ -1,65 +1,3 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - fill="#000000" - height="24" - viewBox="0 0 24 24" - width="24" - id="svg2" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="securityPropertySecure.svg"> - <metadata - id="metadata12"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <defs - id="defs10" /> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1643" - inkscape:window-height="853" - id="namedview8" - showgrid="true" - inkscape:zoom="17.13151" - inkscape:cx="-1.5254237" - inkscape:cy="12" - inkscape:window-x="1245" - inkscape:window-y="786" - inkscape:window-maximized="0" - inkscape:current-layer="svg2"> - <inkscape:grid - type="xygrid" - id="grid4140" /> - </sodipodi:namedview> - <circle - style="fill:#1ac222;fill-opacity:1" - id="path4142" - cx="12" - cy="12" - r="7" /> - <path - d="M0 0h24v24H0z" - fill="none" - id="path4" /> -</svg> +<svg fill="#000000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" fill="#1ac222" r="7"/> +</svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyWarning.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyWarning.svg index a1cf24b..1037fde 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyWarning.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityPropertyWarning.svg
@@ -1,78 +1,5 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="48px" - height="48px" - viewBox="0 0 48 48" - version="1.1" - id="svg2" - inkscape:version="0.91 r13725" - sodipodi:docname="securityPropertyWarning.svg"> - <metadata - id="metadata14"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1487" - inkscape:window-height="840" - id="namedview12" - showgrid="true" - inkscape:zoom="7.4692757" - inkscape:cx="21.565556" - inkscape:cy="24" - inkscape:window-x="1232" - inkscape:window-y="751" - inkscape:window-maximized="0" - inkscape:current-layer="svg2"> - <inkscape:grid - type="xygrid" - id="grid4142" /> - </sodipodi:namedview> - <defs - id="defs4" /> - <g - id="Page-1" - stroke="none" - stroke-width="1" - fill="none" - fill-rule="evenodd"> - <g - id="Material" - transform="translate(-64.000000, 0.000000)"> - <g - id="ic_change_history_black_48px" - transform="translate(64.000000, 0.000000)"> - <path - d="m 24,11.818633 -15.2267073,24.362734 30.4534143,0 L 24,11.818633 Z" - id="Shape" - inkscape:connector-curvature="0" - style="fill:#ffb003" - sodipodi:nodetypes="ccccc" /> - <path - d="M0,0 L48,0 L48,48 L0,48 L0,0 L0,0 Z" - id="path10" /> - </g> - </g> +<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"> + <g fill="none" fill-rule="evenodd"> + <path d="m 24 11.819 -15.227 24.363 30.453 0 L 24 11.819" fill="#ffb003"/> </g> -</svg> +</svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityStateInsecure.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityStateInsecure.svg index f9ab88e..1f17f294 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityStateInsecure.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityStateInsecure.svg
@@ -1,17 +1,10 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="96px" height="96px" viewBox="0 0 96 96" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="omnibox-icons" transform="translate(-2988.000000, -1022.000000)"> - <g id="Notes" transform="translate(328.000000, 139.000000)"></g> - <g id="omnibox_https_invalid-xxxhdpi" transform="translate(2988.000000, 1022.000000)"> - <g id="icon" transform="translate(8.000000, 8.000000)"> - <rect id="Rectangle-22" fill="#FFFFFF" x="10" y="4" width="60" height="70"></rect> - <path d="M45.5,42.016 L40.1,47.416 L34.688,42.004 L32.184,44.504 L37.6,49.92 L32.12,55.396 L34.62,57.9 L40.1,52.42 L45.488,57.808 L47.992,55.304 L42.604,49.92 L48.004,44.516 L45.5,42.016" id="Fill-1" fill="#DB4437"></path> - <path d="M30,28 L30,32 L50,32 L50,28 C50,22.423184 45.716,20 40,20 C34.284,20 30,22.423184 30,28 Z" id="Fill-2" fill="#DB4437"></path> - <path d="M73.3333333,0 L6.66666667,0 C2.98333333,0 0,2.98333333 0,6.66666667 L0,73.3333333 C0,77.0166667 2.98333333,80 6.66666667,80 L73.3333333,80 C77.0166667,80 80,77.0166667 80,73.3333333 L80,6.66666667 C80,2.98333333 77.0166667,0 73.3333333,0 L73.3333333,0 Z M54.284,66 L25.716,66 C22.856,66 20,63.144 20,60.284 L20,37.428 C20,34.572 23.14,32 26,32 L26,28 C26,19.428 31.428,16 40,16 C48.572,16 54,19.428 54,28 L54,32 C56.86,32 60,34.572 60,37.428 L60,60.284 C60,63.144 57.144,66 54.284,66 Z" id="Fill-3" fill="#DB4437"></path> - </g> - </g> - </g> +<svg viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg"> + <g fill="none" fill-rule="evenodd" transform="translate(8 8)"> + <path d="M 10,4 H70 V74 H10 z" fill="#fff"/> + <g fill="#db4437"> + <path d="M 45.5 42.02 L 40.1 47.42 L 34.688 42 L 32.18 44.504 L 37.6 49.92 L 32.12 55.4 L 34.62 57.9 L 40.1 52.42 L 45.49 57.808 L 47.992 55.3 L 42.604 49.92 L 48 44.516 L 45.5 42.02"/> + <path d="M 30 28 L 30 32 L 50 32 L 50 28 C 50 22.423 45.716 20 40 20 C 34.28 20 30 22.423 30 28"/> + <path d="M 73.33 0 L 6.667 0 C 2.983 0 0 2.983 0 6.667 L 0 73.33 C 0 77.02 2.983 80 6.667 80 L 73.33 80 C 77.02 80 80 77.02 80 73.33 L 80 6.667 C 80 2.983 77.02 0 73.33 0 M 54.28 66 L 25.716 66 C 22.856 66 20 63.14 20 60.28 L 20 37.428 C 20 34.572 23.14 32 26 32 L 26 28 C 26 19.428 31.428 16 40 16 C 48.572 16 54 19.428 54 28 L 54 32 C 56.86 32 60 34.572 60 37.428 L 60 60.28 C 60 63.14 57.14 66 54.28 66"/> </g> + </g> </svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityStateNeutral.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityStateNeutral.svg index d8624e6..a295722 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityStateNeutral.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityStateNeutral.svg
@@ -1,11 +1,5 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="96px" height="96px" viewBox="0 0 96 96" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="omnibox-icons" transform="translate(-3530.000000, -1022.000000)" fill="#5A5A5A"> - <g id="omnibox_http-xxxhdpi" transform="translate(3530.000000, 1022.000000)"> - <path d="M52,20 L28,20 L28,76 L68,76 L68,36 L52,20 L52,20 Z M62,36 L52,36 L52,26 L62,36 L62,36 Z M64,72 L32,72 L32,24 L48,24 L48,40 L64,40 L64,72 L64,72 Z" id="Imported-Layers"></path> - </g> - </g> - </g> +<svg viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg"> + <g fill="none" fill-rule="evenodd"> + <path d="M 52 20 L 28 20 L 28 76 L 68 76 L 68 36 L 52 20 M 62 36 L 52 36 L 52 26 L 62 36 M 64 72 L 32 72 L 32 24 L 48 24 L 48 40 L 64 40 L 64 72" fill="#5a5a5a"/> + </g> </svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/securityStateSecure.svg b/third_party/WebKit/Source/devtools/front_end/Images/securityStateSecure.svg index 6d51175..c573dda2 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/securityStateSecure.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/securityStateSecure.svg
@@ -1,17 +1,10 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="96px" height="96px" viewBox="0 0 96 96" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="omnibox-icons" transform="translate(-3124.000000, -1022.000000)"> - <g id="Notes" transform="translate(328.000000, 139.000000)"></g> - <g id="omnibox_https_valid-xxxhdpi" transform="translate(3124.000000, 1022.000000)"> - <g id="icon" transform="translate(8.000000, 8.000000)"> - <rect id="Rectangle-23" fill="#FFFFFF" x="10" y="6" width="60" height="70"></rect> - <path d="M30,28.0000001 L30,31.9999996 L50,32 C50,32 50.0029864,28.1279148 50,28 C49.8723774,22.5336524 45.5853016,20 40,20 C34.284,20 30,22.2880001 30,28.0000001 Z" id="Fill-1" fill="#1AC222"></path> - <path d="M40,40.284 C36.844,40.284 34.284,42.929413 34.284,46.1907112 C34.284,48.3690434 35.44,50.2539001 37.144,51.2748642 L37.144,58 L42.856,58 L42.856,51.2748642 C44.56,50.2539001 45.716,48.3690434 45.716,46.1907112 C45.716,42.929413 43.156,40.284 40,40.284" id="Fill-2" fill="#1AC222"></path> - <path d="M73.3333333,0 L6.66666667,0 C2.98333333,0 0,2.98333333 0,6.66666667 L0,73.3333333 C0,77.0166667 2.98333333,80 6.66666667,80 L73.3333333,80 C77.0166667,80 80,77.0166667 80,73.3333333 L80,6.66666667 C80,2.98333333 77.0166667,0 73.3333333,0 L73.3333333,0 Z M54.284,66 L25.716,66 C22.856,66 20,63.144 20,60.284 L20,37.428 C20,34.572 23.14,32 26,32 L26,28 C26,19.428 31.428,16 40,16 C48.572,16 54,19.428 54,28 L54,32 C56.86,32 60,34.572 60,37.428 L60,60.284 C60,63.144 57.144,66 54.284,66 Z" id="Fill-3" fill="#1AC222"></path> - </g> - </g> - </g> +<svg viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg"> + <g fill="none" fill-rule="evenodd" transform="translate(8 8)"> + <path d="M 10,6 H70 V76 H10 z" fill="#fff"/> + <g fill="#1ac222"> + <path d="M 30 28 L 30 32 L 50 32 C 50 32 50 28.13 50 28 C 49.872 22.534 45.585 20 40 20 C 34.28 20 30 22.288 30 28"/> + <path d="M 40 40.28 C 36.844 40.28 34.28 42.929 34.28 46.19 C 34.28 48.37 35.44 50.25 37.14 51.27 L 37.14 58 L 42.856 58 L 42.856 51.27 C 44.56 50.25 45.716 48.37 45.716 46.19 C 45.716 42.929 43.16 40.28 40 40.28"/> + <path d="M 73.33 0 L 6.667 0 C 2.983 0 0 2.983 0 6.667 L 0 73.33 C 0 77.02 2.983 80 6.667 80 L 73.33 80 C 77.02 80 80 77.02 80 73.33 L 80 6.667 C 80 2.983 77.02 0 73.33 0 M 54.28 66 L 25.716 66 C 22.856 66 20 63.14 20 60.28 L 20 37.428 C 20 34.572 23.14 32 26 32 L 26 28 C 26 19.428 31.428 16 40 16 C 48.572 16 54 19.428 54 28 L 54 32 C 56.86 32 60 34.572 60 37.428 L 60 60.28 C 60 63.14 57.14 66 54.28 66"/> </g> + </g> </svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/serviceWorker.svg b/third_party/WebKit/Source/devtools/front_end/Images/serviceWorker.svg index 48443da..ec977b1 100644 --- a/third_party/WebKit/Source/devtools/front_end/Images/serviceWorker.svg +++ b/third_party/WebKit/Source/devtools/front_end/Images/serviceWorker.svg
@@ -1,70 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="24" - height="24" - viewBox="0 0 24 24" - id="svg2" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="gears.svg"> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1178" - id="namedview8" - showgrid="false" - inkscape:zoom="28.90299" - inkscape:cx="5.2826799" - inkscape:cy="11.738532" - inkscape:window-x="-8" - inkscape:window-y="-8" - inkscape:window-maximized="1" - inkscape:current-layer="svg2" /> - <metadata - id="metadata12"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> - </cc:Work> - </rdf:RDF> - </metadata> - <defs - id="defs10" /> - <path - id="path4" - fill="none" - d="M0 0h24v24h-24z" /> - <g - id="g4892" - transform="translate(10.431484,15.449824)" - inkscape:label="Gear10"> - <path - style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1" - d="M 7.8535156,6.9628906 6.8769531,7.2792969 6.8574219,8.6171875 6.8886719,8.7050781 7.3984375,9.6992188 6.1875,10.578125 5.3984375,9.7871094 5.3261719,9.7304688 4.046875,9.3359375 3.4433594,10.166016 l 0.7695312,1.09375 0.078125,0.05273 0.9960938,0.503906 -0.4628906,1.423828 -1.1035157,-0.175781 -0.091797,-0.0039 -1.265625,0.431641 0,1.027343 1.265625,0.433594 0.091797,-0.0039 1.1035157,-0.177735 0.4628906,1.423828 -0.9960938,0.50586 -0.078125,0.05078 -0.7695312,1.09375 0.6035156,0.830078 1.2792969,-0.392578 0.072266,-0.05859 0.7890625,-0.791015 1.2109375,0.878906 -0.5097656,0.996094 -0.03125,0.08594 0.019531,1.337891 0.9765625,0.316406 0.8027344,-1.068359 0.025391,-0.08984 0.171875,-1.103516 1.4980468,0 0.171876,1.103516 0.02539,0.08984 0.802734,1.068359 0.976563,-0.316406 0.01953,-1.337891 -0.03125,-0.08594 -0.509765,-0.996094 1.210937,-0.878906 0.789063,0.791015 0.07226,0.05859 1.279297,0.392578 0.603516,-0.830078 -0.771485,-1.09375 -0.07617,-0.05078 -0.996093,-0.50586 0.460937,-1.423828 1.105469,0.177735 0.0918,0.0039 1.265625,-0.433594 0,-1.027343 -1.265625,-0.431641 -0.0918,0.0039 -1.105469,0.175781 -0.460937,-1.423828 0.996093,-0.503906 0.07617,-0.05273 0.771485,-1.09375 -0.603516,-0.8300785 -1.279297,0.3945313 -0.07226,0.056641 -0.789063,0.7910152 -1.210937,-0.8789058 0.509765,-0.9941407 0.03125,-0.087891 -0.01953,-1.3378906 -0.976563,-0.3164063 -0.802734,1.0703125 -0.02539,0.087891 -0.171876,1.1054687 -1.4980468,0 L 8.6816406,8.1210938 8.65625,8.0332031 7.8535156,6.9628906 Z m 1.7480469,3.3984374 a 3.620795,3.6452599 0 0 1 3.6210935,3.644531 3.620795,3.6452599 0 0 1 -3.6210935,3.646485 3.620795,3.6452599 0 0 1 -3.6191406,-3.646485 3.620795,3.6452599 0 0 1 3.6191406,-3.644531 z" - transform="translate(-9.8960245,-14.103976)" - id="path4894" - inkscape:connector-curvature="0" /> - </g> - <path - style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.89853436" - d="M 14.884766 1.5625 L 14.177734 1.9570312 L 14.365234 3.2402344 L 14.396484 3.2792969 L 15.140625 4.0429688 L 14.552734 5.0273438 L 13.529297 4.7363281 L 13.478516 4.7285156 L 12.261719 5.171875 L 12.25 5.9804688 L 13.455078 6.4589844 L 13.505859 6.453125 L 14.537109 6.1894531 L 15.097656 7.1914062 L 14.332031 7.9316406 L 14.300781 7.9707031 L 14.076172 9.2480469 L 14.771484 9.6621094 L 15.787109 8.859375 L 15.806641 8.8105469 L 16.095703 7.7871094 L 17.242188 7.8027344 L 17.501953 8.8339844 L 17.519531 8.8828125 L 18.513672 9.7148438 L 19.21875 9.3203125 L 19.03125 8.0371094 L 19 7.9980469 L 18.257812 7.234375 L 18.84375 6.25 L 19.869141 6.5410156 L 19.919922 6.5507812 L 21.136719 6.1054688 L 21.148438 5.296875 L 19.943359 4.8183594 L 19.892578 4.8242188 L 18.861328 5.0878906 L 18.300781 4.0859375 L 19.066406 3.3457031 L 19.097656 3.3066406 L 19.322266 2.0292969 L 18.626953 1.6152344 L 17.609375 2.4179688 L 17.589844 2.4667969 L 17.302734 3.4902344 L 16.15625 3.4746094 L 15.896484 2.4433594 L 15.878906 2.3945312 L 14.884766 1.5625 z M 16.699219 3.7011719 A 1.9375159 1.9375159 0 0 1 18.636719 5.6386719 A 1.9375159 1.9375159 0 0 1 16.699219 7.5761719 A 1.9375159 1.9375159 0 0 1 14.761719 5.6386719 A 1.9375159 1.9375159 0 0 1 16.699219 3.7011719 z " - id="path7649" /> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g stroke="#000"><path d="M 7.854 6.963 6.877 7.279 6.857 8.617 6.889 8.705 7.398 9.699 6.188 10.578 5.398 9.787 5.326 9.73 4.047 9.336 3.443 10.166 l 0.77 1.094 0.078 0.053 0.996 0.504 -0.463 1.424 -1.104 -0.176 -0.092 -0.004 -1.266 0.432 0 1.027 1.266 0.434 0.092 -0.004 1.104 -0.178 0.463 1.424 -0.996 0.506 -0.078 0.051 -0.77 1.094 0.604 0.83 1.279 -0.393 0.072 -0.059 0.789 -0.791 1.211 0.879 -0.51 0.996 -0.031 0.086 0.02 1.338 0.977 0.316 0.803 -1.068 0.025 -0.09 0.172 -1.104 1.498 0 0.172 1.104 0.025 0.09 0.803 1.068 0.977 -0.316 0.02 -1.338 -0.031 -0.086 -0.51 -0.996 1.211 -0.879 0.789 0.791 0.072 0.059 1.279 0.393 0.604 -0.83 -0.771 -1.094 -0.076 -0.051 -0.996 -0.506 0.461 -1.424 1.105 0.178 0.092 0.004 1.266 -0.434 0 -1.027 -1.266 -0.432 -0.092 0.004 -1.105 0.176 -0.461 -1.424 0.996 -0.504 0.076 -0.053 0.771 -1.094 -0.604 -0.83 -1.279 0.395 -0.072 0.057 -0.789 0.791 -1.211 -0.879 0.51 -0.994 0.031 -0.088 -0.02 -1.338 -0.977 -0.316 -0.803 1.07 -0.025 0.088 -0.172 1.105 -1.498 0 L 8.682 8.121 8.656 8.03 7.854 6.963 m 1.748 3.398 a 3.621 3.645 0 0 1 3.621 3.645 3.621 3.645 0 0 1 -3.621 3.646 3.621 3.645 0 0 1 -3.619 -3.646 3.621 3.645 0 0 1 3.619 -3.645 z" transform="translate(0.535 1.346)"/><path d="M 14.885 1.563 L 14.178 1.957 L 14.365 3.24 L 14.396 3.279 L 15.14 4.04 L 14.553 5.03 L 13.529 4.736 L 13.479 4.729 L 12.262 5.172 L 12.25 5.98 L 13.455 6.459 L 13.506 6.453 L 14.537 6.189 L 15.1 7.191 L 14.332 7.932 L 14.301 7.971 L 14.08 9.248 L 14.771 9.662 L 15.787 8.859 L 15.807 8.811 L 16.1 7.787 L 17.242 7.803 L 17.502 8.834 L 17.52 8.883 L 18.514 9.715 L 19.219 9.32 L 19.03 8.04 L 19 7.998 L 18.258 7.234 L 18.844 6.25 L 19.869 6.541 L 19.92 6.551 L 21.14 6.105 L 21.15 5.297 L 19.943 4.818 L 19.893 4.824 L 18.861 5.088 L 18.301 4.086 L 19.07 3.346 L 19.1 3.307 L 19.322 2.029 L 18.627 1.615 L 17.609 2.418 L 17.59 2.467 L 17.303 3.49 L 16.16 3.475 L 15.896 2.443 L 15.879 2.395 L 14.885 1.563 z M 16.699 3.701 A 1.938 1.938 0 0 1 18.637 5.639 A 1.938 1.938 0 0 1 16.699 7.576 A 1.938 1.938 0 0 1 14.762 5.639 A 1.938 1.938 0 0 1 16.699 3.701 z" stroke-width="0.899"/></g></svg> \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js index af35e204..61a8cd4 100644 --- a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js +++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js
@@ -189,7 +189,8 @@ createInfo: function(textContent, className) { var classNameOrDefault = className || "info"; - this.element.createChild("div", classNameOrDefault).textContent = info; + var info = this.element.createChild("div", classNameOrDefault); + info.textContent = textContent; return info; }, @@ -390,7 +391,7 @@ }; /** - * @param {!AccessibilityAgent.AXValueType} type + * @param {?AccessibilityAgent.AXValueType} type * @param {string} value * @return {!Element} */ @@ -398,7 +399,7 @@ { var valueElement; var AXValueType = AccessibilityAgent.AXValueType; - if (type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) + if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) valueElement = createElement("span"); else valueElement = createElementWithClass("span", "monospace"); @@ -415,7 +416,7 @@ valueText = String(value); } - if (type in WebInspector.AXNodePropertyTreeElement.TypeStyles) + if (type && type in WebInspector.AXNodePropertyTreeElement.TypeStyles) valueElement.classList.add(WebInspector.AXNodePropertyTreeElement.TypeStyles[type]); valueElement.setTextContentTruncatedIfNeeded(valueText || ""); @@ -484,7 +485,7 @@ this.appendChild(child); } } - var valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, value.value); + var valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, String(value.value)); this.listItemElement.appendChild(valueElement); }, @@ -514,7 +515,6 @@ /** * @param {!AccessibilityAgent.AXValue} value - * @return {!Element} */ appendRelatedNodeListValueElement: function(value) { @@ -538,14 +538,16 @@ } relatedNodes.some(matchesIDRef); if (matchingNode) { - var deferredNode = new WebInspector.DeferredDOMNode(this._target, matchingNode.backendNodeId); - var child = new WebInspector.AXRelatedNodeTreeElement({ deferredNode: deferredNode }, matchingNode); + var relatedNode = /** @type {!AccessibilityAgent.AXRelatedNode} */ (matchingNode); + var backendNodeId = matchingNode.backendNodeId; + var deferredNode = new WebInspector.DeferredDOMNode(this._target, backendNodeId); + var child = new WebInspector.AXRelatedNodeTreeElement({ deferredNode: deferredNode, idref: idref }, relatedNode); this.appendChild(child); } else { this.appendChild(new WebInspector.AXRelatedNodeTreeElement({ idref: idref })); } } - valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, value.value); + valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, String(value.value)); } else { for (var i = 0; i < numNodes; i++) { var relatedNode = relatedNodes[i]; @@ -554,7 +556,7 @@ this.appendChild(child); } var numNodesString = "(" + numNodes + (numNodes === 1 ? " node" : " nodes") + ")"; - valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement("pseudo", numNodesString); + valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(null, numNodesString); } if (relatedNodes.length <= 3) this.expand(); @@ -607,7 +609,8 @@ /** * @constructor * @extends {WebInspector.AXNodePropertyTreeElement} - * @param {!AccessibilityAgent.AXValueSource} + * @param {!AccessibilityAgent.AXValueSource} source + * @param {!WebInspector.Target} target */ WebInspector.AXValueSourceTreeElement = function(source, target) { @@ -663,19 +666,19 @@ this.listItemElement.appendChild(nameElement); }, - /** @override */ _update: function() { this.listItemElement.removeChildren(); - this.appendSourceNameElement(this._source); - if (this._source.invalid) { - this.listItemElement.appendChild(WebInspector.AccessibilitySidebarView.createExclamationMark()); + var exclamationMark = WebInspector.AccessibilitySidebarView.createExclamationMark(WebInspector.UIString("Invalid source.")); + this.listItemElement.appendChild(exclamationMark); this.listItemElement.classList.add("ax-value-source-invalid"); } else if (this._source.superseded) { this.listItemElement.classList.add("ax-value-source-unused"); } + this.appendSourceNameElement(this._source); + this.listItemElement.createChild("span", "separator").textContent = ": "; if (this._source.value) { @@ -695,8 +698,8 @@ /** * @constructor * @extends {TreeElement} - * @param {{deferredNode: !WebInspector.DeferredDOMNode, idref: string}} node - * @param {!AXRelatedNode=} value + * @param {{deferredNode: (!WebInspector.DeferredDOMNode|undefined), idref: (string|undefined)}} node + * @param {!AccessibilityAgent.AXRelatedNode=} value */ WebInspector.AXRelatedNodeTreeElement = function(node, value) { @@ -728,7 +731,7 @@ valueElement = createElement("span"); this.listItemElement.appendChild(valueElement); this._deferredNode.resolve(onNodeResolved); - } else { + } else if (this._idref) { this.listItemElement.classList.add("invalid"); valueElement = WebInspector.AccessibilitySidebarView.createExclamationMark(WebInspector.UIString("No node with this ID.")); valueElement.createTextChild(this._idref); @@ -736,7 +739,7 @@ this.listItemElement.appendChild(valueElement); if (this._value && this._value.text) { var textElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(AccessibilityAgent.AXValueType.ComputedString, this._value.text); - this.listItemElement.appendChild(document.createTextNode(" ")); + this.listItemElement.createTextChild(" "); this.listItemElement.appendChild(textElement); } }, @@ -791,7 +794,7 @@ var value = this._property.value; if (value.type === AccessibilityAgent.AXValueType.Idref) - this._valueElement = this.appendRelationshipValueElement(value, this._target); + this.appendRelationshipValueElement(value); }, __proto__: WebInspector.AXNodePropertyTreeElement.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/common/ModuleExtensionInterfaces.js b/third_party/WebKit/Source/devtools/front_end/common/ModuleExtensionInterfaces.js index d9d614b..c1e5276 100644 --- a/third_party/WebKit/Source/devtools/front_end/common/ModuleExtensionInterfaces.js +++ b/third_party/WebKit/Source/devtools/front_end/common/ModuleExtensionInterfaces.js
@@ -96,8 +96,9 @@ WebInspector.App.prototype = { /** * @param {!Document} document + * @param {function()} callback */ - presentUI: function(document) { } + presentUI: function(document, callback) { } } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js index 3da5053b7..146a4bd 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
@@ -14,6 +14,11 @@ */ WebInspector.EventListener.frameworkEventListeners = function(object) { + if (!object.target().isPage()) { + // TODO(kozyatinskiy): figure out how this should work for |window|. + return Promise.resolve(/** @type {!WebInspector.FrameworkEventListenersObject} */ ({eventListeners: [], internalHandlers: null})); + } + var listenersResult = /** @type {!WebInspector.FrameworkEventListenersObject} */({eventListeners: []}); return object.callFunctionPromise(frameworkEventListeners, undefined) .then(assertCallFunctionResult)
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 93dbcdd..1efc891 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -244,6 +244,8 @@ this.nameElement.classList.add("object-properties-section-dimmed"); if (this.property.isAccessorProperty()) this.nameElement.classList.add("properties-accessor-property-name"); + if (this.property.synthetic) + this.nameElement.classList.add("synthetic-property"); if (this.property.symbol) this.nameElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property.symbol), false);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css b/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css index 4b573c40..002d4e6 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css +++ b/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css
@@ -47,3 +47,6 @@ padding-left: 0px; } +.object-properties-section .synthetic-property { + font-style: italic; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/main/AdvancedApp.js b/third_party/WebKit/Source/devtools/front_end/main/AdvancedApp.js index 89cf77d2..72bcb82 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/AdvancedApp.js +++ b/third_party/WebKit/Source/devtools/front_end/main/AdvancedApp.js
@@ -13,10 +13,11 @@ WebInspector.AdvancedApp.prototype = { /** - * @param {!Document} document * @override + * @param {!Document} document + * @param {function()} callback */ - presentUI: function(document) + presentUI: function(document, callback) { var rootView = new WebInspector.RootView(); @@ -26,9 +27,8 @@ this._rootSplitWidget.setSidebarWidget(WebInspector.inspectorView); this._inspectedPagePlaceholder = new WebInspector.InspectedPagePlaceholder(); - this._inspectedPagePlaceholder.addEventListener(WebInspector.InspectedPagePlaceholder.Events.Update, this._onSetInspectedPageBounds.bind(this, false), this); + this._inspectedPagePlaceholder.addEventListener(WebInspector.InspectedPagePlaceholder.Events.Update, this._onSetInspectedPageBounds.bind(this), this); this._responsiveDesignView = new WebInspector.ResponsiveDesignView(this._inspectedPagePlaceholder); - this._rootSplitWidget.setMainWidget(this._responsiveDesignView); WebInspector.dockController.addEventListener(WebInspector.DockController.Events.BeforeDockSideChanged, this._onBeforeDockSideChange, this); WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._onDockSideChange, this); @@ -39,6 +39,11 @@ console.timeStamp("AdvancedApp.attachToBody"); rootView.attachToDocument(document); this._inspectedPagePlaceholder.update(); + + if (this._isDocked()) + callback(); + else + this._presentUICallback = callback; }, /** @@ -66,30 +71,27 @@ WebInspector.ContextMenu.installHandler(toolboxDocument); WebInspector.Tooltip.installHandler(toolboxDocument); - var rootView = new WebInspector.RootView(); - var inspectedPagePlaceholder = new WebInspector.InspectedPagePlaceholder(); - inspectedPagePlaceholder.addEventListener(WebInspector.InspectedPagePlaceholder.Events.Update, this._onSetInspectedPageBounds.bind(this, true)); - this._toolboxResponsiveDesignView = new WebInspector.ResponsiveDesignView(inspectedPagePlaceholder); - this._toolboxResponsiveDesignView.show(rootView.element); - rootView.attachToDocument(toolboxDocument); + this._toolboxRootView = new WebInspector.RootView(); + this._toolboxRootView.attachToDocument(toolboxDocument); - this._updatePageResizer(); + this._updateResponsiveDesignView(); + + if (this._presentUICallback) { + var callback = this._presentUICallback; + delete this._presentUICallback; + callback(); + } }, - /** - * @return {!InspectorFrontendHostAPI} - */ - inspectorFrontendHost: function() + _updateResponsiveDesignView: function() { - return window.InspectorFrontendHost; - }, - - _updatePageResizer: function() - { - if (this._isDocked()) + if (this._isDocked()) { + this._rootSplitWidget.setMainWidget(this._responsiveDesignView); this._responsiveDesignView.updatePageResizer(); - else if (this._toolboxResponsiveDesignView) - this._toolboxResponsiveDesignView.updatePageResizer(); + } else if (this._toolboxRootView) { + this._responsiveDesignView.show(this._toolboxRootView.element); + this._responsiveDesignView.updatePageResizer(); + } }, /** @@ -97,7 +99,7 @@ */ _onBeforeDockSideChange: function(event) { - if (/** @type {string} */ (event.data.to) === WebInspector.DockController.State.Undocked && this._toolboxResponsiveDesignView) { + if (/** @type {string} */ (event.data.to) === WebInspector.DockController.State.Undocked && this._toolboxRootView) { // Hide inspectorView and force layout to mimic the undocked state. this._rootSplitWidget.hideSidebar(); this._inspectedPagePlaceholder.update(); @@ -111,12 +113,12 @@ */ _onDockSideChange: function(event) { - this._updatePageResizer(); + this._updateResponsiveDesignView(); var toDockSide = event ? /** @type {string} */ (event.data.to) : WebInspector.dockController.dockSide(); if (toDockSide === WebInspector.DockController.State.Undocked) { this._updateForUndocked(); - } else if (this._toolboxResponsiveDesignView && event && /** @type {string} */ (event.data.from) === WebInspector.DockController.State.Undocked) { + } else if (this._toolboxRootView && event && /** @type {string} */ (event.data.from) === WebInspector.DockController.State.Undocked) { // Don't update yet for smooth transition. this._rootSplitWidget.hideSidebar(); } else { @@ -132,11 +134,11 @@ // We may get here on the first dock side change while loading without BeforeDockSideChange. if (!this._changingDockSide) return; - this._changingDockSide = false; if (/** @type {string} */ (event.data.from) === WebInspector.DockController.State.Undocked) { // Restore docked layout in case of smooth transition. this._updateForDocked(/** @type {string} */ (event.data.to)); } + this._changingDockSide = false; this._inspectedPagePlaceholder.update(); }, @@ -165,15 +167,17 @@ }, /** - * @param {boolean} toolbox * @param {!WebInspector.Event} event */ - _onSetInspectedPageBounds: function(toolbox, event) + _onSetInspectedPageBounds: function(event) { - if (this._changingDockSide || (this._isDocked() === toolbox)) + if (this._changingDockSide) return; + var window = this._inspectedPagePlaceholder.element.window(); if (!window.innerWidth || !window.innerHeight) return; + if (!this._inspectedPagePlaceholder.isShowing()) + return; var bounds = /** @type {{x: number, y: number, width: number, height: number}} */ (event.data); console.timeStamp("AdvancedApp.setInspectedPageBounds"); InspectorFrontendHost.setInspectedPageBounds(bounds);
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 6fceb92a..dfaaf2db 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -256,7 +256,7 @@ // It is important to kick controller lifetime after apps are instantiated. WebInspector.dockController.initialize(); console.timeStamp("Main._presentUI"); - app.presentUI(document); + app.presentUI(document, this._didPresentAppUI.bind(this)); if (!Runtime.queryParam("isSharedWorker")) WebInspector.inspectElementModeController = new WebInspector.InspectElementModeController(); @@ -350,15 +350,28 @@ if (this._mainTarget.isServiceWorker()) this._mainTarget.runtimeAgent().run(); - WebInspector.overridesSupport.init(this._mainTarget, overridesReady); + if (this._appUIPresented) + this._initOverrides(); + }, - function overridesReady() - { - if (!WebInspector.dockController.canDock() && WebInspector.overridesSupport.emulationEnabled()) - WebInspector.inspectorView.showViewInDrawer("emulation", true); + _didPresentAppUI: function() + { + this._appUIPresented = true; + if (this._mainTarget) + this._initOverrides(); + }, - target.inspectorAgent().enable(inspectorAgentEnableCallback); - } + _initOverrides: function() + { + WebInspector.overridesSupport.init(this._mainTarget, this._overridesReady.bind(this)); + }, + + _overridesReady: function() + { + if (!WebInspector.dockController.canDock() && WebInspector.overridesSupport.emulationEnabled()) + WebInspector.inspectorView.showViewInDrawer("emulation", true); + + this._mainTarget.inspectorAgent().enable(inspectorAgentEnableCallback); function inspectorAgentEnableCallback() {
diff --git a/third_party/WebKit/Source/devtools/front_end/main/SimpleApp.js b/third_party/WebKit/Source/devtools/front_end/main/SimpleApp.js index 935630b02..fc0046d53 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/SimpleApp.js +++ b/third_party/WebKit/Source/devtools/front_end/main/SimpleApp.js
@@ -12,15 +12,17 @@ WebInspector.SimpleApp.prototype = { /** - * @param {!Document} document * @override + * @param {!Document} document + * @param {function()} callback */ - presentUI: function(document) + presentUI: function(document, callback) { var rootView = new WebInspector.RootView(); WebInspector.inspectorView.show(rootView.element); WebInspector.inspectorView.showInitialPanel(); rootView.attachToDocument(document); + callback(); } };
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js index 685f197f..c0157e2 100644 --- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js +++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
@@ -18,10 +18,11 @@ WebInspector.ScreencastApp.prototype = { /** - * @param {!Document} document * @override + * @param {!Document} document + * @param {function()} callback */ - presentUI: function(document) + presentUI: function(document, callback) { var rootView = new WebInspector.RootView(); @@ -34,6 +35,7 @@ this._rootSplitWidget.setSidebarWidget(WebInspector.inspectorView); WebInspector.inspectorView.showInitialPanel(); rootView.attachToDocument(document); + callback(); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index e2b06674..6524a7b 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -761,7 +761,7 @@ * @param {string} expression * @param {string} sourceURL * @param {boolean} persistScript - * @param {number=} executionContextId + * @param {number} executionContextId * @param {function(!DebuggerAgent.ScriptId=, ?DebuggerAgent.ExceptionDetails=)=} callback */ compileScript: function(expression, sourceURL, persistScript, executionContextId, callback) @@ -786,7 +786,7 @@ /** * @param {!DebuggerAgent.ScriptId} scriptId - * @param {number=} executionContextId + * @param {number} executionContextId * @param {string=} objectGroup * @param {boolean=} doNotPauseOnExceptionsAndMuteConsole * @param {function(?RuntimeAgent.RemoteObject, ?DebuggerAgent.ExceptionDetails=)=} callback
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index 4f54427..da93ec00 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -537,6 +537,12 @@ */ function eventListeners(fulfill, reject) { + if (!this.target().isPage()) { + // TODO(kozyatinskiy): figure out how this should work for |window| when there is no DOMDebugger. + fulfill([]); + return; + } + if (!this._objectId) { reject(null); return; @@ -551,7 +557,8 @@ * @param {!WebInspector.CallFunctionResult} result * @this {WebInspector.RemoteObject} */ - function storeRemoveFunction(result) { + function storeRemoveFunction(result) + { if (!result.wasThrown && result.object) removeFunction = result.object; this.target().domdebuggerAgent().getEventListeners(this._objectId, mycallback.bind(this)); @@ -1096,9 +1103,10 @@ * @param {boolean=} writable * @param {boolean=} isOwn * @param {boolean=} wasThrown + * @param {boolean=} synthetic * @param {?WebInspector.RemoteObject=} symbol */ -WebInspector.RemoteObjectProperty = function(name, value, enumerable, writable, isOwn, wasThrown, symbol) +WebInspector.RemoteObjectProperty = function(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic) { this.name = name; if (value !== null) @@ -1109,6 +1117,7 @@ this.wasThrown = !!wasThrown; if (symbol) this.symbol = symbol; + this.synthetic = !!synthetic; } WebInspector.RemoteObjectProperty.prototype = {
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 886e5cd1..db71d54 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -197,7 +197,7 @@ * @constructor * @extends {WebInspector.SDKObject} * @param {!WebInspector.Target} target - * @param {number|undefined} id + * @param {number} id * @param {string} name * @param {string} origin * @param {boolean} isPageContext
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js index 26d0ed7..24a0239 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -175,7 +175,8 @@ var oldSecurityState = originState.securityState; originState.securityState = this._securityStateMin(oldSecurityState, securityState); if (oldSecurityState != originState.securityState) { - originState.sidebarElement.setSecurityState(securityState); + this._sidebarOriginSection.removeChild(originState.sidebarElement); + this._insertOriginViewSidebarTreeElementSorted(originState.sidebarElement, securityState); if (originState.originView) originState.originView.setSecurityState(securityState); } @@ -193,14 +194,24 @@ this._origins.set(origin, originState); originState.sidebarElement = new WebInspector.SecurityOriginViewSidebarTreeElement(this, origin); - this._sidebarOriginSection.appendChild(originState.sidebarElement); - originState.sidebarElement.setSecurityState(securityState); + this._insertOriginViewSidebarTreeElementSorted(originState.sidebarElement, securityState); // Don't construct the origin view yet (let it happen lazily). } }, /** + * @param {!WebInspector.SecurityOriginViewSidebarTreeElement} sidebarElement + * @param {!SecurityAgent.SecurityState} securityState + */ + _insertOriginViewSidebarTreeElementSorted: function(sidebarElement, securityState) + { + sidebarElement.setSecurityState(securityState); + var originSectionChildList = /** @type {!Array.<!WebInspector.SecurityOriginViewSidebarTreeElement>} */ (this._sidebarOriginSection.children()); + this._sidebarOriginSection.insertChild(sidebarElement, originSectionChildList.upperBound(sidebarElement, WebInspector.SecurityOriginViewSidebarTreeElement.SecurityStateComparator)); + }, + + /** * @param {!WebInspector.Event} event */ _onRequestFinished: function(event) @@ -368,6 +379,7 @@ { this._panel = panel; this._origin = origin; + this._securityState = SecurityAgent.SecurityState.Unknown; this.small = true; WebInspector.SidebarTreeElement.call(this, "security-sidebar-tree-item", origin); this.iconElement.classList.add("security-property"); @@ -389,18 +401,56 @@ */ setSecurityState: function(newSecurityState) { - for (var className of Array.prototype.slice.call(this.iconElement.classList)) { - if (className.startsWith("security-property-")) - this.iconElement.classList.remove(className); - } + if (this._securityState) + this.iconElement.classList.remove("security-property-" + this._securityState) + this._securityState = newSecurityState; this.iconElement.classList.add("security-property-" + newSecurityState); }, + /** + * @return {!SecurityAgent.SecurityState} + */ + securityState: function() + { + return this._securityState; + }, + __proto__: WebInspector.SidebarTreeElement.prototype } /** + * @param {!WebInspector.SecurityOriginViewSidebarTreeElement} a + * @param {!WebInspector.SecurityOriginViewSidebarTreeElement} b + * @return {number} + */ +WebInspector.SecurityOriginViewSidebarTreeElement.SecurityStateComparator = function(a, b) +{ + var securityStateMap; + if (WebInspector.SecurityOriginViewSidebarTreeElement._symbolicToNumericSecurityState) { + securityStateMap = WebInspector.SecurityOriginViewSidebarTreeElement._symbolicToNumericSecurityState; + } else { + securityStateMap = new Map(); + var ordering = [ + SecurityAgent.SecurityState.Unknown, + SecurityAgent.SecurityState.Info, + SecurityAgent.SecurityState.Insecure, + SecurityAgent.SecurityState.Neutral, + SecurityAgent.SecurityState.Warning, + SecurityAgent.SecurityState.Secure + ]; + for (var i = 0; i < ordering.length; i++) { + securityStateMap.set(ordering[i], i + 1); + } + WebInspector.SecurityOriginViewSidebarTreeElement._symbolicToNumericSecurityState = securityStateMap; + } + var aScore = securityStateMap.get(a.securityState()) || 0; + var bScore = securityStateMap.get(b.securityState()) || 0; + + return aScore - bScore; +} + +/** * @constructor * @implements {WebInspector.PanelFactory} */
diff --git a/third_party/WebKit/Source/devtools/front_end/security/lockIcon.css b/third_party/WebKit/Source/devtools/front_end/security/lockIcon.css index 1af6749..552a8a6 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/lockIcon.css +++ b/third_party/WebKit/Source/devtools/front_end/security/lockIcon.css
@@ -41,3 +41,7 @@ .security-property-secure { background-image: url(Images/securityPropertySecure.svg); } + +.security-property-info { + background-image: url(Images/securityPropertyInfo.svg); +}
diff --git a/third_party/WebKit/Source/devtools/front_end/security/sidebar.css b/third_party/WebKit/Source/devtools/front_end/security/sidebar.css index d1d8efc..3d007b3 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/sidebar.css +++ b/third_party/WebKit/Source/devtools/front_end/security/sidebar.css
@@ -4,18 +4,29 @@ */ .tree-outline { - padding: 0; + padding: 0; +} + +.tree-outline li.selected .lock-icon-neutral { + background-image: none; + background-color: #5a5a5a; + -webkit-mask-image: url(Images/securityStateNeutral.svg); + -webkit-mask-size: cover; +} + +.tree-outline:focus li.selected .lock-icon-neutral { + background-color: #fff; } .tree-outline .security-main-view-sidebar-tree-item { - border-bottom: 1px solid rgb(230, 230, 230); - padding-top: 0; + border-bottom: 1px solid rgb(230, 230, 230); + padding-top: 0; } .tree-outline .security-main-view-sidebar-tree-item .icon, .tree-outline .security-main-view-sidebar-tree-item .titles { - margin-top: 1.5em; - margin-bottom: 1.5em; + margin-top: 1.5em; + margin-bottom: 1.5em; } .tree-outline .security-sidebar-origins { @@ -25,21 +36,21 @@ color: rgb(90, 90, 90); } .tree-outline ol { - padding-left: 0; + padding-left: 0; } .tree-outline li::before { - content: none; + content: none; } .tree-outline .security-main-view-sidebar-tree-item, .tree-outline .security-sidebar-origins, .tree-outline .sidebar-tree-section + .children > .sidebar-tree-item { - padding-left: 16px; + padding-left: 16px; } .tree-outline .sidebar-tree-item .lock-icon, .tree-outline .sidebar-tree-item .security-property { float: left; margin-right: 2px; -} +} \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js index 2d47e09..a47cec9 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js
@@ -42,7 +42,7 @@ this._createCategory(WebInspector.UIString("Window"), ["close"], true); this._createCategory(WebInspector.UIString("XHR"), ["readystatechange", "load", "loadstart", "loadend", "abort", "error", "progress", "timeout"], false, ["XMLHttpRequest", "XMLHttpRequestUpload"]); - WebInspector.targetManager.observeTargets(this); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); } WebInspector.EventListenerBreakpointsSidebarPane.categoryListener = "listener:"; @@ -231,7 +231,7 @@ */ _updateBreakpointOnTarget: function(eventName, eventTargetName, enable, target) { - var targets = target ? [target] : WebInspector.targetManager.targets(); + var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Type.Page); for (var i = 0; i < targets.length; ++i) { if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener)) { var protocolEventName = eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener.length);
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js index 23850b4..05a061e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js
@@ -49,10 +49,13 @@ var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); if (!debuggerModel) return; + var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext); + if (!currentExecutionContext) + return; this._compiling = true; var code = this._sourceFrame.textEditor.text(); - debuggerModel.compileScript(code, "", false, undefined, compileCallback.bind(this, target)); + debuggerModel.compileScript(code, "", false, currentExecutionContext.id, compileCallback.bind(this, target)); /** * @param {!WebInspector.Target} target
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js index acaaa19..dcf5e146 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js
@@ -89,11 +89,11 @@ if (!callFrame.isAsync()) { var exception = details.exception(); if (exception) - extraProperties.push(new WebInspector.RemoteObjectProperty("<exception>", exception)); + extraProperties.push(new WebInspector.RemoteObjectProperty(WebInspector.UIString.capitalize("Exception"), exception, undefined, undefined, undefined, undefined, undefined, true)); } var returnValue = callFrame.returnValue(); if (returnValue) - extraProperties.push(new WebInspector.RemoteObjectProperty("<return>", returnValue)); + extraProperties.push(new WebInspector.RemoteObjectProperty(WebInspector.UIString.capitalize("Return ^value"), returnValue, undefined, undefined, undefined, undefined, undefined, true)); } break; case DebuggerAgent.ScopeType.Closure:
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js index 8832808..8243eae 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
@@ -21,7 +21,7 @@ this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true); - WebInspector.targetManager.observeTargets(this); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); } WebInspector.XHRBreakpointsSidebarPane.prototype = { @@ -139,7 +139,7 @@ */ _updateBreakpointOnTarget: function(url, enable, target) { - var targets = target ? [target] : WebInspector.targetManager.targets(); + var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Type.Page); for (var i = 0; i < targets.length; ++i) { if (enable) targets[i].domdebuggerAgent().setXHRBreakpoint(url);
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json index 0c32c620..ff4a1b01 100644 --- a/third_party/WebKit/Source/devtools/protocol.json +++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -3782,7 +3782,7 @@ { "name": "expression", "type": "string", "description": "Expression to compile." }, { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." }, { "name": "persistScript", "type": "boolean", "description": "Specifies whether the compiled script should be persisted." }, - { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." } + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." } ], "returns": [ { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." }, @@ -3795,7 +3795,7 @@ "hidden": true, "parameters": [ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." }, - { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." }, + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." }, { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }, { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." } ],
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp index b9f5ee76..8fcfb151 100644 --- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp +++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
@@ -361,7 +361,7 @@ m_peerHandler->setLocalDescription(request, sessionDescription->webSessionDescription()); } -RTCSessionDescription* RTCPeerConnection::localDescription(ExceptionState& exceptionState) +RTCSessionDescription* RTCPeerConnection::localDescription() { WebRTCSessionDescription webSessionDescription = m_peerHandler->localDescription(); if (webSessionDescription.isNull()) @@ -384,7 +384,7 @@ m_peerHandler->setRemoteDescription(request, sessionDescription->webSessionDescription()); } -RTCSessionDescription* RTCPeerConnection::remoteDescription(ExceptionState& exceptionState) +RTCSessionDescription* RTCPeerConnection::remoteDescription() { WebRTCSessionDescription webSessionDescription = m_peerHandler->remoteDescription(); if (webSessionDescription.isNull())
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h index ba53a6b9..9736bd93 100644 --- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h +++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h
@@ -71,10 +71,10 @@ void createAnswer(RTCSessionDescriptionCallback*, RTCErrorCallback*, const Dictionary&, ExceptionState&); void setLocalDescription(RTCSessionDescription*, VoidCallback*, RTCErrorCallback*, ExceptionState&); - RTCSessionDescription* localDescription(ExceptionState&); + RTCSessionDescription* localDescription(); void setRemoteDescription(RTCSessionDescription*, VoidCallback*, RTCErrorCallback*, ExceptionState&); - RTCSessionDescription* remoteDescription(ExceptionState&); + RTCSessionDescription* remoteDescription(); String signalingState() const;
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl index fa54946..719c442 100644 --- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl +++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl
@@ -28,56 +28,106 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://w3c.github.io/webrtc-pc/#state-definitions + +enum RTCSignalingState { + "stable", + "have-local-offer", + "have-remote-offer", + "have-local-pranswer", + "have-remote-pranswer", + "closed" +}; + +enum RTCIceGatheringState { + "new", + "gathering", + "complete" +}; + +enum RTCIceConnectionState { + "new", + "checking", + "connected", + "completed", + "failed", + "disconnected", + "closed" +}; + +// https://w3c.github.io/webrtc-pc/#interface-definition + +// TODO(guidou): Many types are of the wrong type in this interface: +// * Dictionary -> specific dictionary types like RTCConfiguration +// * RTCErrorCallback -> RTCPeerConnectionErrorCallback +// * VoidCallback -> VoidFunction [ GarbageCollected, ActiveDOMObject, + // TODO(guidou): There should only be one constructor argument, and it + // should be optional. Constructor(Dictionary rtcConfiguration, optional Dictionary mediaConstraints), ConstructorCallWith=ExecutionContext, NoInterfaceObject, RaisesException=Constructor, ] interface RTCPeerConnection : EventTarget { - [RaisesException] void createOffer(RTCSessionDescriptionCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback, optional Dictionary rtcOfferOptions); - - [RaisesException] void createAnswer(RTCSessionDescriptionCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback, optional Dictionary mediaConstraints); - - [RaisesException] void setLocalDescription(RTCSessionDescription description, [Default=Undefined] optional VoidCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback); - [RaisesException=Getter] readonly attribute RTCSessionDescription localDescription; - - [RaisesException] void setRemoteDescription(RTCSessionDescription description, [Default=Undefined] optional VoidCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback); - [RaisesException=Getter] readonly attribute RTCSessionDescription remoteDescription; - - readonly attribute DOMString signalingState; - - [RaisesException] void updateIce(optional Dictionary configuration, optional Dictionary mediaConstraints); - - // DEPRECATED + // Promise<RTCSessionDescription> createOffer(optional RTCOfferOptions options); + // Promise<RTCSessionDescription> createAnswer(optional RTCAnswerOptions options); + // Promise<void> setLocalDescription(RTCSessionDescription description); + readonly attribute RTCSessionDescription? localDescription; + // readonly attribute RTCSessionDescription? currentLocalDescription; + // readonly attribute RTCSessionDescription? pendingLocalDescription; + // Promise<void> setRemoteDescription(RTCSessionDescription description); + readonly attribute RTCSessionDescription? remoteDescription; + // readonly attribute RTCSessionDescription? currentRemoteDescription; + // readonly attribute RTCSessionDescription? pendingRemoteDescription; + // TODO(guidou): addIceCandidate() should return a Promise. [RaisesException] void addIceCandidate(RTCIceCandidate candidate); - - [RaisesException] void addIceCandidate(RTCIceCandidate candidate, VoidCallback successCallback, RTCErrorCallback failureCallback); - - readonly attribute DOMString iceGatheringState; - readonly attribute DOMString iceConnectionState; - - sequence<MediaStream> getLocalStreams(); - sequence<MediaStream> getRemoteStreams(); - MediaStream getStreamById(DOMString streamId); - - [TypeChecking=Interface, RaisesException] void addStream(MediaStream? stream, optional Dictionary mediaConstraints); - [TypeChecking=Interface, RaisesException] void removeStream(MediaStream? stream); - - void getStats(RTCStatsCallback successCallback, [Default=Undefined] optional MediaStreamTrack selector); - - [RaisesException] RTCDataChannel createDataChannel([TreatUndefinedAs=NullString] DOMString? label, optional Dictionary options); - - [RaisesException] RTCDTMFSender createDTMFSender(MediaStreamTrack track); - + readonly attribute RTCSignalingState signalingState; + readonly attribute RTCIceGatheringState iceGatheringState; + readonly attribute RTCIceConnectionState iceConnectionState; + // readonly attribute boolean? canTrickleIceCandidates; + // RTCConfiguration getConfiguration(); + // void setConfiguration(RTCConfiguration configuration); + // TODO(guidou): close() should never throw an exception. [RaisesException] void close(); - attribute EventHandler onnegotiationneeded; attribute EventHandler onicecandidate; attribute EventHandler onsignalingstatechange; + attribute EventHandler oniceconnectionstatechange; + // attribute EventHandler onicegatheringstatechange; + + // https://w3c.github.io/webrtc-pc/#legacy-interface-extensions + // TODO(guidou): The failureCallback argument should be non-optional. + [RaisesException] void createOffer(RTCSessionDescriptionCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback, optional Dictionary rtcOfferOptions); + // TODO(guidou): None of the arguments should be optional. + [RaisesException] void setLocalDescription(RTCSessionDescription description, [Default=Undefined] optional VoidCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback); + // TODO(guidou): The failureCallback argument should be non-optional, and + // there should be no mediaConstraints argument. + [RaisesException] void createAnswer(RTCSessionDescriptionCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback, optional Dictionary mediaConstraints); + // TODO(guidou): The successCallback and failureCallback arguments should be + // non-optional. + [RaisesException] void setRemoteDescription(RTCSessionDescription description, [Default=Undefined] optional VoidCallback successCallback, [Default=Undefined] optional RTCErrorCallback failureCallback); + [RaisesException] void addIceCandidate(RTCIceCandidate candidate, VoidCallback successCallback, RTCErrorCallback failureCallback); + // TODO(guidou): The selector argument should the first (nullable, + // non-optional) argument, and there should be a third failureCallback + // argument. + void getStats(RTCStatsCallback successCallback, [Default=Undefined] optional MediaStreamTrack selector); + + // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api + // TODO(guidou): The label argument should have [TreatNullAs=EmptyString] + // and be non-nullable. + [RaisesException] RTCDataChannel createDataChannel([TreatUndefinedAs=NullString] DOMString? label, optional Dictionary options); + attribute EventHandler ondatachannel; + + // Non-standard or removed from the spec: + [RaisesException] void updateIce(optional Dictionary configuration, optional Dictionary mediaConstraints); + sequence<MediaStream> getLocalStreams(); + sequence<MediaStream> getRemoteStreams(); + MediaStream getStreamById(DOMString streamId); + [TypeChecking=Interface, RaisesException] void addStream(MediaStream? stream, optional Dictionary mediaConstraints); + [TypeChecking=Interface, RaisesException] void removeStream(MediaStream? stream); + [RaisesException] RTCDTMFSender createDTMFSender(MediaStreamTrack track); attribute EventHandler onaddstream; attribute EventHandler onremovestream; - attribute EventHandler oniceconnectionstatechange; - attribute EventHandler ondatachannel; };
diff --git a/third_party/WebKit/Source/platform/PlatformMouseEvent.h b/third_party/WebKit/Source/platform/PlatformMouseEvent.h index fc1590a..b6734fae 100644 --- a/third_party/WebKit/Source/platform/PlatformMouseEvent.h +++ b/third_party/WebKit/Source/platform/PlatformMouseEvent.h
@@ -31,7 +31,8 @@ namespace blink { -// These button numbers match the ones used in the DOM API, 0 through 2, except for NoButton which isn't specified. +// These button numbers match the ones used in the DOM API, 0 through 2, except for NoButton which is specified in PointerEvent +// spec but not in MouseEvent spec. enum MouseButton { NoButton = -1, LeftButton, MiddleButton, RightButton }; class PlatformMouseEvent : public PlatformEvent {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.cpp index 431e5a4..babd006d 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.cpp
@@ -195,14 +195,14 @@ return consumedCharacters; } -unsigned SimpleShaper::advance(unsigned offset, GlyphBuffer* glyphBuffer) +unsigned SimpleShaper::advance(int offset, GlyphBuffer* glyphBuffer) { - unsigned length = m_textRun.length(); + int length = m_textRun.length(); if (offset > length) offset = length; - if (m_currentCharacter >= offset) + if (m_currentCharacter >= static_cast<unsigned>(offset)) return 0; if (m_textRun.is8Bit()) {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.h b/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.h index 83235bd9..435fac0 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.h +++ b/third_party/WebKit/Source/platform/fonts/shaping/SimpleShaper.h
@@ -45,7 +45,9 @@ SimpleShaper(const Font*, const TextRun&, const GlyphData* emphasisData = nullptr, HashSet<const SimpleFontData*>* fallbackFonts = nullptr, FloatRect* = nullptr); - unsigned advance(unsigned to, GlyphBuffer* = 0); + // TODO(sk.kumar): This function should be updated to take an unsigned value, and callers + // should be updated to not pass negative values. See: crbug.com/540047. + unsigned advance(int to, GlyphBuffer* = 0); bool advanceOneCharacter(float& width); const TextRun& run() const { return m_textRun; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h index 1e4dfa0..1cdc4369 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h
@@ -23,7 +23,7 @@ private: // CachedDisplayItem is never replayed or appended to WebDisplayItemList. - void replay(GraphicsContext&) final { ASSERT_NOT_REACHED(); } + void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); } void appendToWebDisplayItemList(WebDisplayItemList*) const final { ASSERT_NOT_REACHED(); } };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.cpp index 0839034..de7f052d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.cpp
@@ -12,7 +12,7 @@ namespace blink { -void ClipDisplayItem::replay(GraphicsContext& context) +void ClipDisplayItem::replay(GraphicsContext& context) const { context.save(); context.clipRect(m_clipRect, NotAntiAliased, SkRegion::kIntersect_Op); @@ -42,7 +42,7 @@ list->appendClipItem(m_clipRect, webRoundedRects); } -void EndClipDisplayItem::replay(GraphicsContext& context) +void EndClipDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.h index 421f902..b14fdad4 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipDisplayItem.h
@@ -30,7 +30,7 @@ m_roundedRectClips.swap(roundedRectClips); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private: @@ -58,7 +58,7 @@ ASSERT(isEndClipType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp index ca5b0385..9e89281 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
@@ -12,7 +12,7 @@ namespace blink { -void BeginClipPathDisplayItem::replay(GraphicsContext& context) +void BeginClipPathDisplayItem::replay(GraphicsContext& context) const { context.save(); context.clipPath(m_clipPath, AntiAliased); @@ -23,7 +23,7 @@ list->appendClipPathItem(m_clipPath, SkRegion::kIntersect_Op, true); } -void EndClipPathDisplayItem::replay(GraphicsContext& context) +void EndClipPathDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h index fe48e30..7160d60 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
@@ -19,7 +19,7 @@ : PairedBeginDisplayItem(client, BeginClipPath, sizeof(*this)) , m_clipPath(clipPath.skPath()) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private: @@ -41,7 +41,7 @@ EndClipPathDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndClipPath, sizeof(*this)) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.cpp index d466509..80fd2ad0 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.cpp
@@ -12,7 +12,7 @@ namespace blink { -void BeginCompositingDisplayItem::replay(GraphicsContext& context) +void BeginCompositingDisplayItem::replay(GraphicsContext& context) const { context.beginLayer(m_opacity, m_xferMode, m_hasBounds ? &m_bounds : nullptr, m_colorFilter); } @@ -33,7 +33,7 @@ } #endif -void EndCompositingDisplayItem::replay(GraphicsContext& context) +void EndCompositingDisplayItem::replay(GraphicsContext& context) const { context.endLayer(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.h index 925f955..0f300d6 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingDisplayItem.h
@@ -29,7 +29,7 @@ m_bounds = FloatRect(*bounds); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private: @@ -60,7 +60,7 @@ EndCompositingDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndCompositing, sizeof(*this)) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h index 8084dd7..f7f0890 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -246,7 +246,7 @@ return Id(m_client, nonCachedType(m_type), m_scope); } - virtual void replay(GraphicsContext&) { } + virtual void replay(GraphicsContext&) const { } DisplayItemClient client() const { return m_client; } Type type() const { return m_type; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp index b4b9c84..e58e7015 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -577,11 +577,11 @@ #endif // ifndef NDEBUG -void DisplayItemList::replay(GraphicsContext& context) +void DisplayItemList::replay(GraphicsContext& context) const { TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); ASSERT(m_newDisplayItems.isEmpty()); - for (DisplayItem& displayItem : m_currentDisplayItems) + for (const DisplayItem& displayItem : m_currentDisplayItems) displayItem.replay(context); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h index 482c81a..588e52bd9 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h
@@ -238,7 +238,7 @@ void checkNoRemainingCachedDisplayItems(); #endif - void replay(GraphicsContext&); + void replay(GraphicsContext&) const; DisplayItems m_currentDisplayItems; DisplayItems m_newDisplayItems;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp index a5fb85c..bd85b84 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp
@@ -63,7 +63,7 @@ public: TestDisplayItem(const TestDisplayItemClient& client, Type type) : DisplayItem(client, type, sizeof(*this)) { } - void replay(GraphicsContext&) final { ASSERT_NOT_REACHED(); } + void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); } void appendToWebDisplayItemList(WebDisplayItemList*) const final { ASSERT_NOT_REACHED(); } };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp index e7a79b84..f8bc8deb 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
@@ -17,7 +17,7 @@ namespace blink { -void DrawingDisplayItem::replay(GraphicsContext& context) +void DrawingDisplayItem::replay(GraphicsContext& context) const { if (m_picture) context.drawPicture(m_picture.get());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h index 1cb03e5..a5943d57 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
@@ -38,7 +38,7 @@ ASSERT(isDrawingType(type)); } - virtual void replay(GraphicsContext&); + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; bool drawsContent() const override;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp index ec0f2c36..7360a82 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.cpp
@@ -18,7 +18,7 @@ return filterBounds; } -void BeginFilterDisplayItem::replay(GraphicsContext& context) +void BeginFilterDisplayItem::replay(GraphicsContext& context) const { context.save(); @@ -50,7 +50,7 @@ } #endif -void EndFilterDisplayItem::replay(GraphicsContext& context) +void EndFilterDisplayItem::replay(GraphicsContext& context) const { context.endLayer(); context.restore();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h index 7bbf32bb..4e815a6 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/FilterDisplayItem.h
@@ -24,7 +24,7 @@ , m_webFilterOperations(filterOperations) , m_bounds(bounds) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; bool drawsContent() const override; @@ -52,7 +52,7 @@ EndFilterDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndFilter, sizeof(*this)) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FixedPositionContainerDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/FixedPositionContainerDisplayItem.h index 8669ea9..674214a 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FixedPositionContainerDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/FixedPositionContainerDisplayItem.h
@@ -16,7 +16,7 @@ BeginFixedPositionContainerDisplayItem(const DisplayItemClientWrapper& client) : PairedBeginDisplayItem(client, BeginFixedPositionContainer, sizeof(*this)) { } - void replay(GraphicsContext&) final { } + void replay(GraphicsContext&) const final { } void appendToWebDisplayItemList(WebDisplayItemList*) const final; }; @@ -25,7 +25,7 @@ EndFixedPositionContainerDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndFixedPositionContainer, sizeof(*this)) { } - void replay(GraphicsContext&) final { } + void replay(GraphicsContext&) const final { } void appendToWebDisplayItemList(WebDisplayItemList*) const final; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FixedPositionDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/FixedPositionDisplayItem.h index ce2bf6d..d3810ee 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FixedPositionDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/FixedPositionDisplayItem.h
@@ -17,7 +17,7 @@ BeginFixedPositionDisplayItem(const DisplayItemClientWrapper& client) : PairedBeginDisplayItem(client, BeginFixedPosition, sizeof(*this)) { } - void replay(GraphicsContext&) final { } + void replay(GraphicsContext&) const final { } void appendToWebDisplayItemList(WebDisplayItemList*) const final; }; @@ -26,7 +26,7 @@ EndFixedPositionDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndFixedPosition, sizeof(*this)) { } - void replay(GraphicsContext&) final { } + void replay(GraphicsContext&) const final { } void appendToWebDisplayItemList(WebDisplayItemList*) const final; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.cpp index 619c1c0e..fb3b2348 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.cpp
@@ -11,7 +11,7 @@ namespace blink { -void FloatClipDisplayItem::replay(GraphicsContext& context) +void FloatClipDisplayItem::replay(GraphicsContext& context) const { context.save(); context.clip(m_clipRect); @@ -22,7 +22,7 @@ list->appendFloatClipItem(m_clipRect); } -void EndFloatClipDisplayItem::replay(GraphicsContext& context) +void EndFloatClipDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.h index 0945888..107fe7a 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/FloatClipDisplayItem.h
@@ -23,7 +23,7 @@ ASSERT(isFloatClipType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private: @@ -49,7 +49,7 @@ ASSERT(isEndFloatClipType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.cpp index 77efe28..07f2e90 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.cpp
@@ -11,7 +11,7 @@ namespace blink { -void BeginScrollDisplayItem::replay(GraphicsContext& context) +void BeginScrollDisplayItem::replay(GraphicsContext& context) const { context.save(); context.translate(-m_currentOffset.width(), -m_currentOffset.height()); @@ -31,7 +31,7 @@ } #endif -void EndScrollDisplayItem::replay(GraphicsContext& context) +void EndScrollDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.h index 761c46a..22570355 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollDisplayItem.h
@@ -21,7 +21,7 @@ ASSERT(isScrollType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; const IntSize& currentOffset() const { return m_currentOffset; } @@ -49,7 +49,7 @@ ASSERT(isEndScrollType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.cpp index 16f4435..5c1dca8 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.cpp
@@ -11,7 +11,7 @@ namespace blink { -void BeginTransform3DDisplayItem::replay(GraphicsContext& context) +void BeginTransform3DDisplayItem::replay(GraphicsContext& context) const { TransformationMatrix transform(m_transform); transform.applyTransformOrigin(m_transformOrigin); @@ -45,7 +45,7 @@ } #endif -void EndTransform3DDisplayItem::replay(GraphicsContext& context) +void EndTransform3DDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.h index f2add79..b48eddf4 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/Transform3DDisplayItem.h
@@ -27,7 +27,7 @@ ASSERT(DisplayItem::isTransform3DType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; const TransformationMatrix& transform() const { return m_transform; } @@ -58,7 +58,7 @@ ASSERT(DisplayItem::isEndTransform3DType(type)); } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.cpp index 50da105..8ebd21ff 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.cpp
@@ -11,7 +11,7 @@ namespace blink { -void BeginTransformDisplayItem::replay(GraphicsContext& context) +void BeginTransformDisplayItem::replay(GraphicsContext& context) const { context.save(); context.concatCTM(m_transform); @@ -31,7 +31,7 @@ } #endif -void EndTransformDisplayItem::replay(GraphicsContext& context) +void EndTransformDisplayItem::replay(GraphicsContext& context) const { context.restore(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.h index e29248d9..b2fc9471 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformDisplayItem.h
@@ -17,7 +17,7 @@ : PairedBeginDisplayItem(client, BeginTransform, sizeof(*this)) , m_transform(transform) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; const AffineTransform& transform() const { return m_transform; } @@ -42,7 +42,7 @@ EndTransformDisplayItem(const DisplayItemClientWrapper& client) : PairedEndDisplayItem(client, EndTransform, sizeof(*this)) { } - void replay(GraphicsContext&) override; + void replay(GraphicsContext&) const override; void appendToWebDisplayItemList(WebDisplayItemList*) const override; private:
diff --git a/third_party/WebKit/Source/platform/network/ResourceLoadPriority.h b/third_party/WebKit/Source/platform/network/ResourceLoadPriority.h index b6178b9..2a2b2d3 100644 --- a/third_party/WebKit/Source/platform/network/ResourceLoadPriority.h +++ b/third_party/WebKit/Source/platform/network/ResourceLoadPriority.h
@@ -41,6 +41,24 @@ ResourceLoadPriorityHighest = ResourceLoadPriorityVeryHigh, }; +struct ResourcePriority { +public: + enum VisibilityStatus { + NotVisible, + Visible, + }; + + ResourcePriority() : ResourcePriority(NotVisible, 0) { } + ResourcePriority(VisibilityStatus status, int intraValue) + : visibility(status) + , intraPriorityValue(intraValue) + { + } + + VisibilityStatus visibility; + int intraPriorityValue; +}; + } #endif
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp index d926ef8..4a6c434 100644 --- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp +++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
@@ -680,9 +680,9 @@ return ds.release(); } -String FrameLoaderClientImpl::userAgent(const KURL& url) +String FrameLoaderClientImpl::userAgent() { - WebString override = m_webFrame->client()->userAgentOverride(m_webFrame, WebURL(url)); + WebString override = m_webFrame->client()->userAgentOverride(m_webFrame); if (!override.isEmpty()) return override;
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h index c468e0e..d0b498f7 100644 --- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h +++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
@@ -117,7 +117,7 @@ void didChangePerformanceTiming() override; void selectorMatchChanged(const Vector<String>& addedSelectors, const Vector<String>& removedSelectors) override; PassRefPtrWillBeRawPtr<DocumentLoader> createDocumentLoader(LocalFrame*, const ResourceRequest&, const SubstituteData&) override; - WTF::String userAgent(const KURL&) override; + WTF::String userAgent() override; WTF::String doNotTrackValue() override; void transitionToCommittedForNewPage() override; PassRefPtrWillBeRawPtr<LocalFrame> createFrame(const FrameLoadRequest&, const WTF::AtomicString& name, HTMLFrameOwnerElement*) override;
diff --git a/third_party/WebKit/Source/web/PageWidgetDelegate.cpp b/third_party/WebKit/Source/web/PageWidgetDelegate.cpp index 15ec0acc..68ac44f 100644 --- a/third_party/WebKit/Source/web/PageWidgetDelegate.cpp +++ b/third_party/WebKit/Source/web/PageWidgetDelegate.cpp
@@ -217,4 +217,53 @@ return mainFrame.eventHandler().handleTouchEvent(PlatformTouchEventBuilder(mainFrame.view(), event)); } +// TODO(yoichio): Autogenerate the mapping, note the "mismatch" (GestureScrollBegin). +String PageWidgetEventHandler::inputTypeToName(WebInputEvent::Type type) +{ + switch (type) { + case WebInputEvent::MouseDown: + return EventTypeNames::mousedown; + case WebInputEvent::MouseUp: + return EventTypeNames::mouseup; + case WebInputEvent::MouseMove: + return EventTypeNames::mousemove; + case WebInputEvent::MouseEnter: + return EventTypeNames::mouseenter; + case WebInputEvent::MouseLeave: + return EventTypeNames::mouseleave; + case WebInputEvent::ContextMenu: + return EventTypeNames::contextmenu; + case WebInputEvent::MouseWheel: + return EventTypeNames::mousewheel; + case WebInputEvent::KeyDown: + return EventTypeNames::keydown; + case WebInputEvent::KeyUp: + return EventTypeNames::keyup; + case WebInputEvent::GestureScrollBegin: + return EventTypeNames::gesturescrollstart; + case WebInputEvent::GestureScrollEnd: + return EventTypeNames::gesturescrollend; + case WebInputEvent::GestureScrollUpdate: + return EventTypeNames::gesturescrollupdate; + case WebInputEvent::GestureTapDown: + return EventTypeNames::gesturetapdown; + case WebInputEvent::GestureShowPress: + return EventTypeNames::gestureshowpress; + case WebInputEvent::GestureTap: + return EventTypeNames::gesturetap; + case WebInputEvent::GestureTapUnconfirmed: + return EventTypeNames::gesturetapunconfirmed; + case WebInputEvent::TouchStart: + return EventTypeNames::touchstart; + case WebInputEvent::TouchMove: + return EventTypeNames::touchmove; + case WebInputEvent::TouchEnd: + return EventTypeNames::touchend; + case WebInputEvent::TouchCancel: + return EventTypeNames::touchcancel; + default: + return String("unknown"); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/web/PageWidgetDelegate.h b/third_party/WebKit/Source/web/PageWidgetDelegate.h index be1b728..59860f9 100644 --- a/third_party/WebKit/Source/web/PageWidgetDelegate.h +++ b/third_party/WebKit/Source/web/PageWidgetDelegate.h
@@ -32,6 +32,7 @@ #define PageWidgetDelegate_h #include "public/platform/WebCanvas.h" +#include "public/web/WebInputEvent.h" #include "public/web/WebWidget.h" #include "wtf/OwnPtr.h" @@ -58,6 +59,8 @@ virtual bool handleGestureEvent(const WebGestureEvent&) = 0; virtual bool handleTouchEvent(LocalFrame& mainFrame, const WebTouchEvent&); virtual ~PageWidgetEventHandler() { } +protected: + String inputTypeToName(WebInputEvent::Type); };
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp index 5e5f5469..bddbc3e 100644 --- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp +++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
@@ -140,8 +140,15 @@ m_workerContextClient->workerContextFailedToStart(); return; } - if (m_workerThread) - m_workerThread->terminate(); + if (!m_workerThread) { + // The worker thread has not been created yet if the worker is asked to + // terminate during waiting for debugger. + ASSERT(m_workerStartData.waitForDebuggerMode == WebEmbeddedWorkerStartData::WaitForDebugger); + // This deletes 'this'. + m_workerContextClient->workerContextFailedToStart(); + return; + } + m_workerThread->terminate(); m_workerInspectorProxy->workerThreadTerminated(); }
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp index 12b55f4..3483eef 100644 --- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp +++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp
@@ -75,6 +75,18 @@ ::testing::Mock::VerifyAndClearExpectations(m_mockClient); } +TEST_F(WebEmbeddedWorkerImplFailureTest, TerminateWhileWaitingForDebugger) +{ + EXPECT_CALL(*m_mockClient, workerReadyForInspection()).Times(1); + m_startData.waitForDebuggerMode = WebEmbeddedWorkerStartData::WaitForDebugger; + m_worker->startWorkerContext(m_startData); + ::testing::Mock::VerifyAndClearExpectations(m_mockClient); + + EXPECT_CALL(*m_mockClient, workerContextFailedToStart()).Times(1); + m_worker->terminateWorkerContext(); + ::testing::Mock::VerifyAndClearExpectations(m_mockClient); +} + TEST_F(WebEmbeddedWorkerImplFailureTest, TerminateWhileLoadingScript) { EXPECT_CALL(*m_mockClient, workerReadyForInspection()).Times(1);
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index e54cb64..c2b98fd 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -322,56 +322,6 @@ const WebInputEvent* WebFrameWidgetImpl::m_currentInputEvent = nullptr; -// FIXME: autogenerate this kind of code, and use it throughout Blink rather than -// the one-offs for subsets of these values. -static String inputTypeToName(WebInputEvent::Type type) -{ - switch (type) { - case WebInputEvent::MouseDown: - return EventTypeNames::mousedown; - case WebInputEvent::MouseUp: - return EventTypeNames::mouseup; - case WebInputEvent::MouseMove: - return EventTypeNames::mousemove; - case WebInputEvent::MouseEnter: - return EventTypeNames::mouseenter; - case WebInputEvent::MouseLeave: - return EventTypeNames::mouseleave; - case WebInputEvent::ContextMenu: - return EventTypeNames::contextmenu; - case WebInputEvent::MouseWheel: - return EventTypeNames::mousewheel; - case WebInputEvent::KeyDown: - return EventTypeNames::keydown; - case WebInputEvent::KeyUp: - return EventTypeNames::keyup; - case WebInputEvent::GestureScrollBegin: - return EventTypeNames::gesturescrollstart; - case WebInputEvent::GestureScrollEnd: - return EventTypeNames::gesturescrollend; - case WebInputEvent::GestureScrollUpdate: - return EventTypeNames::gesturescrollupdate; - case WebInputEvent::GestureTapDown: - return EventTypeNames::gesturetapdown; - case WebInputEvent::GestureShowPress: - return EventTypeNames::gestureshowpress; - case WebInputEvent::GestureTap: - return EventTypeNames::gesturetap; - case WebInputEvent::GestureTapUnconfirmed: - return EventTypeNames::gesturetapunconfirmed; - case WebInputEvent::TouchStart: - return EventTypeNames::touchstart; - case WebInputEvent::TouchMove: - return EventTypeNames::touchmove; - case WebInputEvent::TouchEnd: - return EventTypeNames::touchend; - case WebInputEvent::TouchCancel: - return EventTypeNames::touchcancel; - default: - return String("unknown"); - } -} - bool WebFrameWidgetImpl::handleInputEvent(const WebInputEvent& inputEvent) {
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp index 4f492195..28be457 100644 --- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp +++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -337,7 +337,7 @@ RefPtrWillBeRawPtr<ContentSecurityPolicy> contentSecurityPolicy = m_mainScriptLoader->releaseContentSecurityPolicy(); OwnPtr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create( m_url, - m_loadingDocument->userAgent(m_url), + m_loadingDocument->userAgent(), m_mainScriptLoader->script(), nullptr, startMode,
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 51f87fbd..375c92e 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2001,56 +2001,6 @@ const WebInputEvent* WebViewImpl::m_currentInputEvent = nullptr; -// FIXME: autogenerate this kind of code, and use it throughout Blink rather than -// the one-offs for subsets of these values. -static String inputTypeToName(WebInputEvent::Type type) -{ - switch (type) { - case WebInputEvent::MouseDown: - return EventTypeNames::mousedown; - case WebInputEvent::MouseUp: - return EventTypeNames::mouseup; - case WebInputEvent::MouseMove: - return EventTypeNames::mousemove; - case WebInputEvent::MouseEnter: - return EventTypeNames::mouseenter; - case WebInputEvent::MouseLeave: - return EventTypeNames::mouseleave; - case WebInputEvent::ContextMenu: - return EventTypeNames::contextmenu; - case WebInputEvent::MouseWheel: - return EventTypeNames::mousewheel; - case WebInputEvent::KeyDown: - return EventTypeNames::keydown; - case WebInputEvent::KeyUp: - return EventTypeNames::keyup; - case WebInputEvent::GestureScrollBegin: - return EventTypeNames::gesturescrollstart; - case WebInputEvent::GestureScrollEnd: - return EventTypeNames::gesturescrollend; - case WebInputEvent::GestureScrollUpdate: - return EventTypeNames::gesturescrollupdate; - case WebInputEvent::GestureTapDown: - return EventTypeNames::gesturetapdown; - case WebInputEvent::GestureShowPress: - return EventTypeNames::gestureshowpress; - case WebInputEvent::GestureTap: - return EventTypeNames::gesturetap; - case WebInputEvent::GestureTapUnconfirmed: - return EventTypeNames::gesturetapunconfirmed; - case WebInputEvent::TouchStart: - return EventTypeNames::touchstart; - case WebInputEvent::TouchMove: - return EventTypeNames::touchmove; - case WebInputEvent::TouchEnd: - return EventTypeNames::touchend; - case WebInputEvent::TouchCancel: - return EventTypeNames::touchcancel; - default: - return String("unknown"); - } -} - bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent) { // TODO(dcheng): The fact that this is getting called when there is no local
diff --git a/third_party/WebKit/Source/web/tests/FrameLoaderClientImplTest.cpp b/third_party/WebKit/Source/web/tests/FrameLoaderClientImplTest.cpp index 48ef6cf..4fe1d6e 100644 --- a/third_party/WebKit/Source/web/tests/FrameLoaderClientImplTest.cpp +++ b/third_party/WebKit/Source/web/tests/FrameLoaderClientImplTest.cpp
@@ -54,14 +54,14 @@ public: ~MockWebFrameClient() override { } - MOCK_METHOD2(userAgentOverride, WebString(WebLocalFrame*, const WebURL&)); + MOCK_METHOD1(userAgentOverride, WebString(WebLocalFrame*)); }; class FrameLoaderClientImplTest : public ::testing::Test { protected: void SetUp() override { - ON_CALL(m_webFrameClient, userAgentOverride(_, _)).WillByDefault(Return(WebString())); + ON_CALL(m_webFrameClient, userAgentOverride(_)).WillByDefault(Return(WebString())); FrameTestHelpers::TestWebViewClient webViewClient; m_webView = WebView::create(&webViewClient); @@ -80,9 +80,8 @@ WebString userAgent() { - // The test always returns the same user agent, regardless of the URL passed in. - KURL dummyURL(ParsedURLString, "about:blank"); - WTF::CString userAgent = frameLoaderClient().userAgent(dummyURL).utf8(); + // The test always returns the same user agent . + WTF::CString userAgent = frameLoaderClient().userAgent().utf8(); return WebString::fromUTF8(userAgent.data(), userAgent.length()); } @@ -103,12 +102,12 @@ const WebString overrideUserAgent = WebString::fromUTF8("dummy override"); // Override the user agent and make sure we get it back. - EXPECT_CALL(webFrameClient(), userAgentOverride(_, _)).WillOnce(Return(overrideUserAgent)); + EXPECT_CALL(webFrameClient(), userAgentOverride(_)).WillOnce(Return(overrideUserAgent)); EXPECT_TRUE(overrideUserAgent.equals(userAgent())); Mock::VerifyAndClearExpectations(&webFrameClient()); // Remove the override and make sure we get the original back. - EXPECT_CALL(webFrameClient(), userAgentOverride(_, _)).WillOnce(Return(WebString())); + EXPECT_CALL(webFrameClient(), userAgentOverride(_)).WillOnce(Return(WebString())); EXPECT_TRUE(defaultUserAgent.equals(userAgent())); }
diff --git a/third_party/WebKit/Source/wtf/AddressSpaceRandomization.cpp b/third_party/WebKit/Source/wtf/AddressSpaceRandomization.cpp index 7f98d9dca..2a363a33 100644 --- a/third_party/WebKit/Source/wtf/AddressSpaceRandomization.cpp +++ b/third_party/WebKit/Source/wtf/AddressSpaceRandomization.cpp
@@ -108,17 +108,6 @@ random &= 0x3fffffffffUL; random += 0x1000000000UL; #else // !CPU(X86_64) && !CPU(ARM64) -#if OS(WIN) - // On win32 host systems the randomization plus huge alignment causes - // excessive fragmentation. Plus most of these systems lack ASLR, so the - // randomization isn't buying anything. In that case we just skip it. - // TODO(jschuh): Just dump the randomization when HE-ASLR is present. - static BOOL isWow64 = -1; - if (isWow64 == -1 && !IsWow64Process(GetCurrentProcess(), &isWow64)) - isWow64 = FALSE; - if (!isWow64) - return nullptr; -#endif // OS(WIN) // This is a good range on Windows, Linux and Mac. // Allocates in the 0.5-1.5GB region. random &= 0x3fffffff;
diff --git a/third_party/WebKit/Source/wtf/PageAllocator.cpp b/third_party/WebKit/Source/wtf/PageAllocator.cpp index 27e83fa8..5f5eb440 100644 --- a/third_party/WebKit/Source/wtf/PageAllocator.cpp +++ b/third_party/WebKit/Source/wtf/PageAllocator.cpp
@@ -58,8 +58,8 @@ namespace WTF { -// This internal function wraps the OS-specific page allocation call so that -// it behaves consistently: the address is a hint and if it cannot be used, +// This simple internal function wraps the OS-specific page allocation call so +// that it behaves consistently: the address is a hint and if it cannot be used, // the allocation will be placed elsewhere. static void* systemAllocPages(void* addr, size_t len, PageAccessibilityConfiguration pageAccessibility) { @@ -67,7 +67,7 @@ ASSERT(!(reinterpret_cast<uintptr_t>(addr) & kPageAllocationGranularityOffsetMask)); void* ret; #if OS(WIN) - DWORD accessFlag = pageAccessibility == PageAccessible ? PAGE_READWRITE : PAGE_NOACCESS; + int accessFlag = pageAccessibility == PageAccessible ? PAGE_READWRITE : PAGE_NOACCESS; ret = VirtualAlloc(addr, len, MEM_RESERVE | MEM_COMMIT, accessFlag); if (!ret) ret = VirtualAlloc(0, len, MEM_RESERVE | MEM_COMMIT, accessFlag); @@ -80,6 +80,29 @@ return ret; } +static bool trimMapping(void* baseAddr, size_t baseLen, void* trimAddr, size_t trimLen) +{ +#if OS(WIN) + return false; +#else + char* basePtr = static_cast<char*>(baseAddr); + char* trimPtr = static_cast<char*>(trimAddr); + ASSERT(trimPtr >= basePtr); + ASSERT(trimPtr + trimLen <= basePtr + baseLen); + size_t preLen = trimPtr - basePtr; + if (preLen) { + int ret = munmap(basePtr, preLen); + RELEASE_ASSERT(!ret); + } + size_t postLen = (basePtr + baseLen) - (trimPtr + trimLen); + if (postLen) { + int ret = munmap(trimPtr + trimLen, postLen); + RELEASE_ASSERT(!ret); + } + return true; +#endif +} + void* allocPages(void* addr, size_t len, size_t align, PageAccessibilityConfiguration pageAccessibility) { ASSERT(len >= kPageAllocationGranularity); @@ -87,8 +110,8 @@ ASSERT(align >= kPageAllocationGranularity); ASSERT(!(align & kPageAllocationGranularityOffsetMask)); ASSERT(!(reinterpret_cast<uintptr_t>(addr) & kPageAllocationGranularityOffsetMask)); - uintptr_t alignOffsetMask = align - 1; - uintptr_t alignBaseMask = ~alignOffsetMask; + size_t alignOffsetMask = align - 1; + size_t alignBaseMask = ~alignOffsetMask; ASSERT(!(reinterpret_cast<uintptr_t>(addr) & alignOffsetMask)); // If the client passed null as the address, choose a good one. if (!addr) { @@ -96,70 +119,50 @@ addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & alignBaseMask); } - // First try to force an exact-size, aligned allocation from our random base. - for (int count = 0; count < 3; ++count) { - void* ret = systemAllocPages(addr, len, pageAccessibility); - // If the alignment is to our liking, we're done. - if (!(reinterpret_cast<uintptr_t>(ret) & alignOffsetMask)) - return ret; - // We failed, so we retry another range depending on the size of our address space. - freePages(ret, len); -#if CPU(32BIT) - // Use a linear probe on 32-bit systems, where the address space tends to be cramped. - // This may wrap, but we'll just fall back to the guaranteed method in that case. - addr = reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(ret) + align) & alignBaseMask); -#else - // Keep trying random addresses on systems that have a large address space. - addr = getRandomPageBase(); - addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & alignBaseMask); -#endif - } + // The common case, which is also the least work we can do, is that the + // address and length are suitable. Just try it. + void* ret = systemAllocPages(addr, len, pageAccessibility); + // If the alignment is to our liking, we're done. + if (!ret || !(reinterpret_cast<uintptr_t>(ret) & alignOffsetMask)) + return ret; - // Map a larger allocation so we can force alignment, but continuing randomizing only on - // 64-bit POSIX. + // Annoying. Unmap and map a larger range to be sure to succeed on the + // second, slower attempt. + freePages(ret, len); + size_t tryLen = len + (align - kPageAllocationGranularity); RELEASE_ASSERT(tryLen > len); - while (true) { - addr = nullptr; -#if OS(POSIX) && CPU(32BIT) - addr = getRandomPageBase(); -#endif - void* ret = systemAllocPages(addr, tryLen, pageAccessibility); - if (!ret) - return nullptr; - size_t preSlack = reinterpret_cast<uintptr_t>(ret) & alignOffsetMask; - preSlack = preSlack ? align - preSlack : 0; - size_t postSlack = tryLen - preSlack - len; - ASSERT(preSlack || postSlack); - ASSERT(preSlack < tryLen); - ASSERT(postSlack < tryLen); -#if OS(POSIX) // On POSIX we can resize the allocation run. - if (preSlack) { - int res = munmap(ret, preSlack); - RELEASE_ASSERT(!res); - ret = addr = reinterpret_cast<char*>(ret) + preSlack; - } - if (postSlack) { - int res = munmap(reinterpret_cast<char*>(ret) + len, postSlack); - RELEASE_ASSERT(!res); - } -#else // On Windows we can't resize the allocation run. - if (preSlack || postSlack) { - addr = reinterpret_cast<char*>(ret) + preSlack; - freePages(ret, len); - ret = systemAllocPages(addr, len, pageAccessibility); - if (!ret) - return nullptr; - } -#endif - if (ret == addr) { - ASSERT(!(reinterpret_cast<uintptr_t>(ret) & alignOffsetMask)); - return ret; - } - freePages(ret, len); - } - return nullptr; + // We loop to cater for the unlikely case where another thread maps on top + // of the aligned location we choose. + int count = 0; + while (count++ < 100) { + ret = systemAllocPages(addr, tryLen, pageAccessibility); + if (!ret) + return 0; + // We can now try and trim out a subset of the mapping. + addr = reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(ret) + alignOffsetMask) & alignBaseMask); + + // On POSIX systems, we can trim the oversized mapping to fit exactly. + // This will always work on POSIX systems. + if (trimMapping(ret, tryLen, addr, len)) + return addr; + + // On Windows, you can't trim an existing mapping so we unmap and remap + // a subset. We used to do for all platforms, but OSX 10.8 has a + // broken mmap() that ignores address hints for valid, unused addresses. + freePages(ret, tryLen); + ret = systemAllocPages(addr, len, pageAccessibility); + if (ret == addr || !ret) + return ret; + + // Unlikely race / collision. Do the simple thing and just start again. + freePages(ret, len); + addr = getRandomPageBase(); + addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & alignBaseMask); + } + IMMEDIATE_CRASH(); + return 0; } void freePages(void* addr, size_t len)
diff --git a/third_party/WebKit/public/platform/WebPointerProperties.h b/third_party/WebKit/public/platform/WebPointerProperties.h index a8c16808..4d59b17 100644 --- a/third_party/WebKit/public/platform/WebPointerProperties.h +++ b/third_party/WebKit/public/platform/WebPointerProperties.h
@@ -20,7 +20,7 @@ , force(0.f) , tiltX(0) , tiltY(0) - , pointerType(PointerTypeUnknown) + , pointerType(PointerType::Unknown) { } @@ -31,11 +31,12 @@ ButtonRight }; - enum PointerType { - PointerTypeUnknown, - PointerTypeMouse, - PointerTypePen, - PointerTypeTouch + enum class PointerType : int { + Unknown, + Mouse, + Pen, + Touch, + LastEntry = Touch // Must be the last entry in the list }; Button button;
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h index 7ad9298a..c52278c 100644 --- a/third_party/WebKit/public/web/WebFrameClient.h +++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -555,10 +555,10 @@ WebSecurityOrigin target, WebDOMMessageEvent event) { return false; } - // Asks the embedder if a specific user agent should be used for the given - // URL. Non-empty strings indicate an override should be used. Otherwise, + // Asks the embedder if a specific user agent should be used. Non-empty + // strings indicate an override should be used. Otherwise, // Platform::current()->userAgent() will be called to provide one. - virtual WebString userAgentOverride(WebLocalFrame*, const WebURL& url) { return WebString(); } + virtual WebString userAgentOverride(WebLocalFrame*) { return WebString(); } // Asks the embedder what value the network stack will send for the DNT // header. An empty string indicates that no DNT header will be send.
diff --git a/third_party/leveldatabase/BUILD.gn b/third_party/leveldatabase/BUILD.gn index b3080d8..636731d 100644 --- a/third_party/leveldatabase/BUILD.gn +++ b/third_party/leveldatabase/BUILD.gn
@@ -14,6 +14,15 @@ ] } +config("leveldb_db_bench_warnings") { + if (is_clang) { + # TrimSpaces in db_bench.cc is unused on non-linux. + # TODO(thakis): Remove this once that's fixed upstream, + # https://github.com/google/leveldb/pull/310 + cflags = [ "-Wno-unused-function" ] + } +} + static_library("leveldatabase") { sources = [ "env_chromium.cc", @@ -213,6 +222,8 @@ ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] + # Needs to be after no_chromium_code to have an effect: + configs += [ ":leveldb_db_bench_warnings" ] deps = [ ":leveldb_testutil", ]
diff --git a/third_party/modp_b64/README.chromium b/third_party/modp_b64/README.chromium index 40b93d2b..364a050 100644 --- a/third_party/modp_b64/README.chromium +++ b/third_party/modp_b64/README.chromium
@@ -1,6 +1,6 @@ Name: modp base64 decoder Short Name: stringencoders -URL: http://code.google.com/p/stringencoders/ +URL: https://github.com/client9/stringencoders Version: unknown License: BSD Security Critical: yes
diff --git a/third_party/ots/README.chromium b/third_party/ots/README.chromium index 6bde0a7..bd86115 100644 --- a/third_party/ots/README.chromium +++ b/third_party/ots/README.chromium
@@ -1,4 +1,4 @@ -Name: OTS +Name: OTS (OpenType Sanitizer) URL: https://github.com/khaledhosny/ots.git Version: a7a3b94ef08cdbdbf5ffcb7d44334d47152a82ef Security Critical: yes
diff --git a/third_party/pyftpdlib/README.chromium b/third_party/pyftpdlib/README.chromium index 7780c6a..cfa81659 100644 --- a/third_party/pyftpdlib/README.chromium +++ b/third_party/pyftpdlib/README.chromium
@@ -1,9 +1,10 @@ Name: Python FTP server library Short Name: pyftpdlib -URL: http://code.google.com/p/pyftpdlib/ +URL: https://github.com/giampaolo/pyftpdlib +Version: 0.7.0-updates +Revision: 2be6d65e31c7ee6320d059f581f05ae8d89d7e45 License: MIT License File: src/LICENSE -Version: unknown Security Critical: no Description: @@ -12,4 +13,4 @@ pyftpdlib is currently the most complete RFC-959 FTP server implementation available for Python programming language. -Learn more by visiting: http://code.google.com/p/pyftpdlib/wiki/FAQ +Learn more by visiting: http://pythonhosted.org/pyftpdlib/faqs.html
diff --git a/third_party/re2/README.chromium b/third_party/re2/README.chromium index 56a3f811..6ce6d2d4 100644 --- a/third_party/re2/README.chromium +++ b/third_party/re2/README.chromium
@@ -1,10 +1,10 @@ Name: re2 - an efficient, principled regular expression library Short Name: re2 -URL: http://code.google.com/p/re2/ +URL: https://github.com/google/re2 Version: 7f91923f3ad4 Date: 2012-06-20 Revision: 100:7f91923f3ad4 -License: BSD 3-Clause License +License: BSD 3-Clause License File: LICENSE Security Critical: yes
diff --git a/third_party/snappy/README.chromium b/third_party/snappy/README.chromium index f7e3742..81d3332 100644 --- a/third_party/snappy/README.chromium +++ b/third_party/snappy/README.chromium
@@ -1,7 +1,7 @@ Name: Snappy: A fast compressor/decompressor Short Name: snappy -URL: http://code.google.com/p/snappy/ -Version: r80 +URL: http://google.github.io/snappy/ +Version: 1.1.0-updates License: New BSD License File: src/COPYING Security Critical: yes
diff --git a/tools/chrome_proxy/common/chrome_proxy_measurements.py b/tools/chrome_proxy/common/chrome_proxy_measurements.py index b7f7515..1628cce 100644 --- a/tools/chrome_proxy/common/chrome_proxy_measurements.py +++ b/tools/chrome_proxy/common/chrome_proxy_measurements.py
@@ -27,6 +27,7 @@ 'function ProbeViaHeader(url, wanted_via) {' 'try {' 'var xmlhttp = new XMLHttpRequest();' + 'xmlhttp.timeout = 15;' 'xmlhttp.open("HEAD",url,false);' 'xmlhttp.send();' 'var via=xmlhttp.getResponseHeader("via");'
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp index 8820407..9b7793a 100644 --- a/tools/clang/plugins/ChromeClassTester.cpp +++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -150,6 +150,16 @@ filename.insert(filename.begin(), '/'); #endif + for (const std::string& allowed_dir : allowed_directories_) { + // If any of the allowed directories occur as a component in filename, + // this file is allowed. + assert(allowed_dir.front() == '/' && "Allowed dir must start with '/'"); + assert(allowed_dir.back() == '/' && "Allowed dir must end with '/'"); + + if (filename.find(allowed_dir) != std::string::npos) + return false; + } + for (const std::string& banned_dir : banned_directories_) { // If any of the banned directories occur as a component in filename, // this file is rejected. @@ -191,75 +201,79 @@ } void ChromeClassTester::BuildBannedLists() { - banned_namespaces_.push_back("std"); - banned_namespaces_.push_back("__gnu_cxx"); + banned_namespaces_.emplace("std"); + banned_namespaces_.emplace("__gnu_cxx"); - if (!options_.enforce_blink) { - banned_namespaces_.push_back("blink"); - banned_namespaces_.push_back("WTF"); + if (!options_.enforce_overriding_blink) { + banned_namespaces_.emplace("blink"); + banned_namespaces_.emplace("WTF"); } - banned_directories_.push_back("/third_party/"); - banned_directories_.push_back("/native_client/"); - banned_directories_.push_back("/breakpad/"); - banned_directories_.push_back("/courgette/"); - banned_directories_.push_back("/pdf/"); - banned_directories_.push_back("/ppapi/"); - banned_directories_.push_back("/usr/include/"); - banned_directories_.push_back("/usr/lib/"); - banned_directories_.push_back("/usr/local/include/"); - banned_directories_.push_back("/usr/local/lib/"); - banned_directories_.push_back("/testing/"); - banned_directories_.push_back("/v8/"); - banned_directories_.push_back("/dart/"); - banned_directories_.push_back("/sdch/"); - banned_directories_.push_back("/icu4c/"); - banned_directories_.push_back("/frameworks/"); + if (options_.enforce_in_thirdparty_webkit) { + allowed_directories_.emplace("/third_party/WebKit/"); + } + + banned_directories_.emplace("/third_party/"); + banned_directories_.emplace("/native_client/"); + banned_directories_.emplace("/breakpad/"); + banned_directories_.emplace("/courgette/"); + banned_directories_.emplace("/pdf/"); + banned_directories_.emplace("/ppapi/"); + banned_directories_.emplace("/usr/include/"); + banned_directories_.emplace("/usr/lib/"); + banned_directories_.emplace("/usr/local/include/"); + banned_directories_.emplace("/usr/local/lib/"); + banned_directories_.emplace("/testing/"); + banned_directories_.emplace("/v8/"); + banned_directories_.emplace("/dart/"); + banned_directories_.emplace("/sdch/"); + banned_directories_.emplace("/icu4c/"); + banned_directories_.emplace("/frameworks/"); // Don't check autogenerated headers. // Make puts them below $(builddir_name)/.../gen and geni. // Ninja puts them below OUTPUT_DIR/.../gen // Xcode has a fixed output directory for everything. - banned_directories_.push_back("/gen/"); - banned_directories_.push_back("/geni/"); - banned_directories_.push_back("/xcodebuild/"); + banned_directories_.emplace("/gen/"); + banned_directories_.emplace("/geni/"); + banned_directories_.emplace("/xcodebuild/"); // Used in really low level threading code that probably shouldn't be out of // lined. - ignored_record_names_.insert("ThreadLocalBoolean"); + ignored_record_names_.emplace("ThreadLocalBoolean"); // A complicated pickle derived struct that is all packed integers. - ignored_record_names_.insert("Header"); + ignored_record_names_.emplace("Header"); // Part of the GPU system that uses multiple included header // weirdness. Never getting this right. - ignored_record_names_.insert("Validators"); + ignored_record_names_.emplace("Validators"); // Has a UNIT_TEST only constructor. Isn't *terribly* complex... - ignored_record_names_.insert("AutocompleteController"); - ignored_record_names_.insert("HistoryURLProvider"); + ignored_record_names_.emplace("AutocompleteController"); + ignored_record_names_.emplace("HistoryURLProvider"); // Used over in the net unittests. A large enough bundle of integers with 1 // non-pod class member. Probably harmless. - ignored_record_names_.insert("MockTransaction"); + ignored_record_names_.emplace("MockTransaction"); // Enum type with _LAST members where _LAST doesn't mean last enum value. - ignored_record_names_.insert("ServerFieldType"); + ignored_record_names_.emplace("ServerFieldType"); // Used heavily in ui_base_unittests and once in views_unittests. Fixing this // isn't worth the overhead of an additional library. - ignored_record_names_.insert("TestAnimationDelegate"); + ignored_record_names_.emplace("TestAnimationDelegate"); // Part of our public interface that nacl and friends use. (Arguably, this // should mean that this is a higher priority but fixing this looks hard.) - ignored_record_names_.insert("PluginVersionInfo"); + ignored_record_names_.emplace("PluginVersionInfo"); // Measured performance improvement on cc_perftests. See // https://codereview.chromium.org/11299290/ - ignored_record_names_.insert("QuadF"); + ignored_record_names_.emplace("QuadF"); // Enum type with _LAST members where _LAST doesn't mean last enum value. - ignored_record_names_.insert("ViewID"); + ignored_record_names_.emplace("ViewID"); } std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
diff --git a/tools/clang/plugins/ChromeClassTester.h b/tools/clang/plugins/ChromeClassTester.h index 6b5cdf3..e3d7e3c 100644 --- a/tools/clang/plugins/ChromeClassTester.h +++ b/tools/clang/plugins/ChromeClassTester.h
@@ -85,10 +85,14 @@ clang::DiagnosticsEngine& diagnostic_; // List of banned namespaces. - std::vector<std::string> banned_namespaces_; + std::set<std::string> banned_namespaces_; + + // List of directories allowed even though their parent directories are in + // |banned_directories_|, below. + std::set<std::string> allowed_directories_; // List of banned directories. - std::vector<std::string> banned_directories_; + std::set<std::string> banned_directories_; // List of types that we don't check. std::set<std::string> ignored_record_names_;
diff --git a/tools/clang/plugins/FindBadConstructsAction.cpp b/tools/clang/plugins/FindBadConstructsAction.cpp index 5595cde..0f6fbd5d 100644 --- a/tools/clang/plugins/FindBadConstructsAction.cpp +++ b/tools/clang/plugins/FindBadConstructsAction.cpp
@@ -49,8 +49,11 @@ if (args[i] == "check-base-classes") { // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed. options_.check_base_classes = true; - } else if (args[i] == "enforce-blink") { - options_.enforce_blink = true; + } else if (args[i] == "enforce-overriding-blink") { + options_.enforce_overriding_blink = true; + } else if (args[i] == "enforce-in-thirdparty-webkit") { + options_.enforce_in_thirdparty_webkit = true; + options_.enforce_overriding_blink = true; } else if (args[i] == "check-enum-last-value") { // TODO(tsepez): Enable this by default once http://crbug.com/356815 // and http://crbug.com/356816 are fixed.
diff --git a/tools/clang/plugins/Options.h b/tools/clang/plugins/Options.h index a79bb1e..a94c95e 100644 --- a/tools/clang/plugins/Options.h +++ b/tools/clang/plugins/Options.h
@@ -10,14 +10,16 @@ struct Options { Options() : check_base_classes(false), - enforce_blink(false), + enforce_overriding_blink(false), + enforce_in_thirdparty_webkit(false), check_enum_last_value(false), with_ast_visitor(false), check_templates(false), warn_only(false) {} bool check_base_classes; - bool enforce_blink; + bool enforce_overriding_blink; // Blink base-class use + bool enforce_in_thirdparty_webkit; // Use in Blink code itself bool check_enum_last_value; bool with_ast_visitor; bool check_templates;
diff --git a/tools/clang/plugins/tests/overridden_methods.flags b/tools/clang/plugins/tests/overridden_methods.flags index da946afc..eab5ca0 100644 --- a/tools/clang/plugins/tests/overridden_methods.flags +++ b/tools/clang/plugins/tests/overridden_methods.flags
@@ -1 +1 @@ --Xclang -plugin-arg-find-bad-constructs -Xclang enforce-blink +-Xclang -plugin-arg-find-bad-constructs -Xclang enforce-overriding-blink
diff --git a/tools/gn/builder.cc b/tools/gn/builder.cc index ca11e888..5548d2b 100644 --- a/tools/gn/builder.cc +++ b/tools/gn/builder.cc
@@ -416,7 +416,6 @@ !ResolveConfigs(&target->configs(), err) || !ResolveConfigs(&target->all_dependent_configs(), err) || !ResolveConfigs(&target->public_configs(), err) || - !ResolveForwardDependentConfigs(target, err) || !ResolveToolchain(target, err)) return false; } else if (record->type() == BuilderRecord::ITEM_CONFIG) { @@ -477,37 +476,6 @@ return true; } -// "Forward dependent configs" should refer to targets in the deps that should -// have their configs forwarded. -bool Builder::ResolveForwardDependentConfigs(Target* target, Err* err) { - const UniqueVector<LabelTargetPair>& configs = - target->forward_dependent_configs(); - - // Assume that the lists are small so that brute-force n^2 is appropriate. - for (const auto& config : configs) { - for (const auto& dep_pair : target->GetDeps(Target::DEPS_LINKED)) { - if (config.label == dep_pair.label) { - DCHECK(dep_pair.ptr); // Should already be resolved. - // UniqueVector's contents are constant so uniqueness is preserved, but - // we want to update this pointer which doesn't change uniqueness - // (uniqueness in this vector is determined by the label only). - const_cast<LabelTargetPair&>(config).ptr = dep_pair.ptr; - break; - } - } - if (!config.ptr) { - *err = Err(target->defined_from(), - "Target in forward_dependent_configs_from was not listed in the deps", - "This target has a forward_dependent_configs_from entry that was " - "not present in\nthe deps. A target can only forward things it " - "depends on. It was forwarding:\n " + - config.label.GetUserVisibleName(false)); - return false; - } - } - return true; -} - bool Builder::ResolveToolchain(Target* target, Err* err) { BuilderRecord* record = GetResolvedRecordOfType( target->settings()->toolchain_label(), target->defined_from(),
diff --git a/tools/gn/builder.h b/tools/gn/builder.h index 7f9e59b4..3a22266 100644 --- a/tools/gn/builder.h +++ b/tools/gn/builder.h
@@ -118,7 +118,6 @@ // if anything isn't found or if the type doesn't match. bool ResolveDeps(LabelTargetVector* deps, Err* err); bool ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err); - bool ResolveForwardDependentConfigs(Target* target, Err* err); bool ResolveToolchain(Target* target, Err* err); // Given a list of unresolved records, tries to find any circular
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc index 01422c5..3f2bbaf5 100644 --- a/tools/gn/command_desc.cc +++ b/tools/gn/command_desc.cc
@@ -153,25 +153,6 @@ } } -void PrintForwardDependentConfigsFrom(const Target* target, - bool display_header) { - if (target->forward_dependent_configs().empty()) - return; - - if (display_header) - OutputString("\nforward_dependent_configs_from:\n"); - - // Collect the sorted list of deps. - std::vector<Label> forward; - for (const auto& pair : target->forward_dependent_configs()) - forward.push_back(pair.label); - std::sort(forward.begin(), forward.end()); - - Label toolchain_label = target->label().GetToolchainLabel(); - for (const auto& fwd : forward) - OutputString(" " + fwd.GetUserVisibleName(toolchain_label) + "\n"); -} - // libs and lib_dirs are special in that they're inherited. We don't currently // implement a blame feature for this since the bottom-up inheritance makes // this difficult. @@ -527,10 +508,6 @@ " Shows the labels of configs applied to targets that depend on this\n" " one (either directly or all of them).\n" "\n" - " forward_dependent_configs_from\n" - " Shows the labels of dependencies for which dependent configs will\n" - " be pushed to targets depending on the current one.\n" - "\n" " script\n" " args\n" " depfile\n" @@ -647,8 +624,6 @@ PrintPublicConfigs(target, false); } else if (what == variables::kAllDependentConfigs) { PrintAllDependentConfigs(target, false); - } else if (what == variables::kForwardDependentConfigsFrom) { - PrintForwardDependentConfigsFrom(target, false); } else if (what == variables::kSources) { PrintSources(target, false); } else if (what == variables::kPublic) { @@ -736,7 +711,6 @@ PrintPublicConfigs(target, true); PrintAllDependentConfigs(target, true); - PrintForwardDependentConfigsFrom(target, true); PrintInputs(target, true);
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md index c8370374..657796a 100644 --- a/tools/gn/docs/reference.md +++ b/tools/gn/docs/reference.md
@@ -378,10 +378,6 @@ Shows the labels of configs applied to targets that depend on this one (either directly or all of them). - forward_dependent_configs_from - Shows the labels of dependencies for which dependent configs will - be pushed to targets depending on the current one. - script args depfile @@ -1036,8 +1032,7 @@ ### **Variables on a target used to apply configs**: ``` - all_dependent_configs, configs, public_configs, - forward_dependent_configs_from + all_dependent_configs, configs, public_configs ``` @@ -1230,7 +1225,7 @@ Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs, precompiled_header, precompiled_source - Deps: data_deps, deps, forward_dependent_configs_from, public_deps + Deps: data_deps, deps, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibility @@ -1587,16 +1582,14 @@ specify configs that apply to their dependents. Depending on a group is exactly like depending directly on that - group's deps. Direct dependent configs will get automatically - forwarded through the group so you shouldn't need to use - "forward_dependent_configs_from. + group's deps. ``` ### **Variables** ``` - Deps: data_deps, deps, forward_dependent_configs_from, public_deps + Deps: data_deps, deps, public_deps Dependent configs: all_dependent_configs, public_configs ``` @@ -2005,7 +1998,7 @@ Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs, precompiled_header, precompiled_source - Deps: data_deps, deps, forward_dependent_configs_from, public_deps + Deps: data_deps, deps, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibility @@ -2046,7 +2039,7 @@ Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs, precompiled_header, precompiled_source - Deps: data_deps, deps, forward_dependent_configs_from, public_deps + Deps: data_deps, deps, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibility @@ -2070,7 +2063,7 @@ Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc, defines, include_dirs, ldflags, lib_dirs, libs, precompiled_header, precompiled_source - Deps: data_deps, deps, forward_dependent_configs_from, public_deps + Deps: data_deps, deps, public_deps Dependent configs: all_dependent_configs, public_configs General: check_includes, configs, data, inputs, output_name, output_extension, public, sources, testonly, visibility @@ -3725,56 +3718,6 @@ ``` -## **forward_dependent_configs_from** - -``` - A list of target labels. - - DEPRECATED. Use public_deps instead which will have the same effect. - - Exposes the public_configs from a private dependent target as - public_configs of the current one. Each label in this list - must also be in the deps. - - Generally you should use public_deps instead of this variable to - express the concept of exposing a dependency as part of a target's - public API. We're considering removing this variable. - -``` - -### **Discussion** - -``` - Sometimes you depend on a child library that exports some necessary - configuration via public_configs. If your target in turn exposes the - child library's headers in its public headers, it might mean that - targets that depend on you won't work: they'll be seeing the child - library's code but not the necessary configuration. This list - specifies which of your deps' direct dependent configs to expose as - your own. - -``` - -### **Examples** - -``` - If we use a given library "a" from our public headers: - - deps = [ ":a", ":b", ... ] - forward_dependent_configs_from = [ ":a" ] - - This example makes a "transparent" target that forwards a dependency - to another: - - group("frob") { - if (use_system_frob) { - deps = ":system_frob" - } else { - deps = "//third_party/fallback_frob" - } - forward_dependent_configs_from = deps - } - ``` ## **include_dirs**: Additional include directories.
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc index 01d0aeb..9413a7f 100644 --- a/tools/gn/functions.cc +++ b/tools/gn/functions.cc
@@ -265,8 +265,7 @@ CONFIG_VALUES_VARS_HELP "\n" "Variables on a target used to apply configs:\n" - " all_dependent_configs, configs, public_configs,\n" - " forward_dependent_configs_from\n" + " all_dependent_configs, configs, public_configs\n" "\n" "Example:\n" " config(\"myconfig\") {\n"
diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc index ffe8f5f..fbac2d2 100644 --- a/tools/gn/functions_target.cc +++ b/tools/gn/functions_target.cc
@@ -16,7 +16,7 @@ #define DEPENDENT_CONFIG_VARS \ " Dependent configs: all_dependent_configs, public_configs\n" #define DEPS_VARS \ - " Deps: data_deps, deps, forward_dependent_configs_from, public_deps\n" + " Deps: data_deps, deps, public_deps\n" #define GENERAL_TARGET_VARS \ " General: check_includes, configs, data, inputs, output_name,\n" \ " output_extension, public, sources, testonly, visibility\n" @@ -330,9 +330,7 @@ " specify configs that apply to their dependents.\n" "\n" " Depending on a group is exactly like depending directly on that\n" - " group's deps. Direct dependent configs will get automatically\n" - " forwarded through the group so you shouldn't need to use\n" - " \"forward_dependent_configs_from.\n" + " group's deps. \n" "\n" "Variables\n" "\n"
diff --git a/tools/gn/misc/emacs/gn-mode.el b/tools/gn/misc/emacs/gn-mode.el index d867567..e61dec5 100644 --- a/tools/gn/misc/emacs/gn-mode.el +++ b/tools/gn/misc/emacs/gn-mode.el
@@ -73,10 +73,9 @@ '("all_dependent_configs" "allow_circular_includes_from" "args" "asmflags" "cflags" "cflags_c" "cflags_cc" "cflags_objc" "cflags_objcc" "check_includes" "complete_static_lib" "configs" "data" "data_deps" - "defines" "depfile" "deps" "forward_dependent_configs_from" "include_dirs" - "inputs" "ldflags" "lib_dirs" "libs" "output_extension" "output_name" - "outputs" "public" "public_configs" "public_deps" "script" "sources" - "testonly" "visibility")) + "defines" "depfile" "deps" "include_dirs" "inputs" "ldflags" "lib_dirs" + "libs" "output_extension" "output_name" "outputs" "public" "public_configs" + "public_deps" "script" "sources" "testonly" "visibility")) (defconst gn-font-lock-keywords `((,(regexp-opt gn-font-lock-target-declaration-keywords 'words) .
diff --git a/tools/gn/misc/tm/GN.tmLanguage b/tools/gn/misc/tm/GN.tmLanguage index 44cb611..5f39f01 100644 --- a/tools/gn/misc/tm/GN.tmLanguage +++ b/tools/gn/misc/tm/GN.tmLanguage
@@ -89,7 +89,7 @@ <key>comment</key> <string>target variables</string> <key>match</key> - <string>\b(?:all_dependent_configs|allow_circular_includes_from|args|asmflags|cflags|cflags_c|cflags_cc|cflags_objc|cflags_objcc|check_includes|complete_static_lib|configs|data|data_deps|defines|depfile|deps|forward_dependent_configs_from|include_dirs|inputs|ldflags|lib_dirs|libs|output_extension|output_name|outputs|public|public_configs|public_deps|script|sources|testonly|visibility)\b</string> + <string>\b(?:all_dependent_configs|allow_circular_includes_from|args|asmflags|cflags|cflags_c|cflags_cc|cflags_objc|cflags_objcc|check_includes|complete_static_lib|configs|data|data_deps|defines|depfile|deps|include_dirs|inputs|ldflags|lib_dirs|libs|output_extension|output_name|outputs|public|public_configs|public_deps|script|sources|testonly|visibility)\b</string> <key>name</key> <string>entity.other.attribute-name.gn</string> </dict>
diff --git a/tools/gn/misc/vim/syntax/gn.vim b/tools/gn/misc/vim/syntax/gn.vim index d9757e3..b7cef23 100644 --- a/tools/gn/misc/vim/syntax/gn.vim +++ b/tools/gn/misc/vim/syntax/gn.vim
@@ -44,10 +44,10 @@ syn keyword gnVariable args asmflags cflags cflags_c cflags_cc cflags_objc syn keyword gnVariable cflags_objcc check_includes complete_static_lib syn keyword gnVariable configs data data_deps defines depfile deps -syn keyword gnVariable forward_dependent_configs_from include_dirs inputs -syn keyword gnVariable ldflags lib_dirs libs output_extension output_name -syn keyword gnVariable outputs public public_configs public_deps script -syn keyword gnVariable sources testonly visibility +syn keyword gnVariable include_dirs inputs ldflags lib_dirs libs +syn keyword gnVariable output_extension output_name outputs public +syn keyword gnVariable public_configs public_deps scripte sources testonly +syn keyword gnVariable visibility hi def link gnVariable Keyword " Strings
diff --git a/tools/gn/target.cc b/tools/gn/target.cc index 585c850c3..a27a5c4f 100644 --- a/tools/gn/target.cc +++ b/tools/gn/target.cc
@@ -168,7 +168,7 @@ } PullDependentTargets(); - PullForwardedDependentConfigs(); + PullPublicConfigs(); PullRecursiveHardDeps(); if (!ResolvePrecompiledHeaders(err)) return false; @@ -305,30 +305,13 @@ PullDependentTarget(dep.ptr, false); } -void Target::PullForwardedDependentConfigs() { +void Target::PullPublicConfigs() { // Pull public configs from each of our dependency's public deps. for (const auto& dep : public_deps_) - PullForwardedDependentConfigsFrom(dep.ptr); - - // Forward public configs if explicitly requested. - for (const auto& dep : forward_dependent_configs_) { - const Target* from_target = dep.ptr; - - // The forward_dependent_configs_ must be in the deps (public or private) - // already, so we don't need to bother copying to our configs, only - // forwarding. - DCHECK(std::find_if(private_deps_.begin(), private_deps_.end(), - LabelPtrPtrEquals<Target>(from_target)) != - private_deps_.end() || - std::find_if(public_deps_.begin(), public_deps_.end(), - LabelPtrPtrEquals<Target>(from_target)) != - public_deps_.end()); - - PullForwardedDependentConfigsFrom(from_target); - } + PullPublicConfigsFrom(dep.ptr); } -void Target::PullForwardedDependentConfigsFrom(const Target* from) { +void Target::PullPublicConfigsFrom(const Target* from) { public_configs_.Append(from->public_configs().begin(), from->public_configs().end()); }
diff --git a/tools/gn/target.h b/tools/gn/target.h index a983241..fc752ac 100644 --- a/tools/gn/target.h +++ b/tools/gn/target.h
@@ -174,15 +174,6 @@ return public_configs_; } - // A list of a subset of deps where we'll re-export public_configs as - // public_configs of this target. - const UniqueVector<LabelTargetPair>& forward_dependent_configs() const { - return forward_dependent_configs_; - } - UniqueVector<LabelTargetPair>& forward_dependent_configs() { - return forward_dependent_configs_; - } - // Dependencies that can include files from this target. const std::set<Label>& allow_circular_includes_from() const { return allow_circular_includes_from_; @@ -260,8 +251,8 @@ // These each pull specific things from dependencies to this one when all // deps have been resolved. - void PullForwardedDependentConfigs(); - void PullForwardedDependentConfigsFrom(const Target* from); + void PullPublicConfigs(); + void PullPublicConfigsFrom(const Target* from); void PullRecursiveHardDeps(); // Fills the link and dependency output files when a target is resolved. @@ -298,7 +289,6 @@ UniqueVector<LabelConfigPair> configs_; UniqueVector<LabelConfigPair> all_dependent_configs_; UniqueVector<LabelConfigPair> public_configs_; - UniqueVector<LabelTargetPair> forward_dependent_configs_; std::set<Label> allow_circular_includes_from_;
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc index 833b382e2..366210c 100644 --- a/tools/gn/target_generator.cc +++ b/tools/gn/target_generator.cc
@@ -247,10 +247,6 @@ return false; } - // This is a list of dependent targets to have their configs fowarded, so - // it goes here rather than in FillConfigs. - if (!FillForwardDependentConfigs()) - return false; return true; } @@ -359,14 +355,3 @@ } return !err_->has_error(); } - -bool TargetGenerator::FillForwardDependentConfigs() { - const Value* value = scope_->GetValue( - variables::kForwardDependentConfigsFrom, true); - if (value) { - ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(), - ToolchainLabelForScope(scope_), - &target_->forward_dependent_configs(), err_); - } - return !err_->has_error(); -}
diff --git a/tools/gn/target_generator.h b/tools/gn/target_generator.h index 83e3af1..1fd055b1 100644 --- a/tools/gn/target_generator.h +++ b/tools/gn/target_generator.h
@@ -77,8 +77,6 @@ UniqueVector<LabelConfigPair>* dest); bool FillGenericDeps(const char* var_name, LabelTargetVector* dest); - bool FillForwardDependentConfigs(); - DISALLOW_COPY_AND_ASSIGN(TargetGenerator); };
diff --git a/tools/gn/target_unittest.cc b/tools/gn/target_unittest.cc index 1eeac254..f4acaca 100644 --- a/tools/gn/target_unittest.cc +++ b/tools/gn/target_unittest.cc
@@ -75,8 +75,7 @@ EXPECT_EQ(0u, exec.all_lib_dirs().size()); } -// Test all_dependent_configs, public_config inheritance, and -// forward_dependent_configs_from +// Test all_dependent_configs and public_config inheritance. TEST(Target, DependentConfigs) { TestWithScope setup; Err err; @@ -124,15 +123,13 @@ TestTarget b_fwd(setup, "//foo:b_fwd", Target::STATIC_LIBRARY); a_fwd.private_deps().push_back(LabelTargetPair(&b_fwd)); b_fwd.private_deps().push_back(LabelTargetPair(&c)); - b_fwd.forward_dependent_configs().push_back(LabelTargetPair(&c)); ASSERT_TRUE(b_fwd.OnResolved(&err)); ASSERT_TRUE(a_fwd.OnResolved(&err)); // A_fwd should now have both configs. - ASSERT_EQ(2u, a_fwd.configs().size()); + ASSERT_EQ(1u, a_fwd.configs().size()); EXPECT_EQ(&all, a_fwd.configs()[0].ptr); - EXPECT_EQ(&direct, a_fwd.configs()[1].ptr); ASSERT_EQ(1u, a_fwd.all_dependent_configs().size()); EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr); } @@ -387,15 +384,7 @@ // This target has a private dependency on dest for forwards configs. TestTarget forward(setup, "//a:f", Target::SOURCE_SET); forward.private_deps().push_back(LabelTargetPair(&dest)); - forward.forward_dependent_configs().push_back(LabelTargetPair(&dest)); ASSERT_TRUE(forward.OnResolved(&err)); - - // Depending on the forward target should apply the config. - TestTarget dep_on_forward(setup, "//a:dof", Target::SOURCE_SET); - dep_on_forward.private_deps().push_back(LabelTargetPair(&forward)); - ASSERT_TRUE(dep_on_forward.OnResolved(&err)); - ASSERT_EQ(1u, dep_on_forward.configs().size()); - EXPECT_EQ(&pub_config, dep_on_forward.configs()[0].ptr); } // Tests that different link/depend outputs work for solink tools.
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc index 6f9c848..d4e978d3 100644 --- a/tools/gn/variables.cc +++ b/tools/gn/variables.cc
@@ -731,54 +731,6 @@ "\n" " See also \"public_deps\" and \"data_deps\".\n"; -// TODO(brettw) remove this, deprecated. -const char kForwardDependentConfigsFrom[] = "forward_dependent_configs_from"; -const char kForwardDependentConfigsFrom_HelpShort[] = - "forward_dependent_configs_from: [label list] DEPRECATED."; -const char kForwardDependentConfigsFrom_Help[] = - "forward_dependent_configs_from\n" - "\n" - " A list of target labels.\n" - "\n" - " DEPRECATED. Use public_deps instead which will have the same effect.\n" - "\n" - " Exposes the public_configs from a private dependent target as\n" - " public_configs of the current one. Each label in this list\n" - " must also be in the deps.\n" - "\n" - " Generally you should use public_deps instead of this variable to\n" - " express the concept of exposing a dependency as part of a target's\n" - " public API. We're considering removing this variable.\n" - "\n" - "Discussion\n" - "\n" - " Sometimes you depend on a child library that exports some necessary\n" - " configuration via public_configs. If your target in turn exposes the\n" - " child library's headers in its public headers, it might mean that\n" - " targets that depend on you won't work: they'll be seeing the child\n" - " library's code but not the necessary configuration. This list\n" - " specifies which of your deps' direct dependent configs to expose as\n" - " your own.\n" - "\n" - "Examples\n" - "\n" - " If we use a given library \"a\" from our public headers:\n" - "\n" - " deps = [ \":a\", \":b\", ... ]\n" - " forward_dependent_configs_from = [ \":a\" ]\n" - "\n" - " This example makes a \"transparent\" target that forwards a dependency\n" - " to another:\n" - "\n" - " group(\"frob\") {\n" - " if (use_system_frob) {\n" - " deps = \":system_frob\"\n" - " } else {\n" - " deps = \"//third_party/fallback_frob\"\n" - " }\n" - " forward_dependent_configs_from = deps\n" - " }\n"; - const char kIncludeDirs[] = "include_dirs"; const char kIncludeDirs_HelpShort[] = "include_dirs: [directory list] Additional include directories."; @@ -1393,7 +1345,6 @@ INSERT_VARIABLE(Defines) INSERT_VARIABLE(Depfile) INSERT_VARIABLE(Deps) - INSERT_VARIABLE(ForwardDependentConfigsFrom) INSERT_VARIABLE(IncludeDirs) INSERT_VARIABLE(Inputs) INSERT_VARIABLE(Ldflags)
diff --git a/tools/gn/variables.h b/tools/gn/variables.h index a08270c6..074f731 100644 --- a/tools/gn/variables.h +++ b/tools/gn/variables.h
@@ -143,10 +143,6 @@ extern const char kDeps_HelpShort[]; extern const char kDeps_Help[]; -extern const char kForwardDependentConfigsFrom[]; -extern const char kForwardDependentConfigsFrom_HelpShort[]; -extern const char kForwardDependentConfigsFrom_Help[]; - extern const char kIncludeDirs[]; extern const char kIncludeDirs_HelpShort[]; extern const char kIncludeDirs_Help[];
diff --git a/tools/licenses.py b/tools/licenses.py index f73c323c..03c6f52 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -159,11 +159,6 @@ "License": "BSD", "License File": "/LICENSE", }, - os.path.join('third_party', 'ots'): { - "Name": "OTS (OpenType Sanitizer)", - "URL": "http://code.google.com/p/ots/", - "License": "BSD", - }, os.path.join('third_party', 'pdfium'): { "Name": "PDFium", "URL": "http://code.google.com/p/pdfium/",
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index cf6d33a..67fb575 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -60127,6 +60127,14 @@ <int value="957" label="BackspaceNavigatedBack"/> <int value="958" label="BackspaceNavigatedBackAfterFormInteraction"/> <int value="959" label="CSPSourceWildcardWouldMatchExactHost"/> + <int value="960" label="CredentialManagerGet"/> + <int value="961" label="CredentialManagerGetWithUI"/> + <int value="962" label="CredentialManagerGetWithoutUI"/> + <int value="963" label="CredentialManagerStore"/> + <int value="964" label="CredentialManagerRequireUserMediation"/> + <int value="965" label="RequestAutocomplete"/> + <int value="966" label="CastOverlayClicked"/> + <int value="967" label="CastOverlayShown"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -64095,6 +64103,7 @@ <int value="-711890895" label="enable-website-settings-manager"/> <int value="-699767107" label="enable-sync-app-list"/> <int value="-697751423" label="disable-quickoffice-component-app"/> + <int value="-684900739" label="disable-merge-key-char-events"/> <int value="-667517406" label="overscroll-history-navigation"/> <int value="-661978438" label="enable-data-reduction-proxy-lo-fi"/> <int value="-660160292" label="enable-apps-show-on-first-paint"/> @@ -64370,6 +64379,7 @@ <int value="1658644418" label="disable-app-list-voice-search"/> <int value="1661925474" label="silent-debugger-extension-api"/> <int value="1668611601" label="enable-encrypted-media"/> + <int value="1689183477" label="enable-merge-key-char-events"/> <int value="1694854500" label="disable-save-password-bubble"/> <int value="1696139514" label="enable-ble-advertising-in-apps"/> <int value="1705724232" label="use-android-midi-api"/> @@ -64400,6 +64410,7 @@ label="enable-message-center-always-scroll-up-upon-notification-removal"/> <int value="1862207743" label="enable-android-spellchecker"/> <int value="1865799183" label="javascript-harmony"/> + <int value="1881036528" label="disable-multilingual-spellchecker"/> <int value="1891210939" label="enable-blink-features"/> <int value="1892201400" label="enable-password-separated-signin-flow"/> <int value="1896456311" label="enable-password-save-in-page-navigation"/>
diff --git a/tools/perf/core/chromium_config.py b/tools/perf/core/chromium_config.py new file mode 100644 index 0000000..f7848c33 --- /dev/null +++ b/tools/perf/core/chromium_config.py
@@ -0,0 +1,38 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import logging +import os +import sys + +from core import path_util + +sys.path.append(path_util.GetTelemetryDir()) +from telemetry import project_config + + +CLIENT_CONFIG_PATH = os.path.join( + path_util.GetPerfDir(), 'core', 'binary_dependencies.json') + + +class ChromiumConfig(project_config.ProjectConfig): + def __init__(self, top_level_dir=None, benchmark_dirs=None, + client_config=CLIENT_CONFIG_PATH, + chromium_src_dir=path_util.GetChromiumSrcDir()): + + if not benchmark_dirs: + benchmark_dirs = [path_util.GetPerfBenchmarksDir()] + logging.info('No benchmark directories specified. Defaulting to %s', + benchmark_dirs) + if not top_level_dir: + top_level_dir = path_util.GetPerfDir() + logging.info('No top level directory specified. Defaulting to %s', + top_level_dir) + + super(ChromiumConfig, self).__init__( + top_level_dir=top_level_dir, benchmark_dirs=benchmark_dirs, + client_config=client_config) + + self._chromium_src_dir = chromium_src_dir +
diff --git a/tools/perf/core/path_util.py b/tools/perf/core/path_util.py index 3050c981..ee84e5c 100644 --- a/tools/perf/core/path_util.py +++ b/tools/perf/core/path_util.py
@@ -6,9 +6,18 @@ def GetChromiumSrcDir(): - return os.path.abspath(os.path.join( - os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) + return os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( + os.path.abspath(__file__))))) -def GetStorySetsDir(): - return os.path.abspath(os.path.join( - os.path.dirname(__file__), os.pardir , 'page_sets')) +def GetTelemetryDir(): + return os.path.join(GetChromiumSrcDir(), 'tools', 'telemetry') + +def GetPerfDir(): + return os.path.join(GetChromiumSrcDir(), 'tools', 'perf') + +def GetPerfStorySetsDir(): + return os.path.join(GetPerfDir(), 'page_sets') + +def GetPerfBenchmarksDir(): + return os.path.join(GetPerfDir(), 'benchmarks') +
diff --git a/tools/perf/core/project_config.py b/tools/perf/core/project_config.py deleted file mode 100644 index c4bd4a3..0000000 --- a/tools/perf/core/project_config.py +++ /dev/null
@@ -1,25 +0,0 @@ -# Copyright (c) 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import sys - - -THIS_DIR = os.path.dirname(os.path.abspath(__file__)) -TOP_LEVEL_DIR = os.path.dirname(THIS_DIR) -TELEMETRY_DIR = os.path.normpath(os.path.join( - TOP_LEVEL_DIR, os.pardir, 'telemetry')) - -sys.path.append(TELEMETRY_DIR) -from telemetry import benchmark_runner - -binary_dependencies_file = os.path.join(THIS_DIR, 'binary_dependencies.json') - -config = benchmark_runner.ProjectConfig( - top_level_dir=TOP_LEVEL_DIR, - benchmark_dirs=[os.path.join(TOP_LEVEL_DIR, 'benchmarks')], - client_config=binary_dependencies_file) - -config.telemetry_dir = TELEMETRY_DIR -
diff --git a/tools/perf/fetch_benchmark_deps_unittest.py b/tools/perf/fetch_benchmark_deps_unittest.py index 68194fd..8361e9f 100644 --- a/tools/perf/fetch_benchmark_deps_unittest.py +++ b/tools/perf/fetch_benchmark_deps_unittest.py
@@ -30,7 +30,7 @@ sys.argv = ['./fetch_benchmark_deps', ''] def _RunFetchBenchmarkDepsTest(self, benchmark_name, - expected_fetched_file_paths = None): + expected_fetched_file_paths=None): """Simulates './fetch_benchmark_deps [benchmark_name]' It checks if the paths returned are expected and have corresponding sha1 @@ -65,5 +65,8 @@ self._RunFetchBenchmarkDepsTest('media.tough_video_cases') def testFetchOctane(self): - expected = 'src/tools/perf/page_sets/data/octane_001.wpr' + octane_wpr_path = os.path.join( + os.path.dirname(__file__), 'page_sets', 'data', 'octane_001.wpr') + expected = os.path.relpath(octane_wpr_path, + fetch_benchmark_deps.GetChromiumDir()) self._RunFetchBenchmarkDepsTest('octane', NormPaths(expected))
diff --git a/tools/perf/page_sets/memory_health_story.py b/tools/perf/page_sets/memory_health_story.py index a2de9ce..79e5e6022 100644 --- a/tools/perf/page_sets/memory_health_story.py +++ b/tools/perf/page_sets/memory_health_story.py
@@ -39,11 +39,10 @@ self.archive_data_file = story_set.archive_data_file def _TakeMemoryMeasurement(self, action_runner, phase): - android_platform = action_runner.tab.browser.platform with action_runner.CreateInteraction(phase): action_runner.Wait(DUMP_WAIT_TIME) action_runner.ForceGarbageCollection() - android_platform.RelaxMemory() + action_runner.tab.browser.platform.FlushEntireSystemCache() action_runner.Wait(DUMP_WAIT_TIME) if not action_runner.tab.browser.DumpMemory(): logging.error('Unable to get a memory dump for %s.', self.name)
diff --git a/tools/perf/run_benchmark b/tools/perf/run_benchmark index 8ba812e..e1a8f1ca 100755 --- a/tools/perf/run_benchmark +++ b/tools/perf/run_benchmark
@@ -10,7 +10,8 @@ from telemetry import benchmark_runner sys.path.append(os.path.join(os.path.dirname(__file__), 'core')) -from core import project_config +from core import chromium_config if __name__ == '__main__': - sys.exit(benchmark_runner.main(project_config.config)) + config = chromium_config.ChromiumConfig() + sys.exit(benchmark_runner.main(config))
diff --git a/tools/perf/run_tests b/tools/perf/run_tests index 7522162..a7c89ab 100755 --- a/tools/perf/run_tests +++ b/tools/perf/run_tests
@@ -12,20 +12,21 @@ import subprocess import sys -from core import project_config as project_config_module +from core import chromium_config +from core import path_util if __name__ == '__main__': - project_config = project_config_module.config + project_config = chromium_config.ChromiumConfig() + telemetry_dir = path_util.GetTelemetryDir() env = os.environ.copy() if 'PYTHONPATH' in env: - env['PYTHONPATH'] = os.path.join(env['PYTHONPATH'], - project_config.telemetry_dir) + env['PYTHONPATH'] = os.path.join(env['PYTHONPATH'], telemetry_dir) else: - env['PYTHONPATH'] = project_config.telemetry_dir + env['PYTHONPATH'] = telemetry_dir path_to_run_tests = os.path.join( - project_config.telemetry_dir, 'telemetry', 'testing', 'run_tests.py') + telemetry_dir, 'telemetry', 'testing', 'run_tests.py') argv = ['--top-level-dir', project_config.top_level_dir, '--client-config', project_config.client_config] + sys.argv[1:] sys.exit(subprocess.call([sys.executable, path_to_run_tests] + argv, env=env))
diff --git a/tools/telemetry/BUILD.gn b/tools/telemetry/BUILD.gn index c6e8d0ae..4997a854c 100644 --- a/tools/telemetry/BUILD.gn +++ b/tools/telemetry/BUILD.gn
@@ -8,11 +8,7 @@ # TODO(aiolos): Remove all dependencies that Telemetry has local copies of. "//build/android/devil/", "//build/android/pylib/", - "//build/util/", - "//third_party/WebKit/PerformanceTests/resources/jquery.tablesorter.min.js", - "//third_party/WebKit/PerformanceTests/resources/statistics.js", - "//third_party/flot/jquery.flot.min.js", - "//third_party/webpagereplay/", + "//third_party/catapult/", "//tools/telemetry/", ] }
diff --git a/tools/telemetry/telemetry/core/android_platform.py b/tools/telemetry/telemetry/core/android_platform.py index a70158f..5806f394 100644 --- a/tools/telemetry/telemetry/core/android_platform.py +++ b/tools/telemetry/telemetry/core/android_platform.py
@@ -42,8 +42,3 @@ self._platform_backend, start_intent, is_app_ready_predicate, app_has_webviews) return android_app.AndroidApp(app_backend, self._platform_backend) - - def RelaxMemory(self): - """Request kernel to drop clean caches and reclaimable slab objects.""" - self._platform_backend.device.RunShellCommand( - 'echo 3 > /proc/sys/vm/drop_caches', check_return=True)
diff --git a/tools/telemetry/telemetry/timeline/tracing_category_filter.py b/tools/telemetry/telemetry/timeline/tracing_category_filter.py index 92db11c..85f79f9 100644 --- a/tools/telemetry/telemetry/timeline/tracing_category_filter.py +++ b/tools/telemetry/telemetry/timeline/tracing_category_filter.py
@@ -60,7 +60,7 @@ if '*' in filter_string or '?' in filter_string: self.contains_wildcards = True - filter_set = set(filter_string.split(',')) + filter_set = set([cf.strip() for cf in filter_string.split(',')]) for category in filter_set: if category == '': continue
diff --git a/tools/telemetry/telemetry/timeline/tracing_category_filter_unittest.py b/tools/telemetry/telemetry/timeline/tracing_category_filter_unittest.py index 8183b61..5569afa 100644 --- a/tools/telemetry/telemetry/timeline/tracing_category_filter_unittest.py +++ b/tools/telemetry/telemetry/timeline/tracing_category_filter_unittest.py
@@ -8,19 +8,27 @@ class TracingCategoryFilterTests(unittest.TestCase): - def testBasic(self): - f = tracing_category_filter.TracingCategoryFilter( - 'x,-y,disabled-by-default-z,DELAY(7;foo)') - self.assertEquals(set(['x']), set(f.included_categories)) - self.assertEquals(set(['y']), set(f.excluded_categories)) + def CheckCategoryFilters(self, cf): + self.assertEquals(set(['x']), set(cf.included_categories)) + self.assertEquals(set(['y']), set(cf.excluded_categories)) self.assertEquals(set(['disabled-by-default-z']), - set(f.disabled_by_default_categories)) - self.assertEquals(set(['DELAY(7;foo)']), set(f.synthetic_delays)) + set(cf.disabled_by_default_categories)) + self.assertEquals(set(['DELAY(7;foo)']), set(cf.synthetic_delays)) - self.assertTrue('x' in f.filter_string) + self.assertTrue('x' in cf.filter_string) self.assertEquals( 'x,disabled-by-default-z,-y,DELAY(7;foo)', - f.stable_filter_string) + cf.stable_filter_string) + + def testBasic(self): + cf = tracing_category_filter.TracingCategoryFilter( + 'x,-y,disabled-by-default-z,DELAY(7;foo)') + self.CheckCategoryFilters(cf) + + def testBasicWithSpace(self): + cf = tracing_category_filter.TracingCategoryFilter( + ' x ,\n-y\t,disabled-by-default-z ,DELAY(7;foo)') + self.CheckCategoryFilters(cf) class CategoryFilterTest(unittest.TestCase):
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc index df75bb2..e828ae08 100644 --- a/ui/base/ime/input_method_win.cc +++ b/ui/base/ime/input_method_win.cc
@@ -6,8 +6,10 @@ #include "base/auto_reset.h" #include "base/basictypes.h" +#include "base/command_line.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/win/tsf_input_scope.h" +#include "ui/base/ui_base_switches.h" #include "ui/events/event.h" #include "ui/events/event_constants.h" #include "ui/events/event_utils.h" @@ -31,8 +33,7 @@ accept_carriage_return_(false), enabled_(false), is_candidate_popup_open_(false), - composing_window_handle_(NULL), - suppress_next_char_(false) { + composing_window_handle_(NULL) { SetDelegate(delegate); } @@ -104,14 +105,41 @@ } const base::NativeEvent& native_key_event = event->native_event(); + BOOL handled = FALSE; if (native_key_event.message == WM_CHAR) { - BOOL handled; OnChar(native_key_event.hwnd, native_key_event.message, native_key_event.wParam, native_key_event.lParam, &handled); if (handled) event->StopPropagation(); return; } + + std::vector<MSG> char_msgs; + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableMergeKeyCharEvents)) { + // Combines the WM_KEY* and WM_CHAR messages in the event processing flow + // which is necessary to let Chrome IME extension to process the key event + // and perform corresponding IME actions. + // Chrome IME extension may wants to consume certain key events based on + // the character information of WM_CHAR messages. Holding WM_KEY* messages + // until WM_CHAR is processed by the IME extension is not feasible because + // there is no way to know wether there will or not be a WM_CHAR following + // the WM_KEY*. + // Chrome never handles dead chars so it is safe to remove/ignore + // WM_*DEADCHAR messages. + MSG msg; + while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, + PM_REMOVE)) { + if (msg.message == WM_CHAR) + char_msgs.push_back(msg); + } + while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR, + WM_SYSDEADCHAR, PM_REMOVE)) { + if (msg.message == WM_SYSCHAR) + char_msgs.push_back(msg); + } + } + // Handles ctrl-shift key to change text direction and layout alignment. if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && !IsTextInputTypeNone()) { @@ -135,9 +163,20 @@ } } + // If only 1 WM_CHAR per the key event, set it as the character of it. + if (char_msgs.size() == 1) + event->set_character(static_cast<base::char16>(char_msgs[0].wParam)); + ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); - if (!details.dispatcher_destroyed) - suppress_next_char_ = event->stopped_propagation(); + if (details.dispatcher_destroyed || details.target_destroyed || + event->stopped_propagation()) { + return; + } + + for (size_t i = 0; i < char_msgs.size(); ++i) { + MSG msg = char_msgs[i]; + OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, &handled); + } } void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { @@ -219,11 +258,6 @@ BOOL* handled) { *handled = TRUE; - if (suppress_next_char_) { - suppress_next_char_ = false; - return 0; - } - // We need to send character events to the focused text input client event if // its text input type is ui::TEXT_INPUT_TYPE_NONE. if (GetTextInputClient()) { @@ -554,10 +588,6 @@ void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) { if (event->is_char()) { - if (suppress_next_char_) { - suppress_next_char_ = false; - return; - } if (GetTextInputClient()) { GetTextInputClient()->InsertChar( static_cast<base::char16>(event->key_code()),
diff --git a/ui/base/ime/input_method_win.h b/ui/base/ime/input_method_win.h index 4814f269..7cc347a 100644 --- a/ui/base/ime/input_method_win.h +++ b/ui/base/ime/input_method_win.h
@@ -129,10 +129,6 @@ // composition. HWND composing_window_handle_; - // Set to true to suppress the next WM_CHAR, when the WM_KEYDOWN gets stopped - // propagation (e.g. triggered an accelerator). - bool suppress_next_char_; - DISALLOW_COPY_AND_ASSIGN(InputMethodWin); };
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index dd98536..db9c274 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc
@@ -19,6 +19,14 @@ const char kShowMacOverlayBorders[] = "show-mac-overlay-borders"; #endif +#if defined(OS_WIN) +// Disables merging the key event (WM_KEY*) with the char event (WM_CHAR). +const char kDisableMergeKeyCharEvents[] = "disable-merge-key-char-events"; + +// Enables merging the key event (WM_KEY*) with the char event (WM_CHAR). +const char kEnableMergeKeyCharEvents[] = "enable-merge-key-char-events"; +#endif + // Disables use of DWM composition for top level windows. const char kDisableDwmComposition[] = "disable-dwm-composition";
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index 5b55fa7..0c02dbc 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h
@@ -18,6 +18,11 @@ UI_BASE_EXPORT extern const char kShowMacOverlayBorders[]; #endif +#if defined(OS_WIN) +UI_BASE_EXPORT extern const char kDisableMergeKeyCharEvents[]; +UI_BASE_EXPORT extern const char kEnableMergeKeyCharEvents[]; +#endif + UI_BASE_EXPORT extern const char kDisableDwmComposition[]; UI_BASE_EXPORT extern const char kDisableIconNtp[]; UI_BASE_EXPORT extern const char kDisableTouchAdjustment[];
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc index b331017..4dca563a 100644 --- a/ui/events/blink/blink_event_util.cc +++ b/ui/events/blink/blink_event_util.cc
@@ -81,19 +81,19 @@ size_t pointer_index) { switch (event.GetToolType(pointer_index)) { case MotionEvent::TOOL_TYPE_UNKNOWN: - return WebTouchPoint::PointerTypeUnknown; + return WebTouchPoint::PointerType::Unknown; case MotionEvent::TOOL_TYPE_FINGER: - return WebTouchPoint::PointerTypeTouch; + return WebTouchPoint::PointerType::Touch; case MotionEvent::TOOL_TYPE_STYLUS: - return WebTouchPoint::PointerTypePen; + return WebTouchPoint::PointerType::Pen; case MotionEvent::TOOL_TYPE_MOUSE: - return WebTouchPoint::PointerTypeMouse; + return WebTouchPoint::PointerType::Mouse; case MotionEvent::TOOL_TYPE_ERASER: - return WebTouchPoint::PointerTypeUnknown; + return WebTouchPoint::PointerType::Unknown; } NOTREACHED() << "Invalid MotionEvent::ToolType = " << event.GetToolType(pointer_index); - return WebTouchPoint::PointerTypeUnknown; + return WebTouchPoint::PointerType::Unknown; } WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
diff --git a/ui/file_manager/file_manager/background/js/import_history.js b/ui/file_manager/file_manager/background/js/import_history.js index e51631d..9a474ba 100644 --- a/ui/file_manager/file_manager/background/js/import_history.js +++ b/ui/file_manager/file_manager/background/js/import_history.js
@@ -1033,7 +1033,6 @@ importer.DriveSyncWatcher.prototype.getSyncStatus_ = function(url) { return util.URLsToEntries([url]) .then( - /** @this {importer.DriveSyncWatcher} */ function(results) { if (results.entries.length !== 1) return Promise.reject();
diff --git a/ui/file_manager/file_manager/background/js/media_scanner.js b/ui/file_manager/file_manager/background/js/media_scanner.js index 5d47402..c55f6d6 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner.js +++ b/ui/file_manager/file_manager/background/js/media_scanner.js
@@ -204,7 +204,6 @@ return Promise.all( batch.map(handleFileEntry)) .then( - /** @this {importer.DefaultMediaScanner} */ function() { if (end < entries.length) { return scanBatch(end);
diff --git a/ui/file_manager/file_manager/background/js/test_util_base.js b/ui/file_manager/file_manager/background/js/test_util_base.js index 4eb42893e..e2e0c04 100644 --- a/ui/file_manager/file_manager/background/js/test_util_base.js +++ b/ui/file_manager/file_manager/background/js/test_util_base.js
@@ -380,10 +380,15 @@ */ test.util.sync.fakeMouseRightClick = function( contentWindow, targetQuery, opt_iframeQuery) { + var mouseDownEvent = new MouseEvent('mousedown', {bubbles: true, button: 2}); + if (!test.util.sync.sendEvent(contentWindow, targetQuery, mouseDownEvent, + opt_iframeQuery)) { + return false; + } + var contextMenuEvent = new MouseEvent('contextmenu', {bubbles: true}); - var result = test.util.sync.sendEvent( - contentWindow, targetQuery, contextMenuEvent, opt_iframeQuery); - return result; + return test.util.sync.sendEvent(contentWindow, targetQuery, contextMenuEvent, + opt_iframeQuery); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js b/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js index 62ae3d9..b46b7d15 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js +++ b/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js
@@ -136,6 +136,8 @@ this.currentDirectoryItem_.firstElementChild.querySelector('.label'); label.textContent = newName; + this.currentDirectoryItem_.entry = newEntry; + this.detach_(); // If renamed directory was current directory, change it to new one.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index b0d1a65..d6902d5 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -248,10 +248,14 @@ */ DirectoryItem.prototype.handleClick = function(e) { cr.ui.TreeItem.prototype.handleClick.call(this, e); - cr.dispatchSimpleEvent(this, 'click-tree-item', true); - if (!e.target.classList.contains('expand-icon') && this.entry) { - this.directoryModel_.activateDirectoryEntry(this.entry); + + if (!this.entry || e.button === 2 || + e.target.classList.contains('expand-icon')) { + return; } + + cr.dispatchSimpleEvent(this, 'click-tree-item', true); + this.directoryModel_.activateDirectoryEntry(this.entry); }; /** @@ -385,11 +389,7 @@ var item = new DirectoryItem(label, tree); item.__proto__ = SubDirectoryItem.prototype; - item.dirEntry_ = dirEntry; - - // Set helper attribute for testing. - if (window.IN_TEST) - item.setAttribute('full-path-for-testing', dirEntry.fullPath); + item.entry = dirEntry; // Sets up icons of the item. var icon = item.querySelector('.icon'); @@ -418,6 +418,14 @@ get entry() { return this.dirEntry_; + }, + + set entry(value) { + this.dirEntry_ = value; + + // Set helper attribute for testing. + if (window.IN_TEST) + this.setAttribute('full-path-for-testing', this.dirEntry_.fullPath); } }; @@ -773,7 +781,13 @@ */ ShortcutItem.prototype.handleClick = function(e) { cr.ui.TreeItem.prototype.handleClick.call(this, e); + + // Do not activate with right click. + if (e.button === 2) + return; + cr.dispatchSimpleEvent(this, 'click-tree-item', true); + this.activate(); // Resets file selection when a volume is clicked. this.parentTree_.directoryModel.clearSelection(); @@ -1177,12 +1191,28 @@ * @private */ DirectoryTree.prototype.onEntriesChanged_ = function(event) { - // TODO(yawano): Handle other entry change kinds. - if (event.kind !== util.EntryChangedKind.DELETED) + var directories = event.entries.filter((entry) => entry.isDirectory); + + if (directories.length === 0) return; - var directories = event.entries.filter((entry) => entry.isDirectory); - directories.forEach((directory) => this.updateTreeByEntry_(directory)); + switch (event.kind) { + case util.EntryChangedKind.CREATED: + // Handle as change event of parent entry. + Promise.all( + directories.map((directory) => + new Promise(directory.getParent.bind(directory)))) + .then(function(parentDirectories) { + parentDirectories.forEach((parentDirectory) => + this.updateTreeByEntry_(parentDirectory)); + }.bind(this)); + break; + case util.EntryChangedKind.DELETED: + directories.forEach((directory) => this.updateTreeByEntry_(directory)); + break; + default: + assertNotReached(); + } }; /**
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index fa80f31e..fbb6ec46 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -39,21 +39,73 @@ ]); /** + * Expands tree item. + */ +function expandTreeItemInDirectoryTree(windowId, query) { + return remoteCall.waitForElement(windowId, query).then(function() { + return remoteCall.callRemoteTestUtil('queryAllElements', windowId, + [`${query}[expanded]`]).then(function(elements) { + // If it's already expanded, do nothing. + if (elements.length > 0) + return; + + // Focus to directory tree. + return remoteCall.callRemoteTestUtil( + 'focus', windowId, ['#directory-tree']).then(function() { + // Expand download volume. + return remoteCall.callRemoteTestUtil('fakeMouseClick', windowId, + [`${query} .expand-icon`]); + }); + }); + }); +} + +/** + * Expands download volume in directory tree. + */ +function expandDownloadVolumeInDirectoryTree(windowId) { + return expandTreeItemInDirectoryTree( + windowId, '[volume-type-for-testing="downloads"]'); +} + +/** + * Expands directory tree for specified path. + * TODO(yawano): Move this to remote_call.js + */ +function expandDirectoryTreeFor(windowId, path) { + return expandDirectoryTreeForInternal_(windowId, path.split('/'), 0); +} + +/** + * Internal function for expanding directory tree for specified path. + */ +function expandDirectoryTreeForInternal_(windowId, components, index) { + if (index >= components.length - 1) + return Promise.resolve(); + + if (index === 0) { + return expandDownloadVolumeInDirectoryTree(windowId).then(function() { + return expandDirectoryTreeForInternal_(windowId, components, index + 1); + }); + } + + var path = `/${components.slice(1, index + 1).join('/')}`; + return expandTreeItemInDirectoryTree( + windowId, `[full-path-for-testing="${path}"]`).then(function() { + return expandDirectoryTreeForInternal_(windowId, components, index + 1); + }); +} + +/** * Navigates to specified directory on Download volume by using directory tree. */ function navigateWithDirectoryTree(windowId, path) { - // Focus to directory tree. - return remoteCall.callRemoteTestUtil( - 'focus', windowId, ['#directory-tree']).then(function() { - // Expand download volume. - return remoteCall.callRemoteTestUtil('fakeMouseClick', windowId, - ['[volume-type-for-testing="downloads"] .expand-icon']); - }).then(function() { - // Select photos directory. + return expandDirectoryTreeFor(windowId, path).then(function() { + // Select target path. return remoteCall.callRemoteTestUtil('fakeMouseClick', windowId, [`[full-path-for-testing="${path}"]`]); }).then(function() { - // Wait until Files.app is navigated to photos. + // Wait until Files.app is navigated to the path. return remoteCall.waitUntilCurrentDirectoryIsChanged( windowId, `/Downloads${path}`); }).then(function() { @@ -68,9 +120,12 @@ * Clicks context menu item of id in directory tree. */ function clickDirectoryTreeContextMenuItem(windowId, path, id) { - // Right click photos directory. - return remoteCall.callRemoteTestUtil('fakeMouseRightClick', windowId, + return remoteCall.callRemoteTestUtil('focus', windowId, [`[full-path-for-testing="${path}"]`]).then(function() { + // Right click photos directory. + return remoteCall.callRemoteTestUtil('fakeMouseRightClick', windowId, + [`[full-path-for-testing="${path}"]`]) + }).then(function() { // Wait for context menu. return remoteCall.waitForElement(windowId, `#directory-tree-context-menu > [command="#${id}"]:not([disabled])`); @@ -101,20 +156,17 @@ return remoteCall.waitForFiles(windowId, ITEMS_IN_DEST_DIR_AFTER_PASTE, {ignoreLastModifiedTime: true}); }); -}; +} /** * Rename photos directory to specified name by using directory tree. */ function renamePhotosDirectoryTo(windowId, newName, useKeyboardShortcut) { - return navigateWithDirectoryTree(windowId, '/photos').then(function() { - if (useKeyboardShortcut) { - return remoteCall.callRemoteTestUtil( - 'fakeKeyDown', windowId, ['body', 'Enter', true /* ctrl */]); - } else { - return clickDirectoryTreeContextMenuItem(windowId, '/photos', 'rename'); - } - }).then(function() { + return (useKeyboardShortcut ? + remoteCall.callRemoteTestUtil( + 'fakeKeyDown', windowId, ['body', 'Enter', true /* ctrl */]) : + clickDirectoryTreeContextMenuItem(windowId, '/photos', 'rename') + ).then(function() { return remoteCall.waitForElement(windowId, '.tree-row > input'); }).then(function() { return remoteCall.callRemoteTestUtil( @@ -133,6 +185,8 @@ var windowId; return setupForDirectoryTreeContextMenuTest().then(function(id) { windowId = id; + return navigateWithDirectoryTree(windowId, '/photos'); + }).then(function() { return renamePhotosDirectoryTo(windowId, 'New photos', useKeyboardShortcut); }).then(function() { // Confirm that current directory has moved to new folder. @@ -148,6 +202,8 @@ var windowId; return setupForDirectoryTreeContextMenuTest().then(function(id) { windowId = id; + return navigateWithDirectoryTree(windowId, '/photos'); + }).then(function() { return renamePhotosDirectoryTo(windowId, newName, false); }).then(function() { // Confirm that a dialog is shown. @@ -158,11 +214,16 @@ /** * Creates directory from directory tree. */ -function createDirectoryFromDirectoryTree(useKeyboardShortcut) { +function createDirectoryFromDirectoryTree( + useKeyboardShortcut, changeCurrentDirectory) { var windowId; return setupForDirectoryTreeContextMenuTest().then(function(id) { windowId = id; - return navigateWithDirectoryTree(windowId, '/photos'); + + if (changeCurrentDirectory) + return navigateWithDirectoryTree(windowId, '/photos'); + else + return expandDownloadVolumeInDirectoryTree(windowId); }).then(function() { if (useKeyboardShortcut) { return remoteCall.callRemoteTestUtil('fakeKeyDown', windowId, @@ -186,7 +247,7 @@ }).then(function() { // Confirm that current directory is not changed at this timing. return remoteCall.waitUntilCurrentDirectoryIsChanged( - windowId, '/Downloads/photos'); + windowId, changeCurrentDirectory ? '/Downloads/photos' : '/Downloads'); }).then(function() { // Confirm that new directory is actually created by navigating to it. return navigateWithDirectoryTree(windowId, '/photos/test'); @@ -227,6 +288,22 @@ }; /** + * Test case for copying a directory from directory tree without changing + * current directory. + */ +testcase.copyFromDirectoryTreeWithoutChaningCurrentDirectory = function() { + var windowId; + testPromise(setupForDirectoryTreeContextMenuTest().then(function(id) { + windowId = id; + return expandDownloadVolumeInDirectoryTree(windowId); + }).then(function() { + return clickDirectoryTreeContextMenuItem(windowId, '/photos', 'copy'); + }).then(function() { + return navigateToDestinationDirectoryAndTestPaste(windowId); + })); +}; + +/** * Test case for cutting a directory from directory tree by using context menu. */ testcase.cutFromDirectoryTreeWithContextMenu = function() { @@ -268,6 +345,25 @@ }; /** + * Test case for cutting a directory from directory tree without changing + * current directory. + */ +testcase.cutFromDirectoryTreeWithoutChaningCurrentDirectory = function() { + var windowId; + testPromise(setupForDirectoryTreeContextMenuTest().then(function(id) { + windowId = id; + return expandDownloadVolumeInDirectoryTree(windowId); + }).then(function() { + return clickDirectoryTreeContextMenuItem(windowId, '/photos', 'cut'); + }).then(function() { + return navigateToDestinationDirectoryAndTestPaste(windowId); + }).then(function() { + return remoteCall.waitForElementLost( + windowId, '[full-path-for-testing="/photos"]'); + })); +}; + +/** * Test case for pasting into folder from directory tree by using context menu. */ testcase.pasteIntoFolderFromDirectoryTreeWithContextMenu = function() { @@ -307,6 +403,34 @@ }; /** + * Test case for pasting into a folder from directory tree without changing + * current directory. + */ +testcase.pasteIntoFolderFromDirectoryTreeWithoutChaningCurrentDirectory = + function() { + var windowId; + testPromise(setupForDirectoryTreeContextMenuTest().then(function(id) { + windowId = id; + return expandDownloadVolumeInDirectoryTree(windowId); + }).then(function() { + return clickDirectoryTreeContextMenuItem(windowId, '/photos', 'copy'); + }).then(function() { + return clickDirectoryTreeContextMenuItem( + windowId, '/destination', 'paste-into-folder'); + }).then(function() { + return remoteCall.waitForElement(windowId, + '[full-path-for-testing="/destination"][may-have-children]'); + }).then(function() { + return remoteCall.callRemoteTestUtil('fakeMouseClick', windowId, + ['[full-path-for-testing="/destination"] .expand-icon']); + }).then(function() { + // Confirm the copied directory is added to the directory tree. + return remoteCall.waitForElement(windowId, + '[full-path-for-testing="/destination/photos"]'); + })); +}; + +/** * Test case for renaming directory from directory tree by using context menu. */ testcase.renameDirectoryFromDirectoryTreeWithContextMenu = function() { @@ -324,6 +448,31 @@ }; /** + * Test case for renaming directory from directory tree without changing current + * directory. + */ +testcase.renameDirectoryFromDirectoryTreeWithoutChangingCurrentDirectory = + function() { + var windowId; + testPromise(setupForDirectoryTreeContextMenuTest().then(function(id) { + windowId = id; + return expandDownloadVolumeInDirectoryTree(windowId); + }).then(function() { + return remoteCall.waitForElement( + windowId, '[full-path-for-testing="/photos"]'); + }).then(function() { + return renamePhotosDirectoryTo( + windowId, 'New photos', false /* Do not use keyboard shortcut. */); + }).then(function() { + return remoteCall.waitForElementLost( + windowId, '[full-path-for-testing="/photos"]'); + }).then(function() { + return remoteCall.waitForElement( + windowId, '[full-path-for-testing="/New photos"]'); + })); +}; + +/** * Test case for renaming directory to empty string. */ testcase.renameDirectoryToEmptyStringFromDirectoryTree = function() { @@ -343,7 +492,8 @@ */ testcase.createDirectoryFromDirectoryTreeWithContextMenu = function() { testPromise(createDirectoryFromDirectoryTree( - false /* do not use keyboard shortcut */)); + false /* do not use keyboard shortcut */, + true /* change current directory */)); }; /** @@ -352,5 +502,17 @@ */ testcase.createDirectoryFromDirectoryTreeWithKeyboardShortcut = function() { testPromise(createDirectoryFromDirectoryTree( - true /* use keyboard shortcut */)); + true /* use keyboard shortcut */, + true /* change current directory */)); +}; + +/** + * Test case for creating directory from directory tree without changing current + * directory. + */ +testcase.createDirectoryFromDirectoryTreeWithoutChangingCurrentDirectory = + function() { + testPromise(createDirectoryFromDirectoryTree( + false /* Do not use keyboard shortcut */, + false /* Do not change current directory */)) };
diff --git a/ui/gfx/color_palette.h b/ui/gfx/color_palette.h index 8b93e7b..c3f989f1 100644 --- a/ui/gfx/color_palette.h +++ b/ui/gfx/color_palette.h
@@ -9,11 +9,15 @@ namespace gfx { -const SkColor kAmber = SkColorSetRGB(0xFF, 0xC1, 0x07); const SkColor kChromeIconGrey = SkColorSetRGB(0x5A, 0x5A, 0x5A); -const SkColor kErrorRed = SkColorSetRGB(0xC5, 0x39, 0x29); const SkColor kGoogleBlue = SkColorSetRGB(0x42, 0x85, 0xF4); +// The number (700) refers to the shade of darkness. Each color in the MD +// palette ranges from 100-900. +const SkColor kGoogleRed700 = SkColorSetRGB(0xC5, 0x39, 0x29); +const SkColor kGoogleGreen700 = SkColorSetRGB(0x0B, 0x80, 0x43); +const SkColor kGoogleYellow700 = SkColorSetRGB(0xF0, 0x93, 0x00); + } // namespace gfx #endif // UI_GFX_COLOR_PALETTE_H_
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index 515b91b..346a4577 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -402,12 +402,15 @@ // calls NotificationList::MarkSinglePopupAsShown() and then updates the // unread count, but the whole cache will be recreated below. notification_list_->MarkSinglePopupAsShown(id, true); + } + notification_cache_.Rebuild( + notification_list_->GetVisibleNotifications(blockers_)); + + for (const auto& id : blocked_ids) { FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, OnNotificationUpdated(id)); } - notification_cache_.Rebuild( - notification_list_->GetVisibleNotifications(blockers_)); FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, OnBlockingStateChanged(blocker));
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index ad6e5e97..edbc756b 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -686,7 +686,7 @@ if (style_ == STYLE_ACTION) border->SetInsets(5, 10, 5, 10); if (invalid_) - border->SetColor(gfx::kErrorRed); + border->SetColor(gfx::kGoogleRed700); SetBorder(border.Pass()); }
diff --git a/ui/views/corewm/cursor_height_provider_win.cc b/ui/views/corewm/cursor_height_provider_win.cc index 1fde647..16d37cee 100644 --- a/ui/views/corewm/cursor_height_provider_win.cc +++ b/ui/views/corewm/cursor_height_provider_win.cc
@@ -13,8 +13,8 @@ #include "base/win/scoped_hdc.h" namespace { -typedef scoped_ptr<uint32_t> PixelData; -typedef std::map<HCURSOR, int> HeightStorage; +using PixelData = scoped_ptr<uint32_t[]>; +using HeightStorage = std::map<HCURSOR, int>; const uint32_t kBitsPeruint32 = sizeof(uint32_t) * 8; // All bits are 1 for transparent portion of monochromatic mask. @@ -26,7 +26,7 @@ const size_t KHeaderAndPalette = sizeof(BITMAPINFOHEADER) + kNumberOfColors * sizeof(RGBQUAD); -static HeightStorage* cached_heights = NULL; +HeightStorage* cached_heights = nullptr; // Extracts the pixel data of provided bitmap PixelData GetBitmapData(HBITMAP handle, const BITMAPINFO& info, HDC hdc) { @@ -38,8 +38,7 @@ // When getting pixel data palette is appended to memory pointed by // BITMAPINFO passed so allocate additional memory to store additional data. - scoped_ptr<BITMAPINFO> header( - reinterpret_cast<BITMAPINFO*>(new char[KHeaderAndPalette])); + scoped_ptr<char[]> header(new char[KHeaderAndPalette]); memcpy(header.get(), &(info.bmiHeader), sizeof(info.bmiHeader)); data.reset(new uint32_t[info.bmiHeader.biSizeImage / sizeof(uint32_t)]); @@ -49,7 +48,7 @@ 0, info.bmiHeader.biHeight, data.get(), - header.get(), + reinterpret_cast<BITMAPINFO*>(header.get()), DIB_RGB_COLORS); if (result == 0)