diff --git a/DEPS b/DEPS index 6a6a66a..2987535 100644 --- a/DEPS +++ b/DEPS
@@ -64,7 +64,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': 'f7fccbd0da7ac700e1342e18b2bd1fa82438f3fc', + 'pdfium_revision': 'e14df7d86c641a42dcea5fa0eedfa16aa49fcb92', # 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. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '299d02a80d4158fc98d2a3bfe1a04c355286aec2', + 'catapult_revision': '5366cb026ba8bca3a035199265d6d122189e88e9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -236,7 +236,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '17d9d862b82ff297f2338f36717296067b5a6952', # commit position 17066 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'a105b33da45f5d3f556e508fd7900462ababff53', # commit position 17101 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java index ba41b16..cd5e29b 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
@@ -89,7 +89,7 @@ @Override public void didFinishNavigation(final String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSamePage, boolean isFragmentNavigation, + boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, Integer pageTransition, int errorCode, String errorDescription, int httpStatusCode) { if (errorCode != 0) { didFailLoad(isInMainFrame, errorCode, errorDescription, url); @@ -108,9 +108,9 @@ if (!isInMainFrame) return; - // Only invoke the onPageCommitVisible callback when navigating to a different page, - // but not when navigating to a different fragment within the same page. - if (!isSamePage) { + // Only invoke the onPageCommitVisible callback when navigating to a different document, + // but not when navigating to a different fragment within the same document. + if (!isSameDocument) { ThreadUtils.postOnUiThread(new Runnable() { @Override public void run() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java index 2b52ee78..0db88d6 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java
@@ -89,17 +89,17 @@ boolean isInMainFrame = true; boolean isErrorPage = false; boolean hasCommitted = true; - boolean isSamePage = true; + boolean isSameDocument = true; boolean fragmentNavigation = true; int errorCode = 0; String errorDescription = ""; int httpStatusCode = 200; callCount = onPageFinishedHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSamePage, !fragmentNavigation, PageTransition.TYPED, errorCode, + hasCommitted, !isSameDocument, !fragmentNavigation, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL_WITH_FRAGMENT, isInMainFrame, - isErrorPage, hasCommitted, isSamePage, fragmentNavigation, PageTransition.TYPED, + isErrorPage, hasCommitted, isSameDocument, fragmentNavigation, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); onPageFinishedHelper.waitForCallback(callCount); assertEquals("onPageFinished should be called for main frame fragment navigations.", @@ -109,7 +109,7 @@ callCount = onPageFinishedHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSamePage, !fragmentNavigation, PageTransition.TYPED, errorCode, + hasCommitted, !isSameDocument, !fragmentNavigation, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); mWebContentsObserver.didFinishLoad(frameId, SYNC_URL, mainFrame); mWebContentsObserver.didStopLoading(SYNC_URL); @@ -129,7 +129,7 @@ boolean isInMainFrame = true; boolean isErrorPage = false; boolean hasCommitted = true; - boolean isSamePage = true; + boolean isSameDocument = true; boolean fragmentNavigation = false; int errorCode = 0; String errorDescription = ""; @@ -139,8 +139,8 @@ int callCount = doUpdateVisitedHistoryHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(nullUrl, isInMainFrame, !isErrorPage, hasCommitted, - !isSamePage, fragmentNavigation, PageTransition.TYPED, errorCode, errorDescription, - httpStatusCode); + !isSameDocument, fragmentNavigation, PageTransition.TYPED, errorCode, + errorDescription, httpStatusCode); doUpdateVisitedHistoryHelper.waitForCallback(callCount); assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); @@ -150,7 +150,7 @@ callCount = doUpdateVisitedHistoryHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSamePage, fragmentNavigation, PageTransition.TYPED, errorCode, + hasCommitted, !isSameDocument, fragmentNavigation, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); doUpdateVisitedHistoryHelper.waitForCallback(callCount); assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, @@ -161,7 +161,7 @@ callCount = doUpdateVisitedHistoryHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, isSamePage, !fragmentNavigation, PageTransition.RELOAD, errorCode, + hasCommitted, isSameDocument, !fragmentNavigation, PageTransition.RELOAD, errorCode, errorDescription, httpStatusCode); doUpdateVisitedHistoryHelper.waitForCallback(callCount); assertEquals("doUpdateVisitedHistory should be called for reloads.", callCount + 1,
diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn index ad7b762..9b3b162 100644 --- a/build/toolchain/android/BUILD.gn +++ b/build/toolchain/android/BUILD.gn
@@ -25,6 +25,9 @@ toolchain_args = invoker.toolchain_args toolchain_args.current_os = "android" + # Output linker map files for binary size analysis. + enable_linker_map = true + # Make our manually injected libs relative to the build dir. _ndk_lib = rebase_path(invoker.sysroot + "/" + invoker.lib_dir, root_build_dir)
diff --git a/build/toolchain/gcc_link_wrapper.py b/build/toolchain/gcc_link_wrapper.py index c589fe330..0e256fa 100755 --- a/build/toolchain/gcc_link_wrapper.py +++ b/build/toolchain/gcc_link_wrapper.py
@@ -15,6 +15,8 @@ import subprocess import sys +import wrapper_utils + # When running on a Windows host and using a toolchain whose tools are # actually wrapper scripts (i.e. .bat files on Windows) rather than binary @@ -37,9 +39,12 @@ help='The strip binary to run', metavar='PATH') parser.add_argument('--unstripped-file', - required=True, help='Executable file produced by linking command', metavar='FILE') + parser.add_argument('--map-file', + help=('Use --Wl,-Map to generate a map file. Will be ' + 'gzipped if extension ends with .gz'), + metavar='FILE') parser.add_argument('--output', required=True, help='Final output executable file', @@ -51,7 +56,8 @@ # Work-around for gold being slow-by-default. http://crbug.com/632230 fast_env = dict(os.environ) fast_env['LC_ALL'] = 'C' - result = subprocess.call(CommandToRun(args.command), env=fast_env) + result = wrapper_utils.RunLinkWithOptionalMapFile(args.command, env=fast_env, + map_file=args.map_file) if result != 0: return result
diff --git a/build/toolchain/gcc_solink_wrapper.py b/build/toolchain/gcc_solink_wrapper.py index 426f9d6..7efc490 100755 --- a/build/toolchain/gcc_solink_wrapper.py +++ b/build/toolchain/gcc_solink_wrapper.py
@@ -78,6 +78,10 @@ required=True, help='Output table-of-contents file', metavar='FILE') + parser.add_argument('--map-file', + help=('Use --Wl,-Map to generate a map file. Will be ' + 'gzipped if extension ends with .gz'), + metavar='FILE') parser.add_argument('--output', required=True, help='Final output shared object file', @@ -99,8 +103,10 @@ whitelist_candidates, args.resource_whitelist) # First, run the actual link. - result = subprocess.call( - wrapper_utils.CommandToRun(args.command), env=fast_env) + command = wrapper_utils.CommandToRun(args.command) + result = wrapper_utils.RunLinkWithOptionalMapFile(command, env=fast_env, + map_file=args.map_file) + if result != 0: return result
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni index b3198066..21985f8 100644 --- a/build/toolchain/gcc_toolchain.gni +++ b/build/toolchain/gcc_toolchain.gni
@@ -214,6 +214,9 @@ extra_ldflags = "" } + enable_linker_map = + defined(invoker.enable_linker_map) && invoker.enable_linker_map + # These library switches can apply to all tools below. lib_switch = "-l" lib_dir_switch = "-L" @@ -319,18 +322,27 @@ link_command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" -Wl,-soname=\"$soname\" @\"$rspfile\"" + # Generate a map file to be used for binary size analysis. + # Map file adds ~10% to the link time on a z620. + # With target_os="android", libchrome.so.map.gz is ~20MB. + map_switch = "" + if (enable_linker_map && is_official_build) { + map_file = "$unstripped_sofile.map.gz" + map_switch = " --map-file \"$map_file\"" + } + assert(defined(readelf), "to solink you must have a readelf") assert(defined(nm), "to solink you must have an nm") strip_switch = "" if (defined(invoker.strip)) { - strip_switch = "--strip=${invoker.strip}" + strip_switch = "--strip=${invoker.strip} " } # This needs a Python script to avoid using a complex shell command # requiring sh control structures, pipelines, and POSIX utilities. # The host might not have a POSIX shell and utilities (e.g. Windows). solink_wrapper = rebase_path("//build/toolchain/gcc_solink_wrapper.py") - command = "$python_path \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"$nm\" $strip_switch --sofile=\"$unstripped_sofile\" --tocfile=\"$tocfile\" --output=\"$sofile\"$whitelist_flag -- $link_command" + command = "$python_path \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"$nm\" $strip_switch--sofile=\"$unstripped_sofile\" --tocfile=\"$tocfile\"$map_switch --output=\"$sofile\"$whitelist_flag -- $link_command" rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" @@ -365,6 +377,9 @@ if (sofile != unstripped_sofile) { outputs += [ unstripped_sofile ] } + if (defined(map_file)) { + outputs += [ map_file ] + } link_output = sofile depend_output = tocfile } @@ -433,12 +448,25 @@ unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename" } - command = "$ld {{ldflags}}${extra_ldflags} -o \"$unstripped_outfile\" -Wl,--start-group @\"$rspfile\" {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postfix" - if (defined(invoker.strip)) { - link_wrapper = - rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) - command = "$python_path \"$link_wrapper\" --strip=\"${invoker.strip}\" --unstripped-file=\"$unstripped_outfile\" --output=\"$outfile\" -- $command" + # Generate a map file to be used for binary size analysis. + # Map file adds ~10% to the link time on a z620. + # With target_os="android", libchrome.so.map.gz is ~20MB. + map_switch = "" + if (enable_linker_map && is_official_build) { + map_file = "$unstripped_outfile.map.gz" + map_switch = " --map-file \"$map_file\"" } + + link_command = "$ld {{ldflags}}${extra_ldflags} -o \"$unstripped_outfile\" -Wl,--start-group @\"$rspfile\" {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postfix" + + strip_switch = "" + if (defined(invoker.strip)) { + strip_switch = " --strip=\"${invoker.strip}\" --unstripped-file=\"$unstripped_outfile\"" + } + + link_wrapper = + rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) + command = "$python_path \"$link_wrapper\" --output=\"$outfile\"$strip_switch$map_switch -- $link_command" description = "LINK $outfile" rspfile_content = "{{inputs}}" outputs = [ @@ -450,6 +478,9 @@ if (defined(invoker.link_outputs)) { outputs += invoker.link_outputs } + if (defined(map_file)) { + outputs += [ map_file ] + } } # These two are really entirely generic, but have to be repeated in @@ -511,7 +542,11 @@ ar = "${toolprefix}ar" nm = "${toolprefix}nm" - forward_variables_from(invoker, [ "strip" ]) + forward_variables_from(invoker, + [ + "enable_linker_map", + "strip", + ]) toolchain_args = { if (defined(invoker.toolchain_args)) {
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn index 86cd7da..3be5c36 100644 --- a/build/toolchain/linux/BUILD.gn +++ b/build/toolchain/linux/BUILD.gn
@@ -58,6 +58,9 @@ } clang_toolchain("clang_x86") { + # Output linker map files for binary size analysis. + enable_linker_map = true + toolchain_args = { current_cpu = "x86" current_os = "linux" @@ -89,6 +92,9 @@ ar = "ar" ld = cxx + # Output linker map files for binary size analysis. + enable_linker_map = true + toolchain_args = { current_cpu = "x86" current_os = "linux" @@ -97,6 +103,9 @@ } clang_toolchain("clang_x64") { + # Output linker map files for binary size analysis. + enable_linker_map = true + toolchain_args = { current_cpu = "x64" current_os = "linux" @@ -128,6 +137,9 @@ ar = "ar" ld = cxx + # Output linker map files for binary size analysis. + enable_linker_map = true + toolchain_args = { current_cpu = "x64" current_os = "linux"
diff --git a/build/toolchain/wrapper_utils.py b/build/toolchain/wrapper_utils.py index 467d85d9..f76192e2 100644 --- a/build/toolchain/wrapper_utils.py +++ b/build/toolchain/wrapper_utils.py
@@ -4,16 +4,31 @@ """Helper functions for gcc_toolchain.gni wrappers.""" +import gzip import os import re import subprocess import shlex +import shutil import sys +import threading _BAT_PREFIX = 'cmd /c call ' _WHITELIST_RE = re.compile('whitelisted_resource_(?P<resource_id>[0-9]+)') +def _GzipThenDelete(src_path, dest_path): + # Results for Android map file with GCC on a z620: + # Uncompressed: 207MB + # gzip -9: 16.4MB, takes 8.7 seconds. + # gzip -1: 21.8MB, takes 2.0 seconds. + # Piping directly from the linker via -print-map (or via -Map with a fifo) + # adds a whopping 30-45 seconds! + with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path, 'wb', 1) as f_out: + shutil.copyfileobj(f_in, f_out) + os.unlink(src_path) + + def CommandToRun(command): """Generates commands compatible with Windows. @@ -36,6 +51,37 @@ return command +def RunLinkWithOptionalMapFile(command, env=None, map_file=None): + """Runs the given command, adding in -Wl,-Map when |map_file| is given. + + Also takes care of gzipping when |map_file| ends with .gz. + + Args: + command: List of arguments comprising the command. + env: Environment variables. + map_file: Path to output map_file. + + Returns: + The exit code of running |command|. + """ + tmp_map_path = None + if map_file and map_file.endswith('.gz'): + tmp_map_path = map_file + '.tmp' + command.append('-Wl,-Map,' + tmp_map_path) + elif map_file: + command.append('-Wl,-Map,' + map_file) + + result = subprocess.call(command, env=env) + + if tmp_map_path and result == 0: + threading.Thread( + target=lambda: _GzipThenDelete(tmp_map_path, map_file)).start() + elif tmp_map_path and os.path.exists(tmp_map_path): + os.unlink(tmp_map_path) + + return result + + def ResolveRspLinks(inputs): """Return a list of files contained in a response file.
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index bd3d966..c8557607 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc
@@ -1321,8 +1321,13 @@ } void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) { - gfx::RectF tex_rect(params->src_offset.x(), params->src_offset.y(), - params->dst_rect.width(), params->dst_rect.height()); + gfx::RectF tex_rect = params->quad->tex_coord_rect; + if (tex_rect.IsEmpty()) { + // TODO(sunxd): make this never be empty. + tex_rect = + gfx::RectF(gfx::PointF(params->src_offset), params->dst_rect.size()); + } + gfx::Size texture_size; if (params->filter_image) { texture_size.set_width(params->filter_image->width()); @@ -1362,25 +1367,23 @@ mask_uv_rect.Scale(params->quad->mask_texture_size.width(), params->quad->mask_texture_size.height()); } + + SkMatrix tex_to_mask = SkMatrix::MakeRectToRect(RectFToSkRect(tex_rect), + RectFToSkRect(mask_uv_rect), + SkMatrix::kFill_ScaleToFit); + if (params->source_needs_flip) { // Mask textures are oriented vertically flipped relative to the // framebuffer and the RenderPass contents texture, so we flip the tex // coords from the RenderPass texture to find the mask texture coords. - gl_->Uniform2f( - current_program_->mask_tex_coord_offset_location(), mask_uv_rect.x(), - mask_uv_rect.height() / tex_rect.height() + mask_uv_rect.y()); - gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), - mask_uv_rect.width() / tex_rect.width(), - -mask_uv_rect.height() / tex_rect.height()); - } else { - // Tile textures are oriented the same way as mask textures. - gl_->Uniform2f(current_program_->mask_tex_coord_offset_location(), - mask_uv_rect.x(), mask_uv_rect.y()); - gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), - mask_uv_rect.width() / tex_rect.width(), - mask_uv_rect.height() / tex_rect.height()); + tex_to_mask.preTranslate(0, 1); + tex_to_mask.preScale(1, -1); } + gl_->Uniform2f(current_program_->mask_tex_coord_offset_location(), + tex_to_mask.getTranslateX(), tex_to_mask.getTranslateY()); + gl_->Uniform2f(current_program_->mask_tex_coord_scale_location(), + tex_to_mask.getScaleX(), tex_to_mask.getScaleY()); last_texture_unit = 1; }
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index 97137ca..dfd32560 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -460,7 +460,11 @@ SkRect dest_visible_rect = gfx::RectFToSkRect( MathUtil::ScaleRectProportional(QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect))); - SkRect content_rect = SkRect::MakeWH(quad->rect.width(), quad->rect.height()); + // TODO(sunxd): make this never be empty. + SkRect content_rect = + quad->tex_coord_rect.IsEmpty() + ? SkRect::MakeWH(quad->rect.width(), quad->rect.height()) + : RectFToSkRect(quad->tex_coord_rect); const SkBitmap* content = lock.sk_bitmap();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java index 13db5a4..7c98a93 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java
@@ -14,8 +14,8 @@ * DownloadManager must be queried for the correct status. */ public class DownloadItem { + public static final int INDETERMINATE_DOWNLOAD_PERCENTAGE = -1; static final long INVALID_DOWNLOAD_ID = -1L; - static final int INVALID_DOWNLOAD_PERCENTAGE = -1; private boolean mUseAndroidDownloadManager; private DownloadInfo mDownloadInfo; @@ -128,6 +128,6 @@ * @return Whether or not the download has an indeterminate percentage. */ public boolean isIndeterminate() { - return getDownloadInfo().getPercentCompleted() == INVALID_DOWNLOAD_PERCENTAGE; + return getDownloadInfo().getPercentCompleted() == INDETERMINATE_DOWNLOAD_PERCENTAGE; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index 94b4da7..c106e2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -691,7 +691,7 @@ private void notifyDownloadPending(String downloadGuid, String fileName, boolean isOffTheRecord, boolean canDownloadWhileMetered, boolean isOfflinePage) { updateActiveDownloadNotification(downloadGuid, fileName, - DownloadItem.INVALID_DOWNLOAD_PERCENTAGE, 0, 0, 0, isOffTheRecord, + DownloadItem.INDETERMINATE_DOWNLOAD_PERCENTAGE, 0, 0, 0, isOffTheRecord, canDownloadWhileMetered, isOfflinePage, true); } @@ -715,7 +715,7 @@ boolean isOffTheRecord, boolean canDownloadWhileMetered, boolean isOfflinePage, boolean isDownloadPending) { boolean indeterminate = - (percentage == DownloadItem.INVALID_DOWNLOAD_PERCENTAGE) || isDownloadPending; + (percentage == DownloadItem.INDETERMINATE_DOWNLOAD_PERCENTAGE) || isDownloadPending; String contentText = null; if (isDownloadPending) { contentText = mContext.getResources().getString(R.string.download_notification_pending);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java index 8c914b1..8bd7568 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java
@@ -63,7 +63,7 @@ Bundle taskExtras, Callback<Boolean> callback) { TriggerConditions triggerConditions = TaskExtrasPacker.unpackTriggerConditionsFromBundle(taskExtras); - DeviceConditions currentConditions = OfflinePageUtils.getDeviceConditions(context); + DeviceConditions currentConditions = DeviceConditions.getCurrentConditions(context); if (!currentConditions.isPowerConnected() && currentConditions.getBatteryPercentage() < triggerConditions.getMinimumBatteryPercentage()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java index 5f6da12..66d0493 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundScheduler.java
@@ -72,25 +72,4 @@ protected Context getContext() { return mContext; } - - /** - * Get the latest power conditions from the android APIs. - */ - public static boolean getPowerConditions(Context context) { - return OfflinePageUtils.getPowerConditions(context); - } - - /** - * Get the latest battery conditions from the android APIs. - */ - public static int getBatteryConditions(Context context) { - return OfflinePageUtils.getBatteryConditions(context); - } - - /** - * Get the latest network conditions from the android APIs. - */ - public static int getNetworkConditions(Context context) { - return OfflinePageUtils.getNetworkConditions(context); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerBridge.java index 1ed08e9..cf09c6a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerBridge.java
@@ -59,17 +59,17 @@ @CalledByNative private static boolean getPowerConditions() { - return BackgroundScheduler.getPowerConditions(ContextUtils.getApplicationContext()); + return DeviceConditions.isPowerConnected(ContextUtils.getApplicationContext()); } @CalledByNative private static int getBatteryConditions() { - return BackgroundScheduler.getBatteryConditions(ContextUtils.getApplicationContext()); + return DeviceConditions.getBatteryPercentage(ContextUtils.getApplicationContext()); } @CalledByNative private static int getNetworkConditions() { - return BackgroundScheduler.getNetworkConditions(ContextUtils.getApplicationContext()); + return DeviceConditions.getNetConnectionType(ContextUtils.getApplicationContext()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/DeviceConditions.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/DeviceConditions.java index 1386f00..1b617b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/DeviceConditions.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/DeviceConditions.java
@@ -4,6 +4,17 @@ package org.chromium.chrome.browser.offlinepages; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.BatteryManager; + +import org.chromium.base.VisibleForTesting; +import org.chromium.net.ConnectionType; +import org.chromium.net.NetworkChangeNotifier; + /** Device network and power conditions. */ public class DeviceConditions { private final boolean mPowerConnected; @@ -22,6 +33,40 @@ mNetConnectionType = netConnectionType; } + @VisibleForTesting + DeviceConditions() { + mPowerConnected = false; + mBatteryPercentage = 0; + mNetConnectionType = ConnectionType.CONNECTION_NONE; + } + + /** Returns the current device conditions. May be overridden for testing. */ + public static DeviceConditions getCurrentConditions(Context context) { + Intent batteryStatus = getBatteryStatus(context); + if (batteryStatus == null) return null; + + return new DeviceConditions(isPowerConnected(batteryStatus), + getBatteryPercentage(batteryStatus), getConnectionType(context)); + } + + /** @return Whether power is connected. */ + public static boolean isPowerConnected(Context context) { + return isPowerConnected(getBatteryStatus(context)); + } + + /** @return Battery percentage. */ + public static int getBatteryPercentage(Context context) { + return getBatteryPercentage(getBatteryStatus(context)); + } + + /** + * @return Network connection type, where possible values are defined by + * org.chromium.net.ConnectionType. + */ + public static int getNetConnectionType(Context context) { + return getConnectionType(context); + } + /** @return Whether power is connected. */ public boolean isPowerConnected() { return mPowerConnected; @@ -39,4 +84,68 @@ public int getNetConnectionType() { return mNetConnectionType; } + + private static Intent getBatteryStatus(Context context) { + IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + // Note this is a sticky intent, so we aren't really registering a receiver, just getting + // the sticky intent. That means that we don't need to unregister the filter later. + return context.registerReceiver(null, filter); + } + + private static boolean isPowerConnected(Intent batteryStatus) { + if (batteryStatus == null) return false; + + int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + boolean isConnected = (status == BatteryManager.BATTERY_STATUS_CHARGING + || status == BatteryManager.BATTERY_STATUS_FULL); + return isConnected; + } + + private static int getBatteryPercentage(Intent batteryStatus) { + if (batteryStatus == null) return 0; + + int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + if (scale == 0) return 0; + + int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int percentage = Math.round(100 * level / (float) scale); + return percentage; + } + + private static int getConnectionType(Context context) { + // Get the connection type from chromium's internal object. + int connectionType = NetworkChangeNotifier.getInstance().getCurrentConnectionType(); + + // Sometimes the NetworkConnectionNotifier lags the actual connection type, especially when + // the GCM NM wakes us from doze state. If we are really connected, report the connection + // type from android. + if (connectionType == ConnectionType.CONNECTION_NONE) { + // Get the connection type from android in case chromium's type is not yet set. + ConnectivityManager cm = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); + if (isConnected) { + connectionType = convertAndroidNetworkTypeToConnectionType(activeNetwork.getType()); + } + } + return connectionType; + } + + /** Returns the NCN network type corresponding to the connectivity manager network type */ + private static int convertAndroidNetworkTypeToConnectionType( + int connectivityManagerNetworkType) { + if (connectivityManagerNetworkType == ConnectivityManager.TYPE_WIFI) { + return ConnectionType.CONNECTION_WIFI; + } + // for mobile, we don't know if it is 2G, 3G, or 4G, default to worst case of 2G. + if (connectivityManagerNetworkType == ConnectivityManager.TYPE_MOBILE) { + return ConnectionType.CONNECTION_2G; + } + if (connectivityManagerNetworkType == ConnectivityManager.TYPE_BLUETOOTH) { + return ConnectionType.CONNECTION_BLUETOOTH; + } + // Since NetworkConnectivityManager doesn't understand the other types, call them UNKNOWN. + return ConnectionType.CONNECTION_UNKNOWN; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index 0435dd7..e839170 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -6,13 +6,8 @@ import android.app.Activity; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.net.Uri; import android.os.AsyncTask; -import android.os.BatteryManager; import android.os.Environment; import org.chromium.base.ActivityState; @@ -251,41 +246,11 @@ } /** - * Returns a class encapsulating the current power, battery, and network conditions. - */ - public static DeviceConditions getDeviceConditions(Context context) { - return getInstance().getDeviceConditionsImpl(context); - } - - /** - * Return true if the device is plugged into wall power. - */ - public static boolean getPowerConditions(Context context) { - // TODO(petewil): refactor to get power, network, and battery directly from both here and - // getDeviceConditionsImpl instead of always making a DeviceConditions object. - return getInstance().getDeviceConditionsImpl(context).isPowerConnected(); - } - - /** - * Get the percentage of battery remaining - */ - public static int getBatteryConditions(Context context) { - return getInstance().getDeviceConditionsImpl(context).getBatteryPercentage(); - } - - /** - * Returns an enum representing the type of the network connection. - */ - public static int getNetworkConditions(Context context) { - return getInstance().getDeviceConditionsImpl(context).getNetConnectionType(); - } - - /** * Records UMA data when the Offline Pages Background Load service awakens. * @param context android context */ public static void recordWakeupUMA(Context context, long taskScheduledTimeMillis) { - DeviceConditions deviceConditions = getDeviceConditions(context); + DeviceConditions deviceConditions = DeviceConditions.getCurrentConditions(context); if (deviceConditions == null) return; // Report charging state. @@ -649,73 +614,10 @@ tab.loadUrl(params); } - private static boolean isPowerConnected(Intent batteryStatus) { - int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); - boolean isConnected = (status == BatteryManager.BATTERY_STATUS_CHARGING - || status == BatteryManager.BATTERY_STATUS_FULL); - Log.d(TAG, "Power connected is " + isConnected); - return isConnected; - } - - private static int batteryPercentage(Intent batteryStatus) { - int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); - int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); - if (scale == 0) return 0; - - int percentage = Math.round(100 * level / (float) scale); - Log.d(TAG, "Battery Percentage is " + percentage); - return percentage; - } - protected OfflinePageBridge getOfflinePageBridge(Profile profile) { return OfflinePageBridge.getForProfile(profile); } - /** Returns the current device conditions. May be overridden for testing. */ - protected DeviceConditions getDeviceConditionsImpl(Context context) { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - // Note this is a sticky intent, so we aren't really registering a receiver, just getting - // the sticky intent. That means that we don't need to unregister the filter later. - Intent batteryStatus = context.registerReceiver(null, filter); - if (batteryStatus == null) return null; - - // Get the connection type from chromium's internal object. - int connectionType = NetworkChangeNotifier.getInstance().getCurrentConnectionType(); - - // Sometimes the NetworkConnectionNotifier lags the actual connection type, especially when - // the GCM NM wakes us from doze state. If we are really connected, report the connection - // type from android. - if (connectionType == ConnectionType.CONNECTION_NONE) { - // Get the connection type from android in case chromium's type is not yet set. - ConnectivityManager cm = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); - if (isConnected) { - connectionType = convertAndroidNetworkTypeToConnectionType(activeNetwork.getType()); - } - } - - return new DeviceConditions( - isPowerConnected(batteryStatus), batteryPercentage(batteryStatus), connectionType); - } - - /** Returns the NCN network type corresponding to the connectivity manager network type */ - protected int convertAndroidNetworkTypeToConnectionType(int connectivityManagerNetworkType) { - if (connectivityManagerNetworkType == ConnectivityManager.TYPE_WIFI) { - return ConnectionType.CONNECTION_WIFI; - } - // for mobile, we don't know if it is 2G, 3G, or 4G, default to worst case of 2G. - if (connectivityManagerNetworkType == ConnectivityManager.TYPE_MOBILE) { - return ConnectionType.CONNECTION_2G; - } - if (connectivityManagerNetworkType == ConnectivityManager.TYPE_BLUETOOTH) { - return ConnectionType.CONNECTION_BLUETOOTH; - } - // Since NetworkConnectivityManager doesn't understand the other types, call them UNKNOWN. - return ConnectionType.CONNECTION_UNKNOWN; - } - /** * Tracks tab creation and closure for the Recent Tabs feature. UI needs to stop showing * recent offline pages as soon as the tab is closed. The TabModel is used to get profile
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageNotificationBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageNotificationBridge.java index 08fe717d..2f132b6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageNotificationBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageNotificationBridge.java
@@ -70,20 +70,20 @@ * @param displayName Name to be displayed on notification. */ @CalledByNative - public static void notifyDownloadProgress( - Context context, String guid, String url, long startTime, String displayName) { + public static void notifyDownloadProgress(Context context, String guid, String url, + long startTime, long bytesReceived, String displayName) { DownloadNotifier notifier = getDownloadNotifier(context); if (notifier == null) return; - // Use -1 percentage for interdeterminate progress bar (until we have better value). - // TODO(qinmin): get the download percentage from native code, - int percentage = -1; + int percentage = + org.chromium.chrome.browser.download.DownloadItem.INDETERMINATE_DOWNLOAD_PERCENTAGE; DownloadInfo downloadInfo = new DownloadInfo.Builder() .setIsOfflinePage(true) .setDownloadGuid(guid) .setFileName(displayName) .setFilePath(url) .setPercentCompleted(percentage) + .setBytesReceived(bytesReceived) .setIsOffTheRecord(false) .setIsResumable(true) .setTimeRemainingInMillis(0)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java index ab71ba6..0de7dac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
@@ -69,6 +69,10 @@ adapter.refreshSuggestions(); } }); + + if (activity.getBottomSheet().getSheetState() != BottomSheet.SHEET_STATE_PEEK) { + adapter.refreshSuggestions(); + } } @Override
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 0278124a..8c8e7e5 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1599,6 +1599,7 @@ "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java", "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java", + "junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java", "junit/src/org/chromium/chrome/browser/offlinepages/ShadowGcmNetworkManager.java", "junit/src/org/chromium/chrome/browser/offlinepages/ShadowGoogleApiAvailability.java", "junit/src/org/chromium/chrome/browser/offlinepages/StubBackgroundSchedulerProcessor.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java index d09cfd91..8fbd78b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
@@ -10,8 +10,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.when; import android.app.Activity; import android.content.Context; @@ -25,8 +23,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.internal.ShadowExtractor; @@ -47,7 +43,8 @@ */ @RunWith(OfflinePageTestRunner.class) @Config(manifest = Config.NONE, application = BaseChromiumApplication.class, - shadows = {ShadowGcmNetworkManager.class, ShadowGoogleApiAvailability.class}) + shadows = {ShadowGcmNetworkManager.class, ShadowGoogleApiAvailability.class, + ShadowDeviceConditions.class}) public class BackgroundOfflinerTaskTest { private static final boolean REQUIRE_POWER = true; private static final boolean REQUIRE_UNMETERED = true; @@ -59,9 +56,6 @@ @Rule public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule(); - @Mock - private OfflinePageUtils mOfflinePageUtils; - private Bundle mTaskExtras; private long mTestTime; private StubBackgroundSchedulerProcessor mStubBackgroundSchedulerProcessor; @@ -76,16 +70,13 @@ @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class))) - .thenReturn(mDeviceConditions); + ShadowDeviceConditions.setCurrentConditions(mDeviceConditions); // Build a bundle with trigger conditions. mTaskExtras = new Bundle(); TaskExtrasPacker.packTimeInBundle(mTaskExtras); TaskExtrasPacker.packTriggerConditionsInBundle(mTaskExtras, mTriggerConditions); - OfflinePageUtils.setInstanceForTesting(mOfflinePageUtils); mStubBackgroundSchedulerProcessor = new StubBackgroundSchedulerProcessor(); mContext = RuntimeEnvironment.application; mGcmNetworkManager = (ShadowGcmNetworkManager) ShadowExtractor.extract( @@ -161,8 +152,7 @@ // Setup low battery conditions. DeviceConditions deviceConditionsLowBattery = new DeviceConditions( !POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI); - when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class))) - .thenReturn(deviceConditionsLowBattery); + ShadowDeviceConditions.setCurrentConditions(deviceConditionsLowBattery); BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor); ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1); @@ -182,8 +172,7 @@ // Now verify low battery level but with power connected will start processing. DeviceConditions deviceConditionsPowerConnected = new DeviceConditions( POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI); - when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class))) - .thenReturn(deviceConditionsPowerConnected); + ShadowDeviceConditions.setCurrentConditions(deviceConditionsPowerConnected); BackgroundOfflinerTask task2 = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java index 177b962..56367ba 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTestRunner.java
@@ -27,6 +27,7 @@ InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder(); builder.addInstrumentedPackage("com.google.android.gms.common"); builder.addInstrumentedPackage("com.google.android.gms.gcm"); + builder.addInstrumentedClass("org.chromium.chrome.browser.offlinepages.DeviceConditions"); return builder.build(); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java new file mode 100644 index 0000000..0862b55 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java
@@ -0,0 +1,42 @@ +// Copyright 2017 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.offlinepages; + +import android.content.Context; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +/** Custom shadow for the OfflinePageUtils. */ +@Implements(DeviceConditions.class) +public class ShadowDeviceConditions { + /** Device conditions for testing. */ + private static DeviceConditions sDeviceConditions = new DeviceConditions(); + + /** Sets device conditions that will be used in test. */ + public static void setCurrentConditions(DeviceConditions deviceConditions) { + sDeviceConditions = deviceConditions; + } + + @Implementation + public static DeviceConditions getCurrentConditions(Context context) { + return sDeviceConditions; + } + + @Implementation + public static boolean isPowerConnected(Context context) { + return sDeviceConditions.isPowerConnected(); + } + + @Implementation + public static int getBatteryPercentage(Context context) { + return sDeviceConditions.getBatteryPercentage(); + } + + @Implementation + public static int getNetConnectionType(Context context) { + return sDeviceConditions.getNetConnectionType(); + } +}
diff --git a/chrome/app/nibs/BUILD.gn b/chrome/app/nibs/BUILD.gn index 744ef8c0..9f7f106 100644 --- a/chrome/app/nibs/BUILD.gn +++ b/chrome/app/nibs/BUILD.gn
@@ -9,7 +9,6 @@ translated_xibs = [ "AppMenu.xib", "BookmarkAllTabs.xib", - "BookmarkBar.xib", "BookmarkBubble.xib", "BookmarkEditor.xib", "BookmarkNameFolder.xib",
diff --git a/chrome/app/nibs/BookmarkBar.xib b/chrome/app/nibs/BookmarkBar.xib deleted file mode 100644 index a3d01fad..0000000 --- a/chrome/app/nibs/BookmarkBar.xib +++ /dev/null
@@ -1,96 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> - <dependencies> - <deployment version="1090" identifier="macosx"/> - <development version="5100" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> - </dependencies> - <objects> - <customObject id="-2" userLabel="File's Owner" customClass="BookmarkBarController"> - <connections> - <outlet property="buttonView_" destination="62" id="65"/> - <outlet property="offTheSideButton_" destination="63" id="66"/> - <outlet property="view" destination="1" id="93"/> - </connections> - </customObject> - <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> - <customObject id="-3" userLabel="Application"/> - <customView hidden="YES" id="1" customClass="BookmarkBarToolbarView"> - <rect key="frame" x="0.0" y="0.0" width="600" height="142"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> - <subviews> - <button id="63" customClass="BookmarkButton"> - <rect key="frame" x="586" y="2" width="20" height="24"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" heightSizable="YES"/> - <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="64" customClass="OffTheSideButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - </buttonCell> - <connections> - <action selector="openOffTheSideFolderFromButton:" target="-2" id="119"/> - <outlet property="delegate_" destination="-2" id="137"/> - </connections> - </button> - <customView id="62" customClass="BookmarkBarView"> - <rect key="frame" x="0.0" y="-2" width="584" height="144"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/> - <subviews> - <customView hidden="YES" id="109" customClass="GTMWidthBasedTweaker"> - <rect key="frame" x="0.0" y="103" width="596" height="41"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/> - <subviews> - <button id="106"> - <rect key="frame" x="177" y="20" width="199" height="14"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/> - <buttonCell key="cell" type="square" title="^IDS_BOOKMARK_BAR_IMPORT_LINK" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="left" controlSize="small" lineBreakMode="truncatingTail" imageScaling="proportionallyDown" inset="2" id="107" customClass="HyperlinkButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="smallSystem"/> - </buttonCell> - <connections> - <action selector="importBookmarks:" target="-2" id="116"/> - </connections> - </button> - <textField verticalHuggingPriority="750" id="82" customClass="NSTextField"> - <rect key="frame" x="5" y="20" width="167" height="14"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES"/> - <textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" enabled="NO" sendsActionOnEndEditing="YES" title="^IDS_BOOKMARKS_NO_ITEMS" id="83"> - <font key="font" metaFont="smallSystem"/> - <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - <connections> - <outlet property="barView_" destination="62" id="139"/> - </connections> - </textField> - </subviews> - <connections> - <outlet property="barView_" destination="62" id="140"/> - </connections> - </customView> - </subviews> - <connections> - <outlet property="controller_" destination="-2" id="95"/> - <outlet property="importBookmarksButton_" destination="106" id="136"/> - <outlet property="noItemContainer" destination="109" id="117"/> - <outlet property="noItemTextfield_" destination="82" id="87"/> - </connections> - </customView> - </subviews> - <connections> - <outlet property="controller_" destination="-2" id="92"/> - <outlet property="delegate_" destination="-2" id="101"/> - </connections> - </customView> - <customObject id="72" customClass="ChromeUILocalizer"> - <connections> - <outlet property="owner_" destination="-2" id="86"/> - </connections> - </customObject> - <customObject id="110" customClass="GTMUILocalizerAndLayoutTweaker"> - <connections> - <outlet property="localizerOwner_" destination="-2" id="111"/> - <outlet property="localizer_" destination="72" id="113"/> - <outlet property="uiObject_" destination="62" id="112"/> - </connections> - </customObject> - </objects> -</document>
diff --git a/chrome/browser/android/offline_pages/background_loader_offliner.cc b/chrome/browser/android/offline_pages/background_loader_offliner.cc index 05d4a4b..07b32f9 100644 --- a/chrome/browser/android/offline_pages/background_loader_offliner.cc +++ b/chrome/browser/android/offline_pages/background_loader_offliner.cc
@@ -39,9 +39,13 @@ BackgroundLoaderOffliner::~BackgroundLoaderOffliner() {} -bool BackgroundLoaderOffliner::LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) { - DCHECK(callback); +// TODO(dimich): Invoke progress_callback as appropriate. +bool BackgroundLoaderOffliner::LoadAndSave( + const SavePageRequest& request, + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) { + DCHECK(completion_callback); + DCHECK(progress_callback); if (pending_request_) { DVLOG(1) << "Already have pending request"; @@ -104,7 +108,7 @@ // Track copy of pending request. pending_request_.reset(new SavePageRequest(request)); - completion_callback_ = callback; + completion_callback_ = completion_callback; // Listen for app foreground/background change. app_listener_.reset(new base::android::ApplicationStatusListener(
diff --git a/chrome/browser/android/offline_pages/background_loader_offliner.h b/chrome/browser/android/offline_pages/background_loader_offliner.h index 04572def..f1b611b 100644 --- a/chrome/browser/android/offline_pages/background_loader_offliner.h +++ b/chrome/browser/android/offline_pages/background_loader_offliner.h
@@ -36,7 +36,8 @@ // Offliner implementation. bool LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) override; + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) override; void Cancel(const CancelCallback& callback) override; bool HandleTimeout(const SavePageRequest& request) override;
diff --git a/chrome/browser/android/offline_pages/background_loader_offliner_unittest.cc b/chrome/browser/android/offline_pages/background_loader_offliner_unittest.cc index 0b4e691c..6cc39f2 100644 --- a/chrome/browser/android/offline_pages/background_loader_offliner_unittest.cc +++ b/chrome/browser/android/offline_pages/background_loader_offliner_unittest.cc
@@ -126,10 +126,14 @@ void SetUp() override; TestBackgroundLoaderOffliner* offliner() const { return offliner_.get(); } - Offliner::CompletionCallback const callback() { + Offliner::CompletionCallback const completion_callback() { return base::Bind(&BackgroundLoaderOfflinerTest::OnCompletion, base::Unretained(this)); } + Offliner::ProgressCallback const progress_callback() { + return base::Bind(&BackgroundLoaderOfflinerTest::OnProgress, + base::Unretained(this)); + } Offliner::CancelCallback const cancel_callback() { return base::Bind(&BackgroundLoaderOfflinerTest::OnCancel, base::Unretained(this)); @@ -153,6 +157,7 @@ private: void OnCompletion(const SavePageRequest& request, Offliner::RequestStatus status); + void OnProgress(const SavePageRequest& request, int64_t bytes); void OnCancel(int64_t offline_id); content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; @@ -188,6 +193,9 @@ request_status_ = status; } +void BackgroundLoaderOfflinerTest::OnProgress(const SavePageRequest& request, + int64_t bytes) {} + void BackgroundLoaderOfflinerTest::OnCancel(int64_t offline_id) { DCHECK(!cancel_callback_called_); cancel_callback_called_ = true; @@ -201,7 +209,8 @@ creation_time, kUserRequested); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); histograms().ExpectBucketCount( "OfflinePages.Background.CctApiDisableStatus", static_cast<int>(OfflinePagesCctApiPrerenderAllowedStatus:: @@ -221,7 +230,8 @@ profile()->GetPrefs()->SetInteger( prefs::kNetworkPredictionOptions, chrome_browser_net::NETWORK_PREDICTION_NEVER); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); histograms().ExpectBucketCount( "OfflinePages.Background.CctApiDisableStatus", static_cast<int>(OfflinePagesCctApiPrerenderAllowedStatus:: @@ -238,7 +248,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_TRUE(offliner()->is_loading()); EXPECT_FALSE(SaveInProgress()); EXPECT_FALSE(completion_callback_called()); @@ -249,7 +260,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); CompleteLoading(); PumpLoop(); EXPECT_FALSE(completion_callback_called()); @@ -261,7 +273,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); offliner()->Cancel(cancel_callback()); PumpLoop(); EXPECT_TRUE(cancel_callback_called()); @@ -272,7 +285,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); CompleteLoading(); PumpLoop(); offliner()->Cancel(cancel_callback()); @@ -291,7 +305,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); CompleteLoading(); PumpLoop(); @@ -308,7 +323,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); CompleteLoading(); PumpLoop(); @@ -325,14 +341,16 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kFileUrl, kClientId, creation_time, kUserRequested); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); } TEST_F(BackgroundLoaderOfflinerTest, ReturnsOnRenderCrash) { base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); offliner()->RenderProcessGone( base::TerminationStatus::TERMINATION_STATUS_PROCESS_CRASHED); @@ -344,7 +362,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); offliner()->RenderProcessGone( base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED); @@ -356,7 +375,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); offliner()->WebContentsDestroyed(); EXPECT_TRUE(completion_callback_called()); @@ -367,7 +387,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); // Create handle with net error code. // Called after calling LoadAndSave so we have web_contents to work with. @@ -390,7 +411,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); // Create handle with net error code. // Called after calling LoadAndSave so we have web_contents to work with. @@ -413,7 +435,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); // First load CompleteLoading(); // Second load
diff --git a/chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.cc b/chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.cc index a74f381..407d81e 100644 --- a/chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.cc +++ b/chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.cc
@@ -56,7 +56,8 @@ Java_OfflinePageNotificationBridge_notifyDownloadProgress( env, GetApplicationContext(), ConvertUTF8ToJavaString(env, item.guid), ConvertUTF8ToJavaString(env, item.url.spec()), - item.start_time.ToJavaTime(), GetDisplayName(item)); + item.start_time.ToJavaTime(), item.download_progress_bytes, + GetDisplayName(item)); } void OfflinePageNotificationBridge::NotifyDownloadPaused(
diff --git a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc index 2afcd8cd..b0fb215 100644 --- a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc +++ b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc
@@ -301,6 +301,10 @@ env, obj, ToJavaSavePageRequest(env, request)); } +void OfflinePageEvaluationBridge::OnNetworkProgress( + const SavePageRequest& request, + int64_t received_bytes) {} + void OfflinePageEvaluationBridge::CustomLog(const std::string& message) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
diff --git a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h index 85eacb9..398196f 100644 --- a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h +++ b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h
@@ -52,6 +52,8 @@ void OnCompleted(const SavePageRequest& request, RequestNotifier::BackgroundSavePageResult status) override; void OnChanged(const SavePageRequest& request) override; + void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override; // OfflineEventLogger::Client implementation. void CustomLog(const std::string& message) override;
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner.cc b/chrome/browser/android/offline_pages/prerendering_offliner.cc index 89707e1..a6564ad 100644 --- a/chrome/browser/android/offline_pages/prerendering_offliner.cc +++ b/chrome/browser/android/offline_pages/prerendering_offliner.cc
@@ -36,14 +36,10 @@ void PrerenderingOffliner::OnNetworkProgress(const SavePageRequest& request, int64_t bytes) { - if (!pending_request_) - return; - DownloadUIAdapter* ui_adapter = - DownloadUIAdapter::FromOfflinePageModel(offline_page_model_); - if (!ui_adapter) + if (!pending_request_ || !progress_callback_) return; - ui_adapter->UpdateProgress(request.request_id(), bytes); + progress_callback_.Run(request, bytes); } void PrerenderingOffliner::OnLoadPageDone( @@ -131,8 +127,10 @@ completion_callback_.Run(request, save_status); } -bool PrerenderingOffliner::LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) { +bool PrerenderingOffliner::LoadAndSave( + const SavePageRequest& request, + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) { DCHECK(!pending_request_.get()); if (pending_request_) { @@ -190,7 +188,8 @@ // Track copy of pending request for callback handling. pending_request_.reset(new SavePageRequest(request)); - completion_callback_ = callback; + completion_callback_ = completion_callback; + progress_callback_ = progress_callback; // Kick off load page attempt. bool accepted = GetOrCreateLoader()->LoadPage(
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner.h b/chrome/browser/android/offline_pages/prerendering_offliner.h index 935d3019..71c1a93 100644 --- a/chrome/browser/android/offline_pages/prerendering_offliner.h +++ b/chrome/browser/android/offline_pages/prerendering_offliner.h
@@ -35,7 +35,8 @@ // Offliner implementation. bool LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) override; + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) override; void Cancel(const CancelCallback& callback) override; bool HandleTimeout(const SavePageRequest& request) override; @@ -93,6 +94,7 @@ std::unique_ptr<SavePageRequest> pending_request_; // Callback to call when pending request completes/fails. CompletionCallback completion_callback_; + ProgressCallback progress_callback_; bool is_low_end_device_; // ApplicationStatusListener to monitor if the Chrome moves to the foreground. std::unique_ptr<base::android::ApplicationStatusListener> app_listener_;
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc index 2d0a21b..1aebeb4 100644 --- a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc +++ b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
@@ -168,10 +168,14 @@ Profile* profile() { return &profile_; } PrerenderingOffliner* offliner() const { return offliner_.get(); } - Offliner::CompletionCallback const callback() { + Offliner::CompletionCallback const completion_callback() { return base::Bind(&PrerenderingOfflinerTest::OnCompletion, base::Unretained(this)); } + Offliner::ProgressCallback const progress_callback() { + return base::Bind(&PrerenderingOfflinerTest::OnProgress, + base::Unretained(this)); + } Offliner::CancelCallback const cancel_callback() { return base::Bind(&PrerenderingOfflinerTest::OnCancel, base::Unretained(this)); @@ -188,6 +192,7 @@ private: void OnCompletion(const SavePageRequest& request, Offliner::RequestStatus status); + void OnProgress(const SavePageRequest& request, int64_t bytes); void OnCancel(int64_t offline_id); content::TestBrowserThreadBundle thread_bundle_; @@ -229,6 +234,9 @@ request_status_ = status; } +void PrerenderingOfflinerTest::OnProgress(const SavePageRequest& request, + int64_t bytes) {} + void PrerenderingOfflinerTest::OnCancel(int64_t offline_id) { DCHECK(!cancel_callback_called_); cancel_callback_called_ = true; @@ -238,7 +246,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kFileUrl, kClientId, creation_time, kUserRequested); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_TRUE(loader()->IsIdle()); } @@ -247,7 +256,8 @@ SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); loader()->DisablePrerendering(); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_TRUE(loader()->IsIdle()); } @@ -258,7 +268,8 @@ SavePageRequest request(kRequestId, kHttpUrl, custom_tabs_client_id, creation_time, kUserRequested); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_TRUE(loader()->IsIdle()); } @@ -271,7 +282,8 @@ profile()->GetPrefs()->SetInteger( prefs::kNetworkPredictionOptions, chrome_browser_net::NETWORK_PREDICTION_NEVER); - EXPECT_FALSE(offliner()->LoadAndSave(request, callback())); + EXPECT_FALSE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_TRUE(loader()->IsIdle()); } @@ -279,7 +291,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); @@ -295,7 +308,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); offliner()->Cancel(cancel_callback()); @@ -308,7 +322,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); @@ -338,7 +353,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); @@ -360,7 +376,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); @@ -382,7 +399,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); @@ -407,7 +425,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); offliner()->SetApplicationStateForTesting( @@ -424,7 +443,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request( kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); EXPECT_FALSE(loader()->IsIdle()); offliner()->SetApplicationStateForTesting( @@ -441,7 +461,8 @@ SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); loader()->set_is_lowbar_met(true); EXPECT_TRUE(offliner()->HandleTimeout(request)); EXPECT_TRUE(loader()->start_snapshot_called()); @@ -455,7 +476,8 @@ SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); loader()->set_is_lowbar_met(true); EXPECT_TRUE(offliner()->HandleTimeout(request)); EXPECT_TRUE(loader()->start_snapshot_called()); @@ -469,7 +491,8 @@ SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); request.set_completed_attempt_count(policy()->GetMaxCompletedTries() - 1); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); loader()->set_is_lowbar_met(false); EXPECT_FALSE(offliner()->HandleTimeout(request)); EXPECT_FALSE(loader()->start_snapshot_called()); @@ -482,7 +505,8 @@ SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); request.set_started_attempt_count(policy()->GetMaxStartedTries() - 1); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); loader()->set_is_lowbar_met(true); EXPECT_TRUE(offliner()->HandleTimeout(request)); EXPECT_TRUE(loader()->start_snapshot_called()); @@ -494,7 +518,8 @@ base::Time creation_time = base::Time::Now(); SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested); - EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); + EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(), + progress_callback())); loader()->set_is_lowbar_met(true); EXPECT_FALSE(offliner()->HandleTimeout(request)); EXPECT_FALSE(loader()->start_snapshot_called());
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc index 17f2a21..b8b8ecd9 100644 --- a/chrome/browser/chrome_browser_field_trials_desktop.cc +++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -18,6 +18,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "base/path_service.h" +#include "base/time/time.h" #include "chrome/browser/features.h" #include "chrome/browser/prerender/prerender_field_trial.h" #include "chrome/common/chrome_features.h" @@ -174,6 +175,8 @@ #elif defined(ARCH_CPU_X86_64) global_data.SetString(browser_watcher::kStabilityPlatform, "Win64"); #endif + global_data.SetInt(browser_watcher::kStabilityStartTimestamp, + base::Time::Now().ToInternalValue()); // Record information about chrome's module. We want this to be done early. RecordChromeModuleInfo(global_tracker);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index d91ac1b..26d6c02 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1134,6 +1134,8 @@ "policy/remote_commands/device_command_reboot_job.h", "policy/remote_commands/device_command_screenshot_job.cc", "policy/remote_commands/device_command_screenshot_job.h", + "policy/remote_commands/device_command_set_volume_job.cc", + "policy/remote_commands/device_command_set_volume_job.h", "policy/remote_commands/device_commands_factory_chromeos.cc", "policy/remote_commands/device_commands_factory_chromeos.h", "policy/remote_commands/screenshot_delegate.cc", @@ -1670,6 +1672,7 @@ "policy/network_configuration_updater_unittest.cc", "policy/recommendation_restorer_unittest.cc", "policy/remote_commands/device_command_screenshot_job_unittest.cc", + "policy/remote_commands/device_command_set_volume_job_unittest.cc", "policy/server_backed_state_keys_broker_unittest.cc", "policy/status_uploader_unittest.cc", "policy/system_log_uploader_unittest.cc",
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.cc new file mode 100644 index 0000000..fe5eed4 --- /dev/null +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.cc
@@ -0,0 +1,85 @@ +// Copyright 2017 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/chromeos/policy/remote_commands/device_command_set_volume_job.h" + +#include <utility> + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/syslog_logging.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/values.h" +#include "chromeos/audio/cras_audio_handler.h" +#include "components/policy/proto/device_management_backend.pb.h" + +namespace policy { + +namespace { + +// Determines the time, measured from the time of issue, after which the command +// queue will consider this command expired if the command has not been started. +const int kCommandExpirationTimeInMinutes = 10; + +const char kVolumeFieldName[] = "volume"; + +} // namespace + +DeviceCommandSetVolumeJob::DeviceCommandSetVolumeJob() {} + +DeviceCommandSetVolumeJob::~DeviceCommandSetVolumeJob() {} + +void DeviceCommandSetVolumeJob::SetVolumeCallbackForTesting( + const VolumeCallback& callback) { + volume_callback_ = callback; +} + +enterprise_management::RemoteCommand_Type DeviceCommandSetVolumeJob::GetType() + const { + return enterprise_management::RemoteCommand_Type_DEVICE_SET_VOLUME; +} + +base::TimeDelta DeviceCommandSetVolumeJob::GetCommmandTimeout() const { + return base::TimeDelta::FromMinutes(kCommandExpirationTimeInMinutes); +} + +bool DeviceCommandSetVolumeJob::ParseCommandPayload( + const std::string& command_payload) { + std::unique_ptr<base::Value> root( + base::JSONReader().ReadToValue(command_payload)); + if (!root.get()) + return false; + base::DictionaryValue* payload = nullptr; + if (!root->GetAsDictionary(&payload)) + return false; + if (!payload->GetInteger(kVolumeFieldName, &volume_)) + return false; + if (volume_ < 0 || volume_ > 100) + return false; + return true; +} + +bool DeviceCommandSetVolumeJob::IsExpired(base::TimeTicks now) { + return now > issued_time() + base::TimeDelta::FromMinutes( + kCommandExpirationTimeInMinutes); +} + +void DeviceCommandSetVolumeJob::RunImpl( + const CallbackWithResult& succeeded_callback, + const CallbackWithResult& failed_callback) { + SYSLOG(INFO) << "Running set volume command, volume = " << volume_; + if (volume_callback_.is_null()) { + auto* audio_handler = chromeos::CrasAudioHandler::Get(); + audio_handler->SetOutputVolumePercent(volume_); + bool mute = audio_handler->IsOutputVolumeBelowDefaultMuteLevel(); + audio_handler->SetOutputMute(mute); + } else { + volume_callback_.Run(volume_); + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(succeeded_callback, nullptr)); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.h b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.h new file mode 100644 index 0000000..b66c5667 --- /dev/null +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.h
@@ -0,0 +1,49 @@ +// Copyright 2017 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_CHROMEOS_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_SET_VOLUME_JOB_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_SET_VOLUME_JOB_H_ + +#include <memory> +#include <string> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "components/policy/core/common/remote_commands/remote_command_job.h" + +namespace policy { + +class DeviceCommandSetVolumeJob : public RemoteCommandJob { + public: + using VolumeCallback = base::Callback<void(int)>; + + DeviceCommandSetVolumeJob(); + ~DeviceCommandSetVolumeJob() override; + + void SetVolumeCallbackForTesting(const VolumeCallback& callback); + + // RemoteCommandJob: + enterprise_management::RemoteCommand_Type GetType() const override; + base::TimeDelta GetCommmandTimeout() const override; + + protected: + // RemoteCommandJob: + bool ParseCommandPayload(const std::string& command_payload) override; + bool IsExpired(base::TimeTicks now) override; + void RunImpl(const CallbackWithResult& succeeded_callback, + const CallbackWithResult& failed_callback) override; + + private: + // New volume level to be set, value in range [0,100]. + int volume_; + + // Used in tests instead of CrasAudioHandler::SetOutputVolumePercent. + VolumeCallback volume_callback_; + + DISALLOW_COPY_AND_ASSIGN(DeviceCommandSetVolumeJob); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_REMOTE_COMMANDS_DEVICE_COMMAND_SET_VOLUME_JOB_H_
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc new file mode 100644 index 0000000..11a01b5 --- /dev/null +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc
@@ -0,0 +1,138 @@ +// Copyright 2017 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/chromeos/policy/remote_commands/device_command_set_volume_job.h" + +#include "ash/test/ash_test_base.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/values.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace em = enterprise_management; + +namespace { + +const RemoteCommandJob::UniqueIDType kUniqueID = 123456789; + +// Name of the field in the command payload containing the volume. +const char kVolumeFieldName[] = "volume"; + +int g_volume; + +em::RemoteCommand GenerateSetVolumeCommandProto(base::TimeDelta age_of_command, + int volume) { + em::RemoteCommand command_proto; + command_proto.set_type( + enterprise_management::RemoteCommand_Type_DEVICE_SET_VOLUME); + command_proto.set_command_id(kUniqueID); + command_proto.set_age_of_command(age_of_command.InMilliseconds()); + std::string payload; + base::DictionaryValue root_dict; + root_dict.SetInteger(kVolumeFieldName, volume); + base::JSONWriter::Write(root_dict, &payload); + command_proto.set_payload(payload); + return command_proto; +} + +void SetVolumeCallback(int volume) { + g_volume = volume; +} + +std::unique_ptr<RemoteCommandJob> CreateSetVolumeJob( + base::TimeTicks issued_time, + int volume) { + auto* job_ptr = new DeviceCommandSetVolumeJob(); + auto job = base::WrapUnique<RemoteCommandJob>(job_ptr); + job_ptr->SetVolumeCallbackForTesting(base::Bind(&SetVolumeCallback)); + auto set_volume_command_proto = GenerateSetVolumeCommandProto( + base::TimeTicks::Now() - issued_time, volume); + EXPECT_TRUE(job->Init(base::TimeTicks::Now(), set_volume_command_proto)); + EXPECT_EQ(kUniqueID, job->unique_id()); + EXPECT_EQ(RemoteCommandJob::NOT_STARTED, job->status()); + return job; +} + +} // namespace + +class DeviceCommandSetVolumeTest : public ash::test::AshTestBase { + public: + void VerifyResults(RemoteCommandJob* job, + RemoteCommandJob::Status expected_status, + int expected_volume); + + protected: + DeviceCommandSetVolumeTest(); + + // testing::Test + void SetUp() override; + + base::RunLoop run_loop_; + base::TimeTicks test_start_time_; + + private: + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; + + DISALLOW_COPY_AND_ASSIGN(DeviceCommandSetVolumeTest); +}; + +DeviceCommandSetVolumeTest::DeviceCommandSetVolumeTest() + : task_runner_(new base::TestMockTimeTaskRunner()) {} + +void DeviceCommandSetVolumeTest::SetUp() { + ash::test::AshTestBase::SetUp(); + test_start_time_ = base::TimeTicks::Now(); +} + +void DeviceCommandSetVolumeTest::VerifyResults( + RemoteCommandJob* job, + RemoteCommandJob::Status expected_status, + int expected_volume) { + EXPECT_EQ(expected_status, job->status()); + if (job->status() == RemoteCommandJob::SUCCEEDED) { + EXPECT_EQ(expected_volume, g_volume); + } + run_loop_.Quit(); +} + +TEST_F(DeviceCommandSetVolumeTest, Success) { + const int kVolume = 45; + auto job = CreateSetVolumeJob(test_start_time_, kVolume); + bool success = + job->Run(base::TimeTicks::Now(), + base::Bind(&DeviceCommandSetVolumeTest::VerifyResults, + base::Unretained(this), base::Unretained(job.get()), + RemoteCommandJob::SUCCEEDED, kVolume)); + EXPECT_TRUE(success); + run_loop_.Run(); +} + +TEST_F(DeviceCommandSetVolumeTest, VolumeOutOfRange) { + const int kVolume = 110; + std::unique_ptr<RemoteCommandJob> job(new DeviceCommandSetVolumeJob()); + auto set_volume_command_proto = GenerateSetVolumeCommandProto( + base::TimeTicks::Now() - test_start_time_, kVolume); + EXPECT_FALSE(job->Init(base::TimeTicks::Now(), set_volume_command_proto)); + EXPECT_EQ(RemoteCommandJob::INVALID, job->status()); +} + +TEST_F(DeviceCommandSetVolumeTest, CommandTimeout) { + const int kVolume = 45; + auto delta = base::TimeDelta::FromMinutes(10); + auto job = CreateSetVolumeJob(test_start_time_ - delta, kVolume); + bool success = + job->Run(base::TimeTicks::Now(), + base::Bind(&DeviceCommandSetVolumeTest::VerifyResults, + base::Unretained(this), base::Unretained(job.get()), + RemoteCommandJob::SUCCEEDED, kVolume)); + EXPECT_FALSE(success); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc index 86b37a1..9614e80 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc
@@ -10,6 +10,7 @@ #include "base/threading/sequenced_worker_pool.h" #include "chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.h" #include "chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h" +#include "chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job.h" #include "chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/policy/core/common/remote_commands/remote_command_job.h" @@ -38,6 +39,9 @@ content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( content::BrowserThread::GetBlockingPool() ->GetSequenceToken())))); + case em::RemoteCommand_Type_DEVICE_SET_VOLUME: + return base::WrapUnique<RemoteCommandJob>( + new DeviceCommandSetVolumeJob()); default: return nullptr; }
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc index 1689fd8b..1cce55eb 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
@@ -10,6 +10,9 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" #include "base/time/time.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.h" @@ -53,7 +56,12 @@ // the settings reset prompt if required by the model and there is at least one // non-incognito browser available for the corresponding profile. void OnModelCreated(std::unique_ptr<SettingsResetPromptModel> model) { - if (!model || !model->ShouldPromptForReset()) + if (!model) + return; + + model->ReportUmaMetrics(); + + if (!model->ShouldPromptForReset()) return; Profile* profile = model->profile(); @@ -137,15 +145,28 @@ void SettingsResetPromptController::DialogShown() { model_->DialogShown(); + time_dialog_shown_ = base::Time::Now(); + base::RecordAction(base::UserMetricsAction("SettingsResetPrompt_Shown")); + UMA_HISTOGRAM_BOOLEAN("SettingsResetPrompt.DialogShown", true); } void SettingsResetPromptController::Accept() { + DCHECK(!time_dialog_shown_.is_null()); + base::RecordAction(base::UserMetricsAction("SettingsResetPrompt_Accepted")); + UMA_HISTOGRAM_LONG_TIMES_100("SettingsResetPrompt.TimeUntilAccepted", + base::Time::Now() - time_dialog_shown_); + UMA_HISTOGRAM_BOOLEAN("SettingsResetPrompt.PromptAccepted", true); model_->PerformReset( base::Bind(&SettingsResetPromptController::OnInteractionDone, base::Unretained(this))); } void SettingsResetPromptController::Cancel() { + DCHECK(!time_dialog_shown_.is_null()); + base::RecordAction(base::UserMetricsAction("SettingsResetPrompt_Declined")); + UMA_HISTOGRAM_LONG_TIMES_100("SettingsResetPrompt.TimeUntilDeclined", + base::Time::Now() - time_dialog_shown_); + UMA_HISTOGRAM_BOOLEAN("SettingsResetPrompt.PromptAccepted", false); OnInteractionDone(); } @@ -204,7 +225,6 @@ } void SettingsResetPromptController::OnInteractionDone() { - // TODO(alito): Add metrics reporting here. delete this; }
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h index 31a7afe..a79a081 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/strings/string16.h" +#include "base/time/time.h" #include "ui/gfx/range/range.h" class Browser; @@ -63,6 +64,9 @@ base::string16 main_text_; gfx::Range main_text_url_range_; + // Used for metrics reporting. + base::Time time_dialog_shown_; + DISALLOW_COPY_AND_ASSIGN(SettingsResetPromptController); };
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc index d402584..dd78583 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
@@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/callback.h" +#include "base/metrics/histogram_macros.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/prefs/session_startup_pref.h" @@ -37,6 +38,15 @@ constexpr char kOmahaUrl[] = "https://tools.google.com/service/update2"; #endif // defined(GOOGLE_CHROME_BUILD) +// These values are used for UMA metrics reporting. New enum values can be +// added, but existing enums must never be renumbered or deleted and reused. +enum SettingsReset { + SETTINGS_RESET_HOMEPAGE = 1, + SETTINGS_RESET_DEFAULT_SEARCH = 2, + SETTINGS_RESET_STARTUP_URLS = 3, + SETTINGS_RESET_MAX, +}; + // Used to keep track of which settings types have been initialized in // |SettingsResetPromptModel|. enum SettingsType : uint32_t { @@ -209,15 +219,28 @@ extension_service->DisableExtension( extension_id, extensions::Extension::DISABLE_USER_ACTION); } + UMA_HISTOGRAM_COUNTS_100("SettingsResetPrompt.NumberOfExtensionsDisabled", + extensions_to_disable().size()); // Disable all the settings that need to be reset. ProfileResetter::ResettableFlags reset_flags = 0; - if (homepage_reset_state() == RESET_REQUIRED) + if (homepage_reset_state() == RESET_REQUIRED) { reset_flags |= ProfileResetter::HOMEPAGE; - if (default_search_reset_state() == RESET_REQUIRED) + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.SettingsReset", + SETTINGS_RESET_HOMEPAGE, SETTINGS_RESET_MAX); + } + if (default_search_reset_state() == RESET_REQUIRED) { reset_flags |= ProfileResetter::DEFAULT_SEARCH_ENGINE; - if (startup_urls_reset_state() == RESET_REQUIRED) + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.SettingsReset", + SETTINGS_RESET_DEFAULT_SEARCH, + SETTINGS_RESET_MAX); + } + if (startup_urls_reset_state() == RESET_REQUIRED) { reset_flags |= ProfileResetter::STARTUP_PAGES; + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.SettingsReset", + SETTINGS_RESET_STARTUP_URLS, SETTINGS_RESET_MAX); + } + profile_resetter_->Reset(reset_flags, std::move(default_settings_), done_callback); } @@ -276,6 +299,22 @@ return extensions_to_disable_; } +void SettingsResetPromptModel::ReportUmaMetrics() const { + UMA_HISTOGRAM_BOOLEAN("SettingsResetPrompt.PromptRequired", + ShouldPromptForReset()); + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.ResetState_DefaultSearch", + default_search_reset_state(), RESET_STATE_MAX); + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.ResetState_StartupUrls", + startup_urls_reset_state(), RESET_STATE_MAX); + UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.ResetState_Homepage", + homepage_reset_state(), RESET_STATE_MAX); + UMA_HISTOGRAM_COUNTS_100("SettingsResetPrompt.NumberOfExtensionsToDisable", + extensions_to_disable().size()); + UMA_HISTOGRAM_SPARSE_SLOWLY( + "SettingsResetPrompt.DelayBeforePromptParam", + prompt_config_->delay_before_prompt().InSeconds()); +} + // static void SettingsResetPromptModel::OnSettingsFetched( Profile* profile,
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h index 771531a..7ac123f 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h
@@ -48,6 +48,7 @@ NO_RESET_REQUIRED_DUE_TO_RECENTLY_PROMPTED = 4, NO_RESET_REQUIRED_DUE_TO_OTHER_SETTING_REQUIRING_RESET = 5, NO_RESET_REQUIRED_DUE_TO_POLICY = 6, + RESET_STATE_MAX = 7 }; using ExtensionMap = @@ -103,6 +104,8 @@ // be disabled. virtual const ExtensionMap& extensions_to_disable() const; + void ReportUmaMetrics() const; + protected: // Exposed for mocking in tests. SettingsResetPromptModel(
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h index e116bed..7767861 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
@@ -229,8 +229,9 @@ // a click outside the bounds of the window. id exitEventTap_; - IBOutlet BookmarkBarView* buttonView_; // Contains 'no items' text fields. - IBOutlet BookmarkButton* offTheSideButton_; // aka the chevron. + base::scoped_nsobject<BookmarkBarView> + buttonView_; // Contains 'no items' text fields. + base::scoped_nsobject<BookmarkButton> offTheSideButton_; // aka the chevron. NSRect originalNoItemsRect_; // Original, pre-resized field rect. NSRect originalImportBookmarksRect_; // Original, pre-resized field rect. @@ -391,12 +392,12 @@ // Actions for manipulating bookmarks. // Open a normal bookmark or folder from a button, ... -- (IBAction)openBookmark:(id)sender; -- (IBAction)openBookmarkFolderFromButton:(id)sender; +- (void)openBookmark:(id)sender; +- (void)openBookmarkFolderFromButton:(id)sender; // From the "off the side" button, ... -- (IBAction)openOffTheSideFolderFromButton:(id)sender; +- (void)openOffTheSideFolderFromButton:(id)sender; // Import bookmarks from another browser. -- (IBAction)importBookmarks:(id)sender; +- (void)importBookmarks:(id)sender; // Returns the app page shortcut button. - (NSButton*)appsPageShortcutButton;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm index 55db28700..b00e907c 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -321,6 +321,33 @@ return contextMenuController_.get(); } +- (void)loadView { + // Height is 0 because this is what the superview expects + [self setView:[[[BookmarkBarToolbarView alloc] + initWithFrame:NSMakeRect(0, 0, initialWidth_, 0)] + autorelease]]; + [[self view] setHidden:YES]; + [[self view] setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; + [[self controlledView] setController:self]; + [[self controlledView] setDelegate:self]; + + buttonView_.reset([[BookmarkBarView alloc] + initWithController:self + frame:NSMakeRect(0, -2, 584, 144)]); + [buttonView_ setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin | + NSViewMaxXMargin]; + [[buttonView_ importBookmarksButton] setTarget:self]; + [[buttonView_ importBookmarksButton] setAction:@selector(importBookmarks:)]; + + [self createOffTheSideButton]; + [buttonView_ addSubview:offTheSideButton_]; + + [self.view addSubview:buttonView_]; + // viewDidLoad became part of the API in 10.10 + if (!base::mac::IsAtLeastOS10_10()) + [self viewDidLoad]; +} + - (BookmarkButton*)bookmarkButtonToPulseForNode:(const BookmarkNode*)node { // Find the closest parent that is visible on the bar. while (node) { @@ -380,6 +407,9 @@ } - (void)dealloc { + [buttonView_ setController:nil]; + [[self controlledView] setController:nil]; + [[self controlledView] setDelegate:nil]; [self browserWillBeDestroyed]; [super dealloc]; } @@ -421,36 +451,7 @@ browser_ = nullptr; } -- (void)awakeFromNib { - [self viewDidLoad]; -} - - (void)viewDidLoad { - if (bridge_) { - // When running on 10.10, expect both -awakeFromNib and -viewDidLoad to be - // called, but only initialize once. - DCHECK(base::mac::IsAtLeastOS10_10()); - return; - } - - // We default to NOT open, which means height=0. - DCHECK([[self view] isHidden]); // Hidden so it's OK to change. - - // Set our initial height to zero, since that is what the superview - // expects. We will resize ourselves open later if needed. - [[self view] setFrame:NSMakeRect(0, 0, initialWidth_, 0)]; - - // Complete init of the "off the side" button, as much as we can. - [offTheSideButton_ setImage:[self offTheSideButtonImage:NO]]; - BookmarkButtonCell* offTheSideCell = [offTheSideButton_ cell]; - [offTheSideCell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; - [offTheSideCell setImagePosition:NSImageOnly]; - - // The cell is configured in the nib to draw a white highlight when clicked. - [offTheSideCell setHighlightsBy:NSNoCellMask]; - [offTheSideButton_.draggableButton setDraggable:NO]; - [offTheSideButton_.draggableButton setActsOnMouseDown:YES]; - // We are enabled by default. barIsEnabled_ = YES; @@ -468,16 +469,6 @@ originalImportBookmarksRect_.origin.x += kBookmarksTextfieldOffsetX; [[buttonView_ importBookmarksButton] setFrame:originalImportBookmarksRect_]; - // Move the chevron button up 2pts from its position in the xib. - NSRect chevronButtonFrame = [offTheSideButton_ frame]; - chevronButtonFrame.origin.y -= 2; - [offTheSideButton_ setFrame:chevronButtonFrame]; - - // To make life happier when the bookmark bar is floating, the chevron is a - // child of the button view. - [offTheSideButton_ removeFromSuperview]; - [buttonView_ addSubview:offTheSideButton_]; - // When resized we may need to add new buttons, or remove them (if // no longer visible), or add/remove the "off the side" menu. [[self view] setPostsFrameChangedNotifications:YES]; @@ -837,7 +828,7 @@ // Middle click on chevron should not open bookmarks under it, instead just // open its folder menu. - if (sender == offTheSideButton_) { + if (sender == offTheSideButton_.get()) { [[sender cell] setStartingChildIndex:displayedButtonCount_]; NSEvent* event = [NSApp currentEvent]; if ([event type] == NSOtherMouseUp) { @@ -858,17 +849,17 @@ } // Click on a bookmark folder button. -- (IBAction)openBookmarkFolderFromButton:(id)sender { +- (void)openBookmarkFolderFromButton:(id)sender { [self openBookmarkFolder:sender]; } // Click on the "off the side" button (chevron), which opens like a folder // button but isn't exactly a parent folder. -- (IBAction)openOffTheSideFolderFromButton:(id)sender { +- (void)openOffTheSideFolderFromButton:(id)sender { [self openBookmarkFolder:sender]; } -- (IBAction)importBookmarks:(id)sender { +- (void)importBookmarks:(id)sender { chrome::ShowImportDialog(browser_); } @@ -1423,6 +1414,27 @@ [self setAppsPageShortcutButtonVisibility]; } +- (void)createOffTheSideButton { + offTheSideButton_.reset( + [[BookmarkButton alloc] initWithFrame:NSMakeRect(586, 0, 20, 24)]); + id offTheSideCell = [BookmarkButtonCell offTheSideButtonCell]; + [offTheSideCell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; + [offTheSideCell setImagePosition:NSImageOnly]; + + [offTheSideCell setHighlightsBy:NSNoCellMask]; + [offTheSideCell setShowsBorderOnlyWhileMouseInside:YES]; + [offTheSideCell setBezelStyle:NSShadowlessSquareBezelStyle]; + [offTheSideButton_ setCell:offTheSideCell]; + [offTheSideButton_ setImage:[self offTheSideButtonImage:NO]]; + [offTheSideButton_ setButtonType:NSMomentaryLightButton]; + + [offTheSideButton_ setTarget:self]; + [offTheSideButton_ setAction:@selector(openOffTheSideFolderFromButton:)]; + [offTheSideButton_ setDelegate:self]; + [[offTheSideButton_ draggableButton] setDraggable:NO]; + [[offTheSideButton_ draggableButton] setActsOnMouseDown:YES]; +} + - (void)openAppsPage:(id)sender { WindowOpenDisposition disposition = ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); @@ -1954,7 +1966,8 @@ [[eventWindow contentView] hitTest:[event locationInWindow]]; if (hitView == [folderController_ parentButton]) return NO; - if (![hitView isDescendantOf:[self view]] || hitView == buttonView_) + if (![hitView isDescendantOf:[self view]] || + hitView == buttonView_.get()) return YES; } // If a click in a bookmark bar folder window and that isn't
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h index ace88f6..e2d764b 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
@@ -32,10 +32,13 @@ @interface BookmarkBarToolbarView : AnimatableView { @private - // The controller which tells us how we should be drawing (as normal or as a - // floating bar). - IBOutlet id<BookmarkBarToolbarViewController> controller_; + // The controller which tells us how we should be drawing (as normal or as a + // floating bar). Weak reference. + id<BookmarkBarToolbarViewController> controller_; } + +// Exposed so that the controller can nil itself out +- (void)setController:(id<BookmarkBarToolbarViewController>)controller; @end #endif // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm index 02fe283..56cc537 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.mm
@@ -23,6 +23,10 @@ @implementation BookmarkBarToolbarView +- (void)setController:(id<BookmarkBarToolbarViewController>)controller { + controller_ = controller; +} + - (BOOL)isOpaque { // -drawRect: calls -drawAsDetachedBubble: or -drawBackground:, both of which // fill the dirty rect with an opaque color.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm index f4479bb..01b3cde 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view_unittest.mm
@@ -24,17 +24,6 @@ using ::testing::Return; using ::testing::SetArgumentPointee; -// Allows us to inject our fake controller below. -@interface BookmarkBarToolbarView (TestingAPI) --(void)setController:(id<BookmarkBarToolbarViewController>)controller; -@end - -@implementation BookmarkBarToolbarView (TestingAPI) --(void)setController:(id<BookmarkBarToolbarViewController>)controller { - controller_ = controller; -} -@end - // Allows us to control which way the view is rendered. @interface DrawDetachedBarFakeController : NSObject<BookmarkBarState, BookmarkBarToolbarViewController> {
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h index 62626ae..565c2a7 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.h
@@ -10,7 +10,7 @@ #import <Cocoa/Cocoa.h> -#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" +#include "base/mac/scoped_nsobject.h" @class BookmarkBarController; @@ -19,22 +19,26 @@ BOOL dropIndicatorShown_; CGFloat dropIndicatorPosition_; // x position - IBOutlet BookmarkBarController* controller_; - IBOutlet NSTextField* noItemTextfield_; - IBOutlet NSButton* importBookmarksButton_; - GTMWidthBasedTweaker* noItemContainer_; + BookmarkBarController* controller_; + base::scoped_nsobject<NSTextField> noItemTextfield_; + base::scoped_nsobject<NSButton> importBookmarksButton_; + base::scoped_nsobject<NSView> noItemContainer_; } - (NSTextField*)noItemTextfield; - (NSButton*)importBookmarksButton; -- (BookmarkBarController*)controller; +- (NSView*)noItemContainer; -@property(nonatomic, assign) IBOutlet GTMWidthBasedTweaker* noItemContainer; +- (instancetype)initWithController:(BookmarkBarController*)controller + frame:(NSRect)frame; +- (void)registerForNotificationsAndDraggedTypes; + +// Exposed so the controller can nil itself out. +@property(nonatomic, assign) BookmarkBarController* controller; @end @interface BookmarkBarView() // TestingOrInternalAPI @property(nonatomic, readonly) BOOL dropIndicatorShown; @property(nonatomic, readonly) CGFloat dropIndicatorPosition; -- (void)setController:(id)controller; @end #endif // CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_VIEW_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.mm index cda5ade..620ccb3 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa.mm
@@ -14,17 +14,29 @@ #import "chrome/browser/ui/cocoa/browser_window_controller.h" #import "chrome/browser/ui/cocoa/themed_window.h" #import "chrome/browser/ui/cocoa/view_id_util.h" +#include "chrome/grit/generated_resources.h" #include "components/bookmarks/browser/bookmark_pasteboard_helper_mac.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "content/public/browser/user_metrics.h" #import "third_party/mozilla/NSPasteboard+Utils.h" #include "ui/base/clipboard/clipboard_util_mac.h" +#import "ui/base/cocoa/controls/hyperlink_button_cell.h" #import "ui/base/cocoa/nsview_additions.h" +#include "ui/base/l10n/l10n_util_mac.h" using base::UserMetricsAction; using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; +static const CGFloat kInitialContainerWidth = 596; +static const CGFloat kInitialContainerHeight = 41; +static const CGFloat kInitialElementYOrigin = 20; +static const CGFloat kInitialElementHeight = 14; +static const CGFloat kInitialTextFieldXOrigin = 5; +// static const CGFloat kInitialTextFieldWidth = 167; +static const CGFloat kTextFieldTrailingPadding = 5; +// static const CGFloat kInitialButtonWidth = 199; + @interface BookmarkBarView (Private) - (void)themeDidChangeNotification:(NSNotification*)aNotification; - (void)updateTheme:(const ui::ThemeProvider*)themeProvider; @@ -37,7 +49,7 @@ @synthesize dropIndicatorShown = dropIndicatorShown_; @synthesize dropIndicatorPosition = dropIndicatorPosition_; -@synthesize noItemContainer = noItemContainer_; +@synthesize controller = controller_; - (void)setFrameSize:(NSSize)size { NSSize oldFrameSize = [self frame].size; @@ -55,20 +67,72 @@ [self unregisterDraggedTypes]; [super dealloc]; - // To be clear, our controller_ is an IBOutlet and owns us, so we - // don't deallocate it explicitly. It is owned by the browser - // window controller, so gets deleted with a browser window is - // closed. + // To be clear, our controller_ owns us, so we on't deallocate it explicitly. + // It is owned by the browser window controller, so gets deleted with a + // browser window is closed. } -- (void)awakeFromNib { +- (instancetype)initWithController:(BookmarkBarController*)controller + frame:(NSRect)frame { + DCHECK(controller) << "Controller shouldn't be nil"; + if (self = [super initWithFrame:frame]) { + controller_ = controller; + + NSFont* smallSystemFont = + [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; + noItemContainer_.reset( + [[NSView alloc] initWithFrame:NSMakeRect(0, 0, kInitialContainerWidth, + kInitialContainerHeight)]); + [noItemContainer_ setAutoresizingMask:NSViewMaxXMargin]; + + noItemTextfield_.reset([[NSTextField alloc] + initWithFrame:NSMakeRect(kInitialTextFieldXOrigin, + kInitialElementYOrigin, CGFLOAT_MAX, + kInitialElementHeight)]); + [noItemTextfield_ setAutoresizingMask:NSViewWidthSizable]; + [noItemTextfield_ setFont:smallSystemFont]; + [noItemTextfield_ + setStringValue:l10n_util::GetNSString(IDS_BOOKMARKS_NO_ITEMS)]; + + [noItemTextfield_ setBordered:NO]; + [[noItemTextfield_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; + + [noItemTextfield_ setTextColor:[NSColor controlTextColor]]; + [noItemTextfield_ setBackgroundColor:[NSColor controlColor]]; + + [noItemTextfield_ setDrawsBackground:NO]; + [noItemTextfield_ setTextColor:[NSColor controlTextColor]]; + [noItemTextfield_ setBackgroundColor:[NSColor controlColor]]; + [noItemTextfield_ sizeToFit]; + + NSButton* importButton = [HyperlinkButtonCell + buttonWithString:l10n_util::GetNSString(IDS_BOOKMARK_BAR_IMPORT_LINK)]; + importBookmarksButton_.reset([importButton retain]); + [importBookmarksButton_ + setFrame:NSMakeRect(NSMaxX([noItemTextfield_ frame]) + + kTextFieldTrailingPadding, + kInitialElementYOrigin, CGFLOAT_MAX, + kInitialElementHeight)]; + [importBookmarksButton_ setAutoresizingMask:NSViewMaxXMargin]; + [importBookmarksButton_ setFont:smallSystemFont]; + [importBookmarksButton_ sizeToFit]; + [noItemContainer_ addSubview:importBookmarksButton_]; + + [noItemContainer_ addSubview:noItemTextfield_]; + + [self addSubview:noItemContainer_]; + [self registerForNotificationsAndDraggedTypes]; + } + return self; +} + +- (void)registerForNotificationsAndDraggedTypes { NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; [defaultCenter addObserver:self selector:@selector(themeDidChangeNotification:) name:kBrowserThemeDidChangeNotification object:nil]; - DCHECK(controller_) << "Expected this to be hooked up via Interface Builder"; NSArray* types = @[ NSStringPboardType, NSHTMLPboardType, NSURLPboardType, ui::ClipboardUtil::UTIForPasteboardType(kBookmarkButtonDragType), @@ -117,12 +181,12 @@ return noItemTextfield_; } -- (NSButton*)importBookmarksButton { - return importBookmarksButton_; +- (NSView*)noItemContainer { + return noItemContainer_; } -- (BookmarkBarController*)controller { - return controller_; +- (NSButton*)importBookmarksButton { + return importBookmarksButton_; } // Internal method, needs to be called whenever a change has been made to @@ -281,10 +345,6 @@ return [[controller_ menuController] menuForBookmarkBar]; } -- (void)setController:(id)controller { - controller_ = controller; -} - - (ViewID)viewID { return VIEW_ID_BOOKMARK_BAR; }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa_unittest.mm index c447200c..2694ed0 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view_cocoa_unittest.mm
@@ -35,7 +35,7 @@ } // namespace // Fake DraggingInfo, fake BookmarkBarController, fake NSPasteboard... -@interface FakeBookmarkDraggingInfo : NSObject { +@interface FakeBookmarkDraggingInfo : BookmarkBarController { @public BOOL dragButtonToPong_; BOOL dragButtonToShouldCopy_; @@ -46,14 +46,14 @@ // Only mock one type of drag data at a time. NSString* dragDataType_; BookmarkButton* button_; // weak - BookmarkModel* bookmarkModel_; // weak + BookmarkModel* stubbedBookmarkModel_; // weak id draggingSource_; } @property (nonatomic) BOOL dropIndicatorShown; @property (nonatomic) BOOL draggingEnteredCalled; @property (nonatomic, copy) NSString* dragDataType; @property (nonatomic, assign) BookmarkButton* button; -@property (nonatomic, assign) BookmarkModel* bookmarkModel; + @end @implementation FakeBookmarkDraggingInfo @@ -62,7 +62,6 @@ @synthesize draggingEnteredCalled = draggingEnteredCalled_; @synthesize dragDataType = dragDataType_; @synthesize button = button_; -@synthesize bookmarkModel = bookmarkModel_; - (id)init { if ((self = [super init])) { @@ -131,6 +130,18 @@ // Fake a controller for callback ponging +- (void)viewDidLoad { + // no-op +} + +- (void)setBookmarkModel:(BookmarkModel*)model { + stubbedBookmarkModel_ = model; +} + +- (BookmarkModel*)bookmarkModel { + return stubbedBookmarkModel_; +} + - (BOOL)dragButton:(BookmarkButton*)button to:(NSPoint)point copy:(BOOL)copy { dragButtonToPong_ = YES; dragButtonToShouldCopy_ = copy;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h index 9144e0b2..184242a 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h
@@ -55,6 +55,9 @@ image:(NSImage*)image menuController:(BookmarkContextMenuCocoaController*)menuController; +// Create an |OffTheSideButtonCell| (aka the overflow chevron.) ++ (id)offTheSideButtonCell; + // Initialize a button cell which draws with a theme. // Designated initializer. - (id)initForNode:(const bookmarks::BookmarkNode*)node
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm index 1b2578c2..4a0ef76 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
@@ -37,6 +37,8 @@ }; // namespace +// TODO(lgrey): Bake setting the chevron image into this +// class instead of setting it externally. @interface OffTheSideButtonCell : BookmarkButtonCell - (NSString*)accessibilityTitle; @@ -106,6 +108,10 @@ return buttonCell; } ++ (id)offTheSideButtonCell { + return [[[OffTheSideButtonCell alloc] init] autorelease]; +} + - (id)initForNode:(const BookmarkNode*)node text:(NSString*)text image:(NSImage*)image
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm index a2ac7828..e820fc14 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell_unittest.mm
@@ -208,4 +208,9 @@ [gradient_cell verticalTextOffset]); } +TEST_F(BookmarkButtonCellTest, OffTheSideCell) { + Class offTheSideButtonCellClass = NSClassFromString(@"OffTheSideButtonCell"); + EXPECT_TRUE([[BookmarkButtonCell offTheSideButtonCell] + isKindOfClass:offTheSideButtonCellClass]); +} } // namespace
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 3c12b1c..57efa23 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -331,8 +331,10 @@ initWithBrowser:browser_.get() initialWidth:NSWidth([[[self window] contentView] frame]) delegate:self]); - // This call triggers an -awakeFromNib for ToolbarView.xib. - [[bookmarkBarController_ controlledView] setResizeDelegate:self]; + // This call loads the view. + BookmarkBarToolbarView* bookmarkBarView = + [bookmarkBarController_ controlledView]; + [bookmarkBarView setResizeDelegate:self]; [bookmarkBarController_ setBookmarkBarEnabled:[self supportsBookmarkBar]];
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc index 9df3712..ea937f9 100644 --- a/chrome/browser/ui/views/extensions/extension_popup.cc +++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -47,7 +47,7 @@ views::View* anchor_view, views::BubbleBorder::Arrow arrow, ShowAction show_action) { - auto popup = new ExtensionPopup(host, anchor_view, arrow, show_action); + auto* popup = new ExtensionPopup(host, anchor_view, arrow, show_action); views::BubbleDialogDelegateView::CreateBubble(popup); return popup; }
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc index 98e4af9..a282dea 100644 --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/ui/views/payments/credit_card_editor_view_controller.h" +#include <memory> +#include <string> #include <utility> +#include <vector> #include "base/memory/ptr_util.h" #include "base/strings/string16.h" @@ -135,6 +138,10 @@ return view; } +int CreditCardEditorViewController::GetViewHeaderTitleId() const { + return IDS_PAYMENT_REQUEST_CREDIT_CARD_EDITOR_ADD_TITLE; +} + std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() { return std::vector<EditorField>{ {autofill::CREDIT_CARD_NUMBER,
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h index ecebd72..4b3a1ce 100644 --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h
@@ -5,7 +5,10 @@ #ifndef CHROME_BROWSER_UI_VIEWS_PAYMENTS_CREDIT_CARD_EDITOR_VIEW_CONTROLLER_H_ #define CHROME_BROWSER_UI_VIEWS_PAYMENTS_CREDIT_CARD_EDITOR_VIEW_CONTROLLER_H_ +#include <memory> #include <set> +#include <string> +#include <vector> #include "base/macros.h" #include "chrome/browser/ui/views/payments/editor_view_controller.h" @@ -27,6 +30,7 @@ // EditorViewController: std::unique_ptr<views::View> CreateHeaderView() override; + int GetViewHeaderTitleId() const override; std::vector<EditorField> GetFieldDefinitions() override; bool ValidateModelAndSave() override; std::unique_ptr<ValidationDelegate> CreateValidationDelegate(
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc index ac5f7a63..d8423a628 100644 --- a/chrome/browser/ui/views/payments/editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/editor_view_controller.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/payments/editor_view_controller.h" +#include <map> #include <memory> #include <utility> @@ -71,9 +72,7 @@ return CreatePaymentView( CreateSheetHeaderView( - true, l10n_util::GetStringUTF16( - IDS_PAYMENT_REQUEST_CREDIT_CARD_EDITOR_ADD_TITLE), - this), + true, l10n_util::GetStringUTF16(GetViewHeaderTitleId()), this), std::move(content_view)); }
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.h b/chrome/browser/ui/views/payments/editor_view_controller.h index 532b5fc..afc14a33 100644 --- a/chrome/browser/ui/views/payments/editor_view_controller.h +++ b/chrome/browser/ui/views/payments/editor_view_controller.h
@@ -5,9 +5,11 @@ #ifndef CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_ #define CHROME_BROWSER_UI_VIEWS_PAYMENTS_EDITOR_VIEW_CONTROLLER_H_ +#include <map> #include <memory> #include <tuple> #include <unordered_map> +#include <utility> #include <vector> #include "base/macros.h" @@ -104,6 +106,8 @@ protected: virtual std::unique_ptr<views::View> CreateHeaderView() = 0; + // Returns the resource id of the view header title. + virtual int GetViewHeaderTitleId() const = 0; // Returns the field definitions used to build the UI. virtual std::vector<EditorField> GetFieldDefinitions() = 0; // Validates the data entered and attempts to save; returns true on success.
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc index 3c114ee..c6d518a 100644 --- a/chrome/browser/win/jumplist.cc +++ b/chrome/browser/win/jumplist.cc
@@ -296,8 +296,11 @@ } } - if (!base::CreateDirectory(icon_dir)) + // If CreateDirectory() fails, exit early. + if (!base::CreateDirectory(icon_dir)) { folder_operation_status |= FolderOperationResult::CREATE_SRC_FAILED; + return; + } // Create temporary icon files for shortcuts in the "Most Visited" category. CreateIconFiles(icon_dir, local_most_visited_pages);
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn index 95a1d9d..406a8a2 100644 --- a/chrome/installer/linux/BUILD.gn +++ b/chrome/installer/linux/BUILD.gn
@@ -85,15 +85,9 @@ ] if (is_chrome_branded) { - sources += [ - "common/google-chrome/google-chrome.appdata.xml.template", - "common/google-chrome/google-chrome.info", - ] + sources += [ "common/google-chrome/google-chrome.info" ] } else { - sources += [ - "common/chromium-browser/chromium-browser.appdata.xml", - "common/chromium-browser/chromium-browser.info", - ] + sources += [ "common/chromium-browser/chromium-browser.info" ] } if (current_cpu == "x86") {
diff --git a/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml b/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml deleted file mode 100644 index 1f4e463..0000000 --- a/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml +++ /dev/null
@@ -1,36 +0,0 @@ -<!-- Copyright 2017 The Chromium Authors --> -<?xml version="1.0" encoding="UTF-8"?> -<component type="desktop"> - <id>chromium-browser.desktop</id> - <update_contact>chromium-dev@chromium.org</update_contact> - <metadata_license>CC0-1.0</metadata_license> - <project_license>BSD-3-Clause and LGPL-2.1+ and Apache-2.0 and IJG and MIT and GPL-2.0+ and ISC and OpenSSL and (MPL-1.1 or GPL-2.0 or LGPL-2.0)</project_license> - <name>Chromium Web Browser</name> - <summary>The web browser from Chromium project</summary> - <description> - <p> - Chromium is an open-source browser project that aims to build a safer, faster, - and more stable way to experience the web. - </p> - <p> - We invite you to join our effort to build a powerful platform for developing a - new generation of web applications. - </p> - <p> - Chromium supports Vorbis, Theora, WebM and HTML5 audio and video standards, but - does not include the non-free AAC, H.264, MP3 or Adobe Flash code that is found - in Chrome. - </p> - </description> - <url type="homepage">https://www.chromium.org/Home</url> - <screenshots> - <screenshot type="default"> - <image>https://www.gstatic.com/chrome/appstream/chrome-1.png</image> - <caption/> - </screenshot> - </screenshots> - <translation/> - <developer_name>The Chromium Authors</developer_name> - <url type="bugtracker">https://www.chromium.org/for-testers/bug-reporting-guidelines</url> - <url type="help">https://chromium.googlesource.com/chromium/src/+/master/docs/linux_debugging.md</url> -</component>
diff --git a/chrome/installer/linux/common/google-chrome/google-chrome.appdata.xml.template b/chrome/installer/linux/common/google-chrome/google-chrome.appdata.xml.template deleted file mode 100644 index 1f03817f..0000000 --- a/chrome/installer/linux/common/google-chrome/google-chrome.appdata.xml.template +++ /dev/null
@@ -1,26 +0,0 @@ -<!-- Copyright 2017 The Chromium Authors --> -<?xml version="1.0" encoding="UTF-8"?> -<component type="desktop"> - <id>@@PACKAGE@@.desktop</id> - <update_contact>chromium-dev@chromium.org</update_contact> - <metadata_license>CC0-1.0</metadata_license> - <project_license>Freeware under Google Chrome Terms of Service</project_license> - <name>@@MENUNAME@@</name> - <summary>The web browser from Google</summary> - <description> - <p> - @@FULLDESC@@ - </p> - </description> - <url type="homepage">@@PRODUCTURL@@</url> - <screenshots> - <screenshot type="default"> - <image>https://www.gstatic.com/chrome/appstream/chrome-1.png</image> - <caption/> - </screenshot> - </screenshots> - <translation/> - <developer_name>Google</developer_name> - <url type="bugtracker">https://support.google.com/chrome/?p=feedback</url> - <url type="help">https://support.google.com/chrome</url> -</component>
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include index f26a0ae..a8666514 100644 --- a/chrome/installer/linux/common/installer.include +++ b/chrome/installer/linux/common/installer.include
@@ -244,14 +244,6 @@ # desktop integration install -m 755 "${BUILDDIR}/xdg-mime" "${STAGEDIR}${INSTALLDIR}/" install -m 755 "${BUILDDIR}/xdg-settings" "${STAGEDIR}${INSTALLDIR}/" - if [ ${PACKAGE:0:6} = google ]; then - process_template "${BUILDDIR}/installer/common/google-chrome/google-chrome.appdata.xml.template" \ - "${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml" - chmod 644 "${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml" - else - install -m 644 "${BUILDDIR}/installer/common/chromium-browser/chromium-browser.appdata.xml" \ - "${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml" - fi process_template "${BUILDDIR}/installer/common/desktop.template" \ "${STAGEDIR}/usr/share/applications/${PACKAGE}.desktop" chmod 644 "${STAGEDIR}/usr/share/applications/${PACKAGE}.desktop"
diff --git a/chrome/installer/linux/rpm/chrome.spec.template b/chrome/installer/linux/rpm/chrome.spec.template index e878a85..08c402c 100644 --- a/chrome/installer/linux/rpm/chrome.spec.template +++ b/chrome/installer/linux/rpm/chrome.spec.template
@@ -89,7 +89,6 @@ /etc/cron.daily/@@PACKAGE@@ %ghost %attr(755,root,root) /usr/bin/google-chrome /usr/bin/@@USR_BIN_SYMLINK_NAME@@ -/usr/share/appdata/@@PACKAGE@@.appdata.xml /usr/share/applications/@@PACKAGE@@.desktop /usr/share/gnome-control-center/default-apps/@@PACKAGE@@.xml %docdir /usr/share/man/man1
diff --git a/chrome/test/chromedriver/VERSION b/chrome/test/chromedriver/VERSION index 7dba3a2..410158ac 100644 --- a/chrome/test/chromedriver/VERSION +++ b/chrome/test/chromedriver/VERSION
@@ -1 +1 @@ -2.27 +2.28
diff --git a/chromeos/dbus/fake_image_loader_client.cc b/chromeos/dbus/fake_image_loader_client.cc index 6f928576..bba0551 100644 --- a/chromeos/dbus/fake_image_loader_client.cc +++ b/chromeos/dbus/fake_image_loader_client.cc
@@ -14,5 +14,10 @@ const BoolDBusMethodCallback& callback) { callback.Run(DBUS_METHOD_CALL_FAILURE, false); } +void FakeImageLoaderClient::LoadComponent( + const std::string& name, + const StringDBusMethodCallback& callback) { + callback.Run(DBUS_METHOD_CALL_FAILURE, ""); +} } // namespace chromeos
diff --git a/chromeos/dbus/fake_image_loader_client.h b/chromeos/dbus/fake_image_loader_client.h index 5d98797..ee0c2d6 100644 --- a/chromeos/dbus/fake_image_loader_client.h +++ b/chromeos/dbus/fake_image_loader_client.h
@@ -26,6 +26,8 @@ const std::string& version, const std::string& component_folder_abs_path, const BoolDBusMethodCallback& callback) override; + void LoadComponent(const std::string& name, + const StringDBusMethodCallback& callback) override; private: DISALLOW_COPY_AND_ASSIGN(FakeImageLoaderClient);
diff --git a/chromeos/dbus/image_loader_client.cc b/chromeos/dbus/image_loader_client.cc index d1d7e9c..060c8b2 100644 --- a/chromeos/dbus/image_loader_client.cc +++ b/chromeos/dbus/image_loader_client.cc
@@ -37,6 +37,17 @@ base::Bind(&ImageLoaderClientImpl::OnBoolMethod, callback)); } + void LoadComponent(const std::string& name, + const StringDBusMethodCallback& callback) override { + dbus::MethodCall method_call(imageloader::kImageLoaderServiceInterface, + imageloader::kLoadComponent); + dbus::MessageWriter writer(&method_call); + writer.AppendString(name); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&ImageLoaderClientImpl::OnStringMethod, callback)); + } + protected: // DBusClient override. void Init(dbus::Bus* bus) override { @@ -62,6 +73,22 @@ callback.Run(DBUS_METHOD_CALL_SUCCESS, result); } + static void OnStringMethod(const StringDBusMethodCallback& callback, + dbus::Response* response) { + if (!response) { + callback.Run(DBUS_METHOD_CALL_FAILURE, ""); + return; + } + dbus::MessageReader reader(response); + std::string result; + if (!reader.PopString(&result)) { + callback.Run(DBUS_METHOD_CALL_FAILURE, ""); + LOG(ERROR) << "Invalid response: " << response->ToString(); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS, result); + } + dbus::ObjectProxy* proxy_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ImageLoaderClientImpl);
diff --git a/chromeos/dbus/image_loader_client.h b/chromeos/dbus/image_loader_client.h index f5dcd58..d7d889a 100644 --- a/chromeos/dbus/image_loader_client.h +++ b/chromeos/dbus/image_loader_client.h
@@ -28,6 +28,11 @@ const std::string& component_folder_abs_path, const BoolDBusMethodCallback& callback) = 0; + // Mount a component given the |name| and return the mount point (if call is + // successful). + virtual void LoadComponent(const std::string& name, + const StringDBusMethodCallback& callback) = 0; + // Factory function, creates a new instance and returns ownership. // For normal usage, access the singleton via DBusThreadManager::Get(). static ImageLoaderClient* Create();
diff --git a/components/browser_watcher/BUILD.gn b/components/browser_watcher/BUILD.gn index d4cc2ac..ff857fe0 100644 --- a/components/browser_watcher/BUILD.gn +++ b/components/browser_watcher/BUILD.gn
@@ -43,38 +43,28 @@ ] } - static_library("postmortem_minidump_writer") { - # TODO(manzagop): remove this lib once Crashpad writes the minidumps. + static_library("postmortem_report_collector") { sources = [ "postmortem_minidump_writer.h", "postmortem_minidump_writer_win.cc", - ] - deps = [ - ":stability_data", - ":stability_report_proto", - "//base", - "//third_party/crashpad/crashpad/client", - "//third_party/crashpad/crashpad/minidump", - "//third_party/crashpad/crashpad/util", - ] - } - - static_library("postmortem_report_collector") { - sources = [ "postmortem_report_collector.cc", "postmortem_report_collector.h", "postmortem_report_extractor.cc", "postmortem_report_extractor.h", + "system_session_analyzer_win.cc", + "system_session_analyzer_win.h", ] deps = [ - ":postmortem_minidump_writer", ":stability_data", ":stability_report_proto", "//base", "//components/variations", "//third_party/crashpad/crashpad/client", + "//third_party/crashpad/crashpad/minidump", "//third_party/crashpad/crashpad/util", ] + libs = [ "wevtapi.lib" ] + ldflags = [ "/DELAYLOAD:wevtapi.dll" ] # Only used after unclean shutdowns. } } @@ -105,6 +95,7 @@ "exit_code_watcher_win_unittest.cc", "postmortem_minidump_writer_win_unittest.cc", "postmortem_report_collector_unittest.cc", + "system_session_analyzer_win_unittest.cc", "watcher_client_win_unittest.cc", "watcher_metrics_provider_win_unittest.cc", "window_hang_monitor_win_unittest.cc", @@ -113,7 +104,6 @@ deps = [ ":browser_watcher", ":browser_watcher_client", - ":postmortem_minidump_writer", ":postmortem_report_collector", ":stability_data", ":stability_report_proto", @@ -140,4 +130,14 @@ "//base", ] } + + executable("fetch_system_session_events") { + sources = [ + "fetch_system_session_events_main_win.cc", + ] + deps = [ + ":postmortem_report_collector", + "//base", + ] + } }
diff --git a/components/browser_watcher/fetch_system_session_events_main_win.cc b/components/browser_watcher/fetch_system_session_events_main_win.cc new file mode 100644 index 0000000..2f17b933 --- /dev/null +++ b/components/browser_watcher/fetch_system_session_events_main_win.cc
@@ -0,0 +1,48 @@ +// Copyright 2017 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. + +// A utility for testing locally the retrieval of system session events. + +#include <iostream> + +#include "base/logging.h" +#include "base/strings/stringprintf.h" +#include "base/time/time.h" +#include "components/browser_watcher/system_session_analyzer_win.h" + +namespace { + +using browser_watcher::SystemSessionAnalyzer; + +class SystemSessionEventFetcher : public SystemSessionAnalyzer { + public: + explicit SystemSessionEventFetcher(uint32_t session_cnt) + : SystemSessionAnalyzer(session_cnt) {} + using SystemSessionAnalyzer::FetchEvents; +}; + +} // namespace + +int main(int argc, char** argv) { + // Retrieve events for the last 5 sessions. + SystemSessionEventFetcher fetcher(5U); + std::vector<SystemSessionEventFetcher::EventInfo> events; + if (!fetcher.FetchEvents(&events)) { + std::cerr << "Failed to fetch events." << std::endl; + return 1; + } + + // Print the event ids and times. + for (const SystemSessionEventFetcher::EventInfo& event : events) { + base::Time::Exploded exploded = {}; + event.event_time.LocalExplode(&exploded); + std::string time = base::StringPrintf( + "%d/%d/%d %d:%02d:%02d", exploded.month, exploded.day_of_month, + exploded.year, exploded.hour, exploded.minute, exploded.second); + std::cout << "Event: " << event.event_id << " (" << time << ")" + << std::endl; + } + + return 0; +}
diff --git a/components/browser_watcher/postmortem_report_collector.cc b/components/browser_watcher/postmortem_report_collector.cc index 7d375c2..35cc7b45 100644 --- a/components/browser_watcher/postmortem_report_collector.cc +++ b/components/browser_watcher/postmortem_report_collector.cc
@@ -24,20 +24,53 @@ using base::FilePath; using crashpad::CrashReportDatabase; +namespace { + +// DO NOT CHANGE VALUES. This is logged persistently in a histogram. +enum SystemSessionAnalysisStatus { + SYSTEM_SESSION_ANALYSIS_SUCCESS = 0, + SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP = 1, + SYSTEM_SESSION_ANALYSIS_NO_ANALYZER = 2, + SYSTEM_SESSION_ANALYSIS_FAILED = 3, + SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE = 4, + SYSTEM_SESSION_ANALYSIS_STATUS_MAX = 5 +}; + +bool GetStartTimestamp( + const google::protobuf::Map<std::string, TypedValue>& global_data, + base::Time* time) { + DCHECK(time); + + const auto& it = global_data.find(kStabilityStartTimestamp); + if (it == global_data.end()) + return false; + + const TypedValue& value = it->second; + if (value.value_case() != TypedValue::kSignedValue) + return false; + + *time = base::Time::FromInternalValue(value.signed_value()); + return true; +} + +} // namespace + PostmortemReportCollector::PostmortemReportCollector( const std::string& product_name, const std::string& version_number, - const std::string& channel_name) + const std::string& channel_name, + SystemSessionAnalyzer* analyzer) : product_name_(product_name), version_number_(version_number), - channel_name_(channel_name) {} + channel_name_(channel_name), + system_session_analyzer_(analyzer) {} PostmortemReportCollector::~PostmortemReportCollector() {} -int PostmortemReportCollector::CollectAndSubmitForUpload( - const FilePath& debug_info_dir, - const FilePath::StringType& debug_file_pattern, - const std::set<FilePath>& excluded_debug_files, +int PostmortemReportCollector::CollectAndSubmitAllPendingReports( + const base::FilePath& debug_info_dir, + const base::FilePath::StringType& debug_file_pattern, + const std::set<base::FilePath>& excluded_debug_files, crashpad::CrashReportDatabase* report_database) { DCHECK_NE(true, debug_info_dir.empty()); DCHECK_NE(true, debug_file_pattern.empty()); @@ -62,7 +95,7 @@ int success_cnt = 0; for (const FilePath& file : debug_files) { CollectionStatus status = - CollectAndSubmit(client_id, file, report_database); + CollectAndSubmitOneReport(client_id, file, report_database); // TODO(manzagop): consider making this a stability metric. UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.Status", status, COLLECTION_STATUS_MAX); @@ -92,7 +125,7 @@ return paths; } -CollectionStatus PostmortemReportCollector::CollectAndSubmit( +CollectionStatus PostmortemReportCollector::CollectAndSubmitOneReport( const crashpad::UUID& client_id, const FilePath& file, crashpad::CrashReportDatabase* report_database) { @@ -104,7 +137,7 @@ // Collect the data from the debug file to a proto. Note: a non-empty report // is interpreted here as an unclean exit. StabilityReport report_proto; - CollectionStatus status = Collect(file, &report_proto); + CollectionStatus status = CollectOneReport(file, &report_proto); if (status != SUCCESS) { // The file was empty, or there was an error collecting the data. Detailed // logging happens within the Collect function. @@ -159,16 +192,30 @@ return SUCCESS; } -CollectionStatus PostmortemReportCollector::Collect(const base::FilePath& file, - StabilityReport* report) { +CollectionStatus PostmortemReportCollector::CollectOneReport( + const base::FilePath& file, + StabilityReport* report) { DCHECK(report); + CollectionStatus status = Extract(file, report); if (status != SUCCESS) return status; - // Add the reporter's details to the report. + SetReporterDetails(report); + RecordSystemShutdownState(report); + + return SUCCESS; +} + +void PostmortemReportCollector::SetReporterDetails( + StabilityReport* report) const { + DCHECK(report); + google::protobuf::Map<std::string, TypedValue>& global_data = *(report->mutable_global_data()); + + // Reporter version details. These are useful as the reporter may be of a + // different version. global_data[kStabilityReporterChannel].set_string_value(channel_name()); #if defined(ARCH_CPU_X86) global_data[kStabilityReporterPlatform].set_string_value( @@ -179,8 +226,47 @@ #endif global_data[kStabilityReporterProduct].set_string_value(product_name()); global_data[kStabilityReporterVersion].set_string_value(version_number()); +} - return SUCCESS; +void PostmortemReportCollector::RecordSystemShutdownState( + StabilityReport* report) const { + DCHECK(report); + + // The session state for the stability report, recorded to provided visibility + // into whether the system session was clean. + SystemState::SessionState session_state = SystemState::UNKNOWN; + // The status of the analysis, recorded to provide insight into the success + // or failure of the analysis. + SystemSessionAnalysisStatus status = SYSTEM_SESSION_ANALYSIS_SUCCESS; + + base::Time time; + if (!GetStartTimestamp(report->global_data(), &time)) { + status = SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP; + } else if (!system_session_analyzer_) { + status = SYSTEM_SESSION_ANALYSIS_NO_ANALYZER; + } else { + SystemSessionAnalyzer::Status analyzer_status = + system_session_analyzer_->IsSessionUnclean(time); + switch (analyzer_status) { + case SystemSessionAnalyzer::FAILED: + status = SYSTEM_SESSION_ANALYSIS_FAILED; + break; + case SystemSessionAnalyzer::CLEAN: + session_state = SystemState::CLEAN; + break; + case SystemSessionAnalyzer::UNCLEAN: + session_state = SystemState::UNCLEAN; + break; + case SystemSessionAnalyzer::OUTSIDE_RANGE: + status = SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE; + break; + } + } + + report->mutable_system_state()->set_session_state(session_state); + UMA_HISTOGRAM_ENUMERATION( + "ActivityTracker.Collect.SystemSessionAnalysisStatus", status, + SYSTEM_SESSION_ANALYSIS_STATUS_MAX); } bool PostmortemReportCollector::WriteReportToMinidump(
diff --git a/components/browser_watcher/postmortem_report_collector.h b/components/browser_watcher/postmortem_report_collector.h index ba9c075..aab3ab8 100644 --- a/components/browser_watcher/postmortem_report_collector.h +++ b/components/browser_watcher/postmortem_report_collector.h
@@ -23,6 +23,7 @@ #include "base/strings/string16.h" #include "components/browser_watcher/postmortem_report_extractor.h" #include "components/browser_watcher/stability_report.pb.h" +#include "components/browser_watcher/system_session_analyzer_win.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" namespace browser_watcher { @@ -37,7 +38,8 @@ public: PostmortemReportCollector(const std::string& product_name, const std::string& version_number, - const std::string& channel_name); + const std::string& channel_name, + SystemSessionAnalyzer* analyzer); virtual ~PostmortemReportCollector(); // Collects postmortem stability reports from files found in |debug_info_dir|, @@ -46,7 +48,7 @@ // Returns the number crash reports successfully registered with the reporter. // TODO(manzagop): consider mechanisms for partial collection if this is to be // used on a critical path. - int CollectAndSubmitForUpload( + int CollectAndSubmitAllPendingReports( const base::FilePath& debug_info_dir, const base::FilePath::StringType& debug_file_pattern, const std::set<base::FilePath>& excluded_debug_files, @@ -75,6 +77,9 @@ FRIEND_TEST_ALL_PREFIXES( PostmortemReportCollectorCollectionFromGlobalTrackerTest, ModuleCollection); + FRIEND_TEST_ALL_PREFIXES( + PostmortemReportCollectorCollectionFromGlobalTrackerTest, + SystemStateTest); // Virtual for unittesting. virtual std::vector<base::FilePath> GetDebugStateFilePaths( @@ -82,13 +87,18 @@ const base::FilePath::StringType& debug_file_pattern, const std::set<base::FilePath>& excluded_debug_files); - CollectionStatus CollectAndSubmit( + CollectionStatus CollectAndSubmitOneReport( const crashpad::UUID& client_id, const base::FilePath& file, crashpad::CrashReportDatabase* report_database); - virtual CollectionStatus Collect(const base::FilePath& stability_file, - StabilityReport* report); + virtual CollectionStatus CollectOneReport( + const base::FilePath& stability_file, + StabilityReport* report); + + void SetReporterDetails(StabilityReport* report) const; + + void RecordSystemShutdownState(StabilityReport* report) const; virtual bool WriteReportToMinidump(StabilityReport* report, const crashpad::UUID& client_id, @@ -99,6 +109,8 @@ std::string version_number_; std::string channel_name_; + SystemSessionAnalyzer* system_session_analyzer_; // Not owned. + DISALLOW_COPY_AND_ASSIGN(PostmortemReportCollector); };
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc index b25dcc8b..14fbf72 100644 --- a/components/browser_watcher/postmortem_report_collector_unittest.cc +++ b/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -108,18 +108,21 @@ CrashReportDatabase::OperationStatus(const UUID& uuid)); }; -// Used for testing CollectAndSubmitForUpload. +// Used for testing CollectAndSubmitAllPendingReports. class MockPostmortemReportCollector : public PostmortemReportCollector { public: MockPostmortemReportCollector() - : PostmortemReportCollector(kProductName, kVersionNumber, kChannelName) {} + : PostmortemReportCollector(kProductName, + kVersionNumber, + kChannelName, + nullptr) {} MOCK_METHOD3(GetDebugStateFilePaths, std::vector<base::FilePath>( const base::FilePath& debug_info_dir, const base::FilePath::StringType& debug_file_pattern, const std::set<base::FilePath>&)); - MOCK_METHOD2(Collect, + MOCK_METHOD2(CollectOneReport, CollectionStatus(const base::FilePath&, StabilityReport* report)); MOCK_METHOD4(WriteReportToMinidump, @@ -129,6 +132,12 @@ base::PlatformFile minidump_file)); }; +class MockSystemSessionAnalyzer : public SystemSessionAnalyzer { + public: + MockSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {} + MOCK_METHOD1(IsSessionUnclean, Status(base::Time timestamp)); +}; + // Checks if two proto messages are the same based on their serializations. Note // this only works if serialization is deterministic, which is not guaranteed. // In practice, serialization is deterministic (even for protocol buffers with @@ -150,7 +159,8 @@ } // namespace -class PostmortemReportCollectorCollectAndSubmitTest : public testing::Test { +class PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest + : public testing::Test { public: void SetUp() override { testing::Test::SetUp(); @@ -175,7 +185,7 @@ EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); // Expect a single collection call. - EXPECT_CALL(collector_, Collect(debug_file_, _)) + EXPECT_CALL(collector_, CollectOneReport(debug_file_, _)) .Times(1) .WillOnce(Return(SUCCESS)); @@ -210,22 +220,22 @@ CrashReportDatabase::NewReport crashpad_report_; }; -TEST_F(PostmortemReportCollectorCollectAndSubmitTest, - CollectAndSubmitForUpload) { +TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, + CollectAndSubmitAllPendingReports) { EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _)) .Times(1) .WillOnce(Return(CrashReportDatabase::kNoError)); // Run the test. - int success_cnt = collector_.CollectAndSubmitForUpload( + int success_cnt = collector_.CollectAndSubmitAllPendingReports( debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, &database_); ASSERT_EQ(1, success_cnt); ASSERT_FALSE(base::PathExists(debug_file_)); } -TEST_F(PostmortemReportCollectorCollectAndSubmitTest, - CollectAndSubmitForUploadStuckFile) { +TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, + CollectAndSubmitAllPendingReportsStuckFile) { // Open the stability debug file to prevent its deletion. base::ScopedFILE file(base::OpenFile(debug_file_, "w")); ASSERT_NE(file.get(), nullptr); @@ -236,7 +246,7 @@ .WillOnce(Return(CrashReportDatabase::kNoError)); // Run the test. - int success_cnt = collector_.CollectAndSubmitForUpload( + int success_cnt = collector_.CollectAndSubmitAllPendingReports( debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, &database_); ASSERT_EQ(0, success_cnt); @@ -276,7 +286,7 @@ } PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); EXPECT_THAT( collector.GetDebugStateFilePaths( temp_dir.GetPath(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), @@ -296,9 +306,10 @@ // Validate collection: an empty file cannot suppport an analyzer. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(ANALYZER_CREATION_FAILED, collector.Collect(file_path, &report)); + ASSERT_EQ(ANALYZER_CREATION_FAILED, + collector.CollectOneReport(file_path, &report)); } TEST(PostmortemReportCollectorTest, CollectRandomFile) { @@ -322,9 +333,9 @@ // Validate collection: random content appears as though there is not // stability data. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(DEBUG_FILE_NO_DATA, collector.Collect(file_path, &report)); + ASSERT_EQ(DEBUG_FILE_NO_DATA, collector.CollectOneReport(file_path, &report)); } namespace { @@ -448,9 +459,9 @@ // Validate collection returns the expected report. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(SUCCESS, collector.Collect(debug_file_path(), &report)); + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); // Validate the report. ASSERT_EQ(1, report.process_states_size()); @@ -545,9 +556,9 @@ // Collect the stability report. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(SUCCESS, collector.Collect(debug_file_path(), &report)); + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); // Validate the report's log content. ASSERT_EQ(2, report.log_messages_size()); @@ -575,9 +586,9 @@ // Collect the stability report. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(SUCCESS, collector.Collect(debug_file_path(), &report)); + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); // Validate the report's user data. const auto& collected_data = report.global_data(); @@ -644,9 +655,9 @@ // Collect the stability report. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(SUCCESS, collector.Collect(debug_file_path(), &report)); + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); // Validate the report's experiment and global data. ASSERT_EQ(2, report.field_trials_size()); @@ -685,9 +696,9 @@ // Collect the stability report. PostmortemReportCollector collector(kProductName, kVersionNumber, - kChannelName); + kChannelName, nullptr); StabilityReport report; - ASSERT_EQ(SUCCESS, collector.Collect(debug_file_path(), &report)); + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); // Validate the report's modules content. ASSERT_EQ(1, report.process_states_size()); @@ -708,4 +719,27 @@ EXPECT_EQ(!module_info.is_loaded, collected_module.is_unloaded()); } +TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, + SystemStateTest) { + // Setup. + GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, + "", 3); + ActivityUserData& global_data = GlobalActivityTracker::Get()->global_data(); + global_data.SetInt(kStabilityStartTimestamp, 12345LL); + + // Collect. + MockSystemSessionAnalyzer analyzer; + EXPECT_CALL(analyzer, + IsSessionUnclean(base::Time::FromInternalValue(12345LL))) + .Times(1) + .WillOnce(Return(SystemSessionAnalyzer::CLEAN)); + PostmortemReportCollector collector(kProductName, kVersionNumber, + kChannelName, &analyzer); + StabilityReport report; + ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); + + // Validate the report. + ASSERT_EQ(SystemState::CLEAN, report.system_state().session_state()); +} + } // namespace browser_watcher
diff --git a/components/browser_watcher/stability_data_names.cc b/components/browser_watcher/stability_data_names.cc index d1a3eed..63341220 100644 --- a/components/browser_watcher/stability_data_names.cc +++ b/components/browser_watcher/stability_data_names.cc
@@ -15,6 +15,7 @@ const char kStabilityReporterProduct[] = "reporter-product"; const char kStabilityReporterVersion[] = "reporter-version"; const char kStabilitySpecialBuild[] = "special-build"; +const char kStabilityStartTimestamp[] = "start-timestamp"; const char kStabilityVersion[] = "version"; } // namespace browser_watcher
diff --git a/components/browser_watcher/stability_data_names.h b/components/browser_watcher/stability_data_names.h index 1bf1f89..4ee91012 100644 --- a/components/browser_watcher/stability_data_names.h +++ b/components/browser_watcher/stability_data_names.h
@@ -17,6 +17,7 @@ extern const char kStabilityReporterProduct[]; extern const char kStabilityReporterVersion[]; extern const char kStabilitySpecialBuild[]; +extern const char kStabilityStartTimestamp[]; extern const char kStabilityVersion[]; } // namespace browser_watcher
diff --git a/components/browser_watcher/stability_report.proto b/components/browser_watcher/stability_report.proto index b5039a2..015d4751 100644 --- a/components/browser_watcher/stability_report.proto +++ b/components/browser_watcher/stability_report.proto
@@ -10,9 +10,18 @@ // The state of the system on which Chrome is running (shutting down, battery // level, load, etc.). -// Next id: 1 +// Next id: 2 message SystemState { - // TODO(manzagop): flesh out. + // The state of a system session. A system session begins when the system + // starts and ends when it shuts down. + enum SessionState { + UNKNOWN = 0; + CLEAN = 1; // Normal shutdown. + UNCLEAN = 2; // Abnormal shutdown (system crash, power loss). + } + + // The state of the system session that contained Chrome's execution. + optional SessionState session_state = 1; } // Next id: 10
diff --git a/components/browser_watcher/system_session_analyzer_win.cc b/components/browser_watcher/system_session_analyzer_win.cc new file mode 100644 index 0000000..e488219 --- /dev/null +++ b/components/browser_watcher/system_session_analyzer_win.cc
@@ -0,0 +1,244 @@ +// Copyright 2017 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/browser_watcher/system_session_analyzer_win.h" + +#include <windows.h> +#include <winevt.h> + +#include <utility> + +#include "base/macros.h" +#include "base/time/time.h" + +namespace browser_watcher { + +namespace { + +// The name of the log channel to query. +const wchar_t kChannelName[] = L"System"; + +// Event ids of system startup / shutdown events. These were obtained from +// inspection of the System log in Event Viewer on Windows 10: +// - id 6005: "The Event log service was started." +// - id 6006: "The Event log service was stopped." +// - id 6008: "The previous system shutdown at <time> on <date> was +// unexpected." +const uint16_t kIdSessionStart = 6005U; +const uint16_t kIdSessionEnd = 6006U; +const uint16_t kIdSessionEndUnclean = 6008U; + +// An XPATH expression to query for system startup / shutdown events. The query +// is expected to retrieve exactly one event for each startup (kIdSessionStart) +// and one event for each shutdown (either kIdSessionEnd or +// kIdSessionEndUnclean). +const wchar_t kSessionEventsQuery[] = + L"*[System[Provider[@Name='eventlog']" + L" and (EventID=6005 or EventID=6006 or EventID=6008)]]"; + +// XPath expressions to attributes of interest. +const wchar_t kEventIdPath[] = L"Event/System/EventID"; +const wchar_t kEventTimePath[] = L"Event/System/TimeCreated/@SystemTime"; + +// The timeout to use for calls to ::EvtNext. +const uint32_t kTimeoutMs = 5000; + +struct EvtHandleCloser { + using pointer = EVT_HANDLE; + void operator()(EVT_HANDLE handle) const { + if (handle) + ::EvtClose(handle); + } +}; + +using EvtHandle = std::unique_ptr<EVT_HANDLE, EvtHandleCloser>; + +base::Time ULLFileTimeToTime(ULONGLONG time_ulonglong) { + // Copy low / high parts as FILETIME is not always 64bit aligned. + ULARGE_INTEGER time; + time.QuadPart = time_ulonglong; + FILETIME ft; + ft.dwLowDateTime = time.LowPart; + ft.dwHighDateTime = time.HighPart; + + return base::Time::FromFileTime(ft); +} + +// Create a render context (i.e. specify attributes of interest). +EvtHandle CreateRenderContext() { + LPCWSTR value_paths[] = {kEventIdPath, kEventTimePath}; + const DWORD kValueCnt = arraysize(value_paths); + + EVT_HANDLE context = NULL; + context = + ::EvtCreateRenderContext(kValueCnt, value_paths, EvtRenderContextValues); + if (!context) + DLOG(ERROR) << "Failed to create render context."; + + return EvtHandle(context); +} + +bool GetEventInfo(EVT_HANDLE context, + EVT_HANDLE event, + SystemSessionAnalyzer::EventInfo* info) { + DCHECK(context); + DCHECK(event); + DCHECK(info); + + // Retrieve attributes of interest from the event. We expect the context to + // specify the retrieval of two attributes (event id and event time), each + // with a specific type. + const DWORD kAttributeCnt = 2U; + std::vector<EVT_VARIANT> buffer(kAttributeCnt); + DWORD buffer_size = kAttributeCnt * sizeof(EVT_VARIANT); + DWORD buffer_used = 0U; + DWORD retrieved_attribute_cnt = 0U; + if (!::EvtRender(context, event, EvtRenderEventValues, buffer_size, + buffer.data(), &buffer_used, &retrieved_attribute_cnt)) { + DLOG(ERROR) << "Failed to render the event."; + return false; + } + + // Validate the count and types of the retrieved attributes. + if ((retrieved_attribute_cnt != kAttributeCnt) || + (buffer[0].Type != EvtVarTypeUInt16) || + (buffer[1].Type != EvtVarTypeFileTime)) { + return false; + } + + info->event_id = buffer[0].UInt16Val; + info->event_time = ULLFileTimeToTime(buffer[1].FileTimeVal); + + return true; +} + +} // namespace + +SystemSessionAnalyzer::SystemSessionAnalyzer(uint32_t session_cnt) + : session_cnt_(session_cnt) {} + +SystemSessionAnalyzer::~SystemSessionAnalyzer() {} + +SystemSessionAnalyzer::Status SystemSessionAnalyzer::IsSessionUnclean( + base::Time timestamp) { + if (!initialized_) { + DCHECK(!init_success_); + init_success_ = Initialize(); + initialized_ = true; + } + if (!init_success_) + return FAILED; + if (timestamp < coverage_start_) + return OUTSIDE_RANGE; + + // Get the first session starting after the timestamp. + std::map<base::Time, base::TimeDelta>::const_iterator it = + unclean_sessions_.upper_bound(timestamp); + if (it == unclean_sessions_.begin()) + return CLEAN; // No prior unclean session. + + // Get the previous session and see if it encompasses the timestamp. + --it; + bool is_spanned = (timestamp - it->first) <= it->second; + return is_spanned ? UNCLEAN : CLEAN; +} + +bool SystemSessionAnalyzer::FetchEvents( + std::vector<EventInfo>* event_infos) const { + DCHECK(event_infos); + + // Query for the events. Note: requesting events from newest to oldest. + EVT_HANDLE query_raw = + ::EvtQuery(nullptr, kChannelName, kSessionEventsQuery, + EvtQueryChannelPath | EvtQueryReverseDirection); + if (!query_raw) { + DLOG(ERROR) << "Event query failed."; + return false; + } + EvtHandle query(query_raw); + + // Retrieve events: 2 events per session, plus the current session's start. + DWORD desired_event_cnt = 2U * session_cnt_ + 1U; + std::vector<EVT_HANDLE> events_raw(desired_event_cnt, NULL); + DWORD event_cnt = 0U; + BOOL success = ::EvtNext(query.get(), desired_event_cnt, events_raw.data(), + kTimeoutMs, 0, &event_cnt); + + // Ensure handles get closed. The MSDN sample seems to imply handles may need + // to be closed event in if EvtNext failed. + std::vector<EvtHandle> events(desired_event_cnt); + for (size_t i = 0; i < event_cnt; ++i) + events[i].reset(events_raw[i]); + + if (!success) { + DLOG(ERROR) << "Failed to retrieve events."; + return false; + } + + // Extract information from the events. + EvtHandle render_context = CreateRenderContext(); + if (!render_context.get()) + return false; + + std::vector<EventInfo> event_infos_tmp; + event_infos_tmp.reserve(event_cnt); + + EventInfo info = {}; + for (size_t i = 0; i < event_cnt; ++i) { + if (!GetEventInfo(render_context.get(), events[i].get(), &info)) + return false; + event_infos_tmp.push_back(info); + } + + event_infos->swap(event_infos_tmp); + return true; +} + +bool SystemSessionAnalyzer::Initialize() { + std::vector<SystemSessionAnalyzer::EventInfo> events; + if (!FetchEvents(&events)) + return false; + + // Validate the number and ordering of events (newest to oldest). The + // expectation is a (start / [unclean]shutdown) pair of events for each + // session, as well as an additional event for the current session's start. + size_t event_cnt = events.size(); + if ((event_cnt % 2) == 0) + return false; // Even number is unexpected. + if (event_cnt < 3) + return false; // Not enough data for a single session. + for (size_t i = 1; i < event_cnt; ++i) { + if (events[i - 1].event_time < events[i].event_time) + return false; + } + + // Step through (start / shutdown) event pairs, validating the types of events + // and recording unclean sessions. + std::map<base::Time, base::TimeDelta> unclean_sessions; + size_t start = 2U; + size_t end = 1U; + for (; start < event_cnt && end < event_cnt; start += 2, end += 2) { + uint16_t start_id = events[start].event_id; + uint16_t end_id = events[end].event_id; + if (start_id != kIdSessionStart) + return false; // Unexpected event type. + if (end_id != kIdSessionEnd && end_id != kIdSessionEndUnclean) + return false; // Unexpected event type. + + if (end_id == kIdSessionEnd) + continue; // This is a clean session. + + unclean_sessions.insert( + std::make_pair(events[start].event_time, + events[end].event_time - events[start].event_time)); + } + + unclean_sessions_.swap(unclean_sessions); + DCHECK_GT(event_cnt, 0U); + coverage_start_ = events[event_cnt - 1].event_time; + + return true; +} + +} // namespace browser_watcher
diff --git a/components/browser_watcher/system_session_analyzer_win.h b/components/browser_watcher/system_session_analyzer_win.h new file mode 100644 index 0000000..33162cd --- /dev/null +++ b/components/browser_watcher/system_session_analyzer_win.h
@@ -0,0 +1,75 @@ +// Copyright 2017 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_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_ +#define COMPONENTS_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "base/gtest_prod_util.h" +#include "base/time/time.h" + +namespace browser_watcher { + +// Analyzes system session events for unclean sessions. Initialization is +// expensive and therefore done lazily, as the analyzer is instantiated before +// knowing whether it will be used. +class SystemSessionAnalyzer { + public: + enum Status { + FAILED = 0, + CLEAN = 1, + UNCLEAN = 2, + OUTSIDE_RANGE = 3, + }; + + // Minimal information about a log event. + struct EventInfo { + uint16_t event_id; + base::Time event_time; + }; + + // Creates a SystemSessionAnalyzer that will analyze system sessions based on + // events pertaining to the last session_cnt system sessions. + explicit SystemSessionAnalyzer(uint32_t session_cnt); + virtual ~SystemSessionAnalyzer(); + + // Returns an analysis status for the system session that contains timestamp. + virtual Status IsSessionUnclean(base::Time timestamp); + + protected: + // Queries for events pertaining to the last session_cnt sessions. On success, + // returns true and event_infos contains events ordered from newest to oldest. + // Returns false otherwise. Virtual for unit testing. + virtual bool FetchEvents(std::vector<EventInfo>* event_infos) const; + + private: + FRIEND_TEST_ALL_PREFIXES(SystemSessionAnalyzerTest, FetchEvents); + + bool Initialize(); + + // The number of sessions to query events for. + uint32_t session_cnt_; + + bool initialized_ = false; + bool init_success_ = false; + + // Information about unclean sessions: start time to duration until the next + // session start, ie *not* session duration. Note: it's easier to get the + // delta to the next session start, and changes nothing wrt classifying + // events that occur during sessions assuming query timestamps fall within + // system sessions. + std::map<base::Time, base::TimeDelta> unclean_sessions_; + + // Timestamp of the oldest event. + base::Time coverage_start_; + + DISALLOW_COPY_AND_ASSIGN(SystemSessionAnalyzer); +}; + +} // namespace browser_watcher + +#endif // COMPONENTS_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_
diff --git a/components/browser_watcher/system_session_analyzer_win_unittest.cc b/components/browser_watcher/system_session_analyzer_win_unittest.cc new file mode 100644 index 0000000..62c96234 --- /dev/null +++ b/components/browser_watcher/system_session_analyzer_win_unittest.cc
@@ -0,0 +1,117 @@ +// Copyright 2017 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/browser_watcher/system_session_analyzer_win.h" + +#include <utility> +#include <vector> + +#include "base/time/time.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace browser_watcher { + +namespace { + +const uint16_t kIdSessionStart = 6005U; +const uint16_t kIdSessionEnd = 6006U; +const uint16_t kIdSessionEndUnclean = 6008U; + +} // namespace + +// Ensure the fetcher retrieves events. +// Note: this test fails if the host system doesn't have at least 1 prior +// session. +TEST(SystemSessionAnalyzerTest, FetchEvents) { + SystemSessionAnalyzer analyzer(1U); + std::vector<SystemSessionAnalyzer::EventInfo> events; + ASSERT_TRUE(analyzer.FetchEvents(&events)); + EXPECT_EQ(3U, events.size()); +} + +// Ensure the fetcher's retrieved events conform to our expectations. +// Note: this test fails if the host system doesn't have at least 1 prior +// session. +TEST(SystemSessionAnalyzerTest, ValidateEvents) { + SystemSessionAnalyzer analyzer(1U); + EXPECT_EQ(SystemSessionAnalyzer::CLEAN, + analyzer.IsSessionUnclean(base::Time::Now())); +} + +// Stubs FetchEvents. +class StubSystemSessionAnalyzer : public SystemSessionAnalyzer { + public: + StubSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {} + + bool FetchEvents(std::vector<EventInfo>* event_infos) const override { + DCHECK(event_infos); + *event_infos = events_; + return true; + } + + void AddEvent(const EventInfo& info) { events_.push_back(info); } + + private: + std::vector<EventInfo> events_; +}; + +TEST(SystemSessionAnalyzerTest, StandardCase) { + StubSystemSessionAnalyzer analyzer; + + base::Time time = base::Time::Now(); + analyzer.AddEvent({kIdSessionStart, time}); + analyzer.AddEvent( + {kIdSessionEndUnclean, time - base::TimeDelta::FromSeconds(10)}); + analyzer.AddEvent({kIdSessionStart, time - base::TimeDelta::FromSeconds(20)}); + analyzer.AddEvent({kIdSessionEnd, time - base::TimeDelta::FromSeconds(22)}); + analyzer.AddEvent({kIdSessionStart, time - base::TimeDelta::FromSeconds(28)}); + + EXPECT_EQ(SystemSessionAnalyzer::OUTSIDE_RANGE, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(30))); + EXPECT_EQ(SystemSessionAnalyzer::CLEAN, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(25))); + EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(20))); + EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(15))); + EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(10))); + EXPECT_EQ(SystemSessionAnalyzer::CLEAN, + analyzer.IsSessionUnclean(time - base::TimeDelta::FromSeconds(5))); + EXPECT_EQ(SystemSessionAnalyzer::CLEAN, + analyzer.IsSessionUnclean(time + base::TimeDelta::FromSeconds(5))); +} + +TEST(SystemSessionAnalyzerTest, NoEvent) { + StubSystemSessionAnalyzer analyzer; + EXPECT_EQ(SystemSessionAnalyzer::FAILED, + analyzer.IsSessionUnclean(base::Time::Now())); +} + +TEST(SystemSessionAnalyzerTest, TimeInversion) { + StubSystemSessionAnalyzer analyzer; + + base::Time time = base::Time::Now(); + analyzer.AddEvent({kIdSessionStart, time}); + analyzer.AddEvent({kIdSessionEnd, time + base::TimeDelta::FromSeconds(1)}); + analyzer.AddEvent({kIdSessionStart, time - base::TimeDelta::FromSeconds(1)}); + + EXPECT_EQ(SystemSessionAnalyzer::FAILED, + analyzer.IsSessionUnclean(base::Time::Now())); +} + +TEST(SystemSessionAnalyzerTest, IdInversion) { + StubSystemSessionAnalyzer analyzer; + + base::Time time = base::Time::Now(); + analyzer.AddEvent({kIdSessionStart, time}); + analyzer.AddEvent({kIdSessionStart, time - base::TimeDelta::FromSeconds(1)}); + analyzer.AddEvent({kIdSessionEnd, time - base::TimeDelta::FromSeconds(2)}); + + EXPECT_EQ(SystemSessionAnalyzer::FAILED, + analyzer.IsSessionUnclean(base::Time::Now())); +} + +} // namespace browser_watcher
diff --git a/components/browser_watcher/watcher_metrics_provider_win.cc b/components/browser_watcher/watcher_metrics_provider_win.cc index 74db4f5..45617eb 100644 --- a/components/browser_watcher/watcher_metrics_provider_win.cc +++ b/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -9,6 +9,7 @@ #include <limits> #include <memory> #include <set> +#include <utility> #include <vector> #include "base/bind.h" @@ -25,6 +26,7 @@ #include "components/browser_watcher/features.h" #include "components/browser_watcher/postmortem_report_collector.h" #include "components/browser_watcher/stability_debugging.h" +#include "components/browser_watcher/system_session_analyzer_win.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" namespace browser_watcher { @@ -263,15 +265,18 @@ LogCollectionInitStatus(INIT_SUCCESS); - // TODO(manzagop): fix incorrect version attribution on update. + // Get the reporter's version details. base::string16 product_name, version_number, channel_name; exe_details_cb_.Run(&product_name, &version_number, &channel_name); - PostmortemReportCollector collector(base::UTF16ToUTF8(product_name), - base::UTF16ToUTF8(version_number), - base::UTF16ToUTF8(channel_name)); - collector.CollectAndSubmitForUpload(stability_dir, GetStabilityFilePattern(), - excluded_debug_files, - crashpad_database.get()); + + const size_t kSystemSessionsToInspect = 5U; + SystemSessionAnalyzer analyzer(kSystemSessionsToInspect); + PostmortemReportCollector collector( + base::UTF16ToUTF8(product_name), base::UTF16ToUTF8(version_number), + base::UTF16ToUTF8(channel_name), &analyzer); + collector.CollectAndSubmitAllPendingReports( + stability_dir, GetStabilityFilePattern(), excluded_debug_files, + crashpad_database.get()); } } // namespace browser_watcher
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 6046a36..e91c8e0 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -15,8 +15,8 @@ "compositor_frame_sink_holder.h", "display.cc", "display.h", - "gamepad.cc", - "gamepad.h", + "gaming_seat.cc", + "gaming_seat.h", "keyboard.cc", "keyboard.h", "keyboard_delegate.h", @@ -113,7 +113,7 @@ sources = [ "buffer_unittest.cc", "display_unittest.cc", - "gamepad_unittest.cc", + "gaming_seat_unittest.cc", "keyboard_unittest.cc", "pointer_unittest.cc", "shared_memory_unittest.cc",
diff --git a/components/exo/gamepad.h b/components/exo/gamepad.h deleted file mode 100644 index f1991a1f..0000000 --- a/components/exo/gamepad.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 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_EXO_GAMEPAD_H_ -#define COMPONENTS_EXO_GAMEPAD_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/exo/wm_helper.h" -#include "device/gamepad/gamepad_data_fetcher.h" -#include "ui/aura/client/focus_change_observer.h" - -namespace exo { -class GamepadDelegate; - -using CreateGamepadDataFetcherCallback = - base::Callback<std::unique_ptr<device::GamepadDataFetcher>()>; - -// This class represents one or more gamepads, it uses a background thread -// for polling gamepad devices and notifies the GamepadDelegate of any -// changes. -class Gamepad : public WMHelper::FocusObserver { - public: - // This class will post tasks to invoke the delegate on the thread runner - // which is associated with the thread that is creating this instance. - Gamepad(GamepadDelegate* delegate, - base::SingleThreadTaskRunner* polling_task_runner); - // Allows test cases to specify a CreateGamepadDataFetcherCallback that - // overrides the default GamepadPlatformDataFetcher. - Gamepad(GamepadDelegate* delegate, - base::SingleThreadTaskRunner* polling_task_runner, - CreateGamepadDataFetcherCallback create_fetcher_callback); - ~Gamepad() override; - - // Overridden WMHelper::FocusObserver: - void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) override; - - private: - class ThreadSafeGamepadChangeFetcher; - - // Processes updates of gamepad data and passes changes on to delegate. - void ProcessGamepadChanges(const blink::WebGamepad new_pad); - - // Private implementation of methods and resources that are used on the - // polling thread. - scoped_refptr<ThreadSafeGamepadChangeFetcher> gamepad_change_fetcher_; - - // The delegate instance that all events are dispatched to. - GamepadDelegate* const delegate_; - - // The current state of the gamepad represented by this instance. - blink::WebGamepad pad_state_; - - // ThreadChecker for the origin thread. - base::ThreadChecker thread_checker_; - - base::WeakPtrFactory<Gamepad> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Gamepad); -}; - -} // namespace exo - -#endif // COMPONENTS_EXO_GAMEPAD_H_
diff --git a/components/exo/gamepad_delegate.h b/components/exo/gamepad_delegate.h index 5304413..a917582 100644 --- a/components/exo/gamepad_delegate.h +++ b/components/exo/gamepad_delegate.h
@@ -5,25 +5,13 @@ #ifndef COMPONENTS_EXO_GAMEPAD_DELEGATE_H_ #define COMPONENTS_EXO_GAMEPAD_DELEGATE_H_ -#include "base/memory/weak_ptr.h" - namespace exo { -class Gamepad; -class Surface; -// Handles events on multiple gamepad +// Handles events for a specific gamepad. class GamepadDelegate { public: - // Gives the delegate a chance to clean up when the Gamepad instance is - // destroyed. - virtual void OnGamepadDestroying(Gamepad* gamepad) = 0; - - // This should return true if |surface| is a valid target for this gamepad. - // E.g. the surface is owned by the same client as the gamepad. - virtual bool CanAcceptGamepadEventsForSurface(Surface* surface) const = 0; - - // Called when the state of the gamepad has changed. - virtual void OnStateChange(bool connected) = 0; + // Called when the gamepad has been removed. + virtual void OnRemoved() = 0; // Called when the user moved an axis of the gamepad. Valid axes are defined // by the W3C 'standard gamepad' specification.
diff --git a/components/exo/gamepad_unittest.cc b/components/exo/gamepad_unittest.cc deleted file mode 100644 index 560c7e4..0000000 --- a/components/exo/gamepad_unittest.cc +++ /dev/null
@@ -1,219 +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 "ash/shell.h" -#include "base/command_line.h" -#include "base/run_loop.h" -#include "base/test/test_simple_task_runner.h" -#include "components/exo/buffer.h" -#include "components/exo/gamepad.h" -#include "components/exo/gamepad_delegate.h" -#include "components/exo/shell_surface.h" -#include "components/exo/surface.h" -#include "components/exo/test/exo_test_base.h" -#include "components/exo/test/exo_test_helper.h" -#include "device/gamepad/gamepad_test_helpers.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/focus_client.h" - -namespace exo { -namespace { - -class MockGamepadDelegate : public GamepadDelegate { - public: - MockGamepadDelegate() {} - - // Overridden from GamepadDelegate: - MOCK_METHOD1(OnGamepadDestroying, void(Gamepad*)); - MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*)); - MOCK_METHOD1(OnStateChange, void(bool)); - MOCK_METHOD2(OnAxis, void(int, double)); - MOCK_METHOD3(OnButton, void(int, bool, double)); - MOCK_METHOD0(OnFrame, void()); -}; - -class GamepadTest : public test::ExoTestBase { - public: - GamepadTest() {} - - std::unique_ptr<device::GamepadDataFetcher> MockDataFetcherFactory() { - blink::WebGamepads initial_data; - std::unique_ptr<device::MockGamepadDataFetcher> fetcher( - new device::MockGamepadDataFetcher(initial_data)); - mock_data_fetcher_ = fetcher.get(); - return std::move(fetcher); - } - - void InitializeGamepad(MockGamepadDelegate* delegate) { - polling_task_runner_ = new base::TestSimpleTaskRunner(); - gamepad_.reset(new Gamepad(delegate, polling_task_runner_.get(), - base::Bind(&GamepadTest::MockDataFetcherFactory, - base::Unretained(this)))); - // Run the polling task runner to have it create the data fetcher. - polling_task_runner_->RunPendingTasks(); - } - - void DestroyGamepad(MockGamepadDelegate* delegate) { - EXPECT_CALL(*delegate, OnGamepadDestroying(testing::_)).Times(1); - mock_data_fetcher_ = nullptr; - gamepad_.reset(); - // Process tasks until polling is shut down. - polling_task_runner_->RunPendingTasks(); - polling_task_runner_ = nullptr; - } - - void SetDataAndPostToDelegate(const blink::WebGamepads& new_data) { - ASSERT_TRUE(mock_data_fetcher_ != nullptr); - mock_data_fetcher_->SetTestData(new_data); - // Run one polling cycle, which will post a task to the origin task runner. - polling_task_runner_->RunPendingTasks(); - // Run origin task runner to invoke delegate. - base::RunLoop().RunUntilIdle(); - } - - protected: - std::unique_ptr<Gamepad> gamepad_; - - // Task runner to simulate the polling thread. - scoped_refptr<base::TestSimpleTaskRunner> polling_task_runner_; - - // Weak reference to the mock data fetcher provided by MockDataFetcherFactory. - // This instance is valid until both gamepad_ and polling_task_runner_ are - // shut down. - device::MockGamepadDataFetcher* mock_data_fetcher_; - - DISALLOW_COPY_AND_ASSIGN(GamepadTest); -}; - -TEST_F(GamepadTest, OnStateChange) { - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); - gfx::Size buffer_size(10, 10); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - surface->Attach(buffer.get()); - surface->Commit(); - - testing::StrictMock<MockGamepadDelegate> delegate; - EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) - .WillOnce(testing::Return(true)); - - InitializeGamepad(&delegate); - - // Gamepad connected. - EXPECT_CALL(delegate, OnStateChange(true)).Times(1); - blink::WebGamepads gamepad_connected; - gamepad_connected.items[0].connected = true; - gamepad_connected.items[0].timestamp = 1; - SetDataAndPostToDelegate(gamepad_connected); - - // Gamepad disconnected. - blink::WebGamepads all_disconnected; - EXPECT_CALL(delegate, OnStateChange(false)).Times(1); - SetDataAndPostToDelegate(all_disconnected); - - DestroyGamepad(&delegate); -} - -TEST_F(GamepadTest, OnAxis) { - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); - gfx::Size buffer_size(10, 10); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - surface->Attach(buffer.get()); - surface->Commit(); - - testing::StrictMock<MockGamepadDelegate> delegate; - EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) - .WillOnce(testing::Return(true)); - - InitializeGamepad(&delegate); - - blink::WebGamepads axis_moved; - axis_moved.items[0].connected = true; - axis_moved.items[0].timestamp = 1; - axis_moved.items[0].axesLength = 1; - axis_moved.items[0].axes[0] = 1.0; - - EXPECT_CALL(delegate, OnStateChange(true)).Times(1); - EXPECT_CALL(delegate, OnAxis(0, 1.0)).Times(1); - EXPECT_CALL(delegate, OnFrame()).Times(1); - SetDataAndPostToDelegate(axis_moved); - - DestroyGamepad(&delegate); -} - -TEST_F(GamepadTest, OnButton) { - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); - gfx::Size buffer_size(10, 10); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - surface->Attach(buffer.get()); - surface->Commit(); - - testing::StrictMock<MockGamepadDelegate> delegate; - EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) - .WillOnce(testing::Return(true)); - - InitializeGamepad(&delegate); - - blink::WebGamepads axis_moved; - axis_moved.items[0].connected = true; - axis_moved.items[0].timestamp = 1; - axis_moved.items[0].buttonsLength = 1; - axis_moved.items[0].buttons[0].pressed = true; - axis_moved.items[0].buttons[0].value = 1.0; - - EXPECT_CALL(delegate, OnStateChange(true)).Times(1); - EXPECT_CALL(delegate, OnButton(0, true, 1.0)).Times(1); - EXPECT_CALL(delegate, OnFrame()).Times(1); - SetDataAndPostToDelegate(axis_moved); - - DestroyGamepad(&delegate); -} - -TEST_F(GamepadTest, OnWindowFocused) { - // Create surface and move focus to it. - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); - gfx::Size buffer_size(10, 10); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - surface->Attach(buffer.get()); - surface->Commit(); - - testing::StrictMock<MockGamepadDelegate> delegate; - EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) - .WillOnce(testing::Return(true)); - - InitializeGamepad(&delegate); - - // In focus. Should be polling indefinitely, check a couple of time that the - // poll task is re-posted. - for (size_t i = 0; i < 5; ++i) { - polling_task_runner_->RunPendingTasks(); - ASSERT_TRUE(polling_task_runner_->HasPendingTask()); - } - - // Remove focus from window. - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); - focus_client->FocusWindow(nullptr); - - // Run EnablePolling and OnPoll task, no more polls should be scheduled. - // In the first round of RunPendingTasks we will execute - // EnablePollingOnPollingThread, which will cause the polling to stop being - // scheduled in the next round. - polling_task_runner_->RunPendingTasks(); - polling_task_runner_->RunPendingTasks(); - ASSERT_FALSE(polling_task_runner_->HasPendingTask()); - - DestroyGamepad(&delegate); -} - -} // namespace -} // namespace exo
diff --git a/components/exo/gamepad.cc b/components/exo/gaming_seat.cc similarity index 64% rename from components/exo/gamepad.cc rename to components/exo/gaming_seat.cc index 8d5e2311..67d9c25 100644 --- a/components/exo/gamepad.cc +++ b/components/exo/gaming_seat.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 "components/exo/gamepad.h" +#include "components/exo/gaming_seat.h" #include <cmath> @@ -12,6 +12,7 @@ #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "components/exo/gamepad_delegate.h" +#include "components/exo/gaming_seat_delegate.h" #include "components/exo/shell_surface.h" #include "components/exo/surface.h" #include "device/gamepad/gamepad_data_fetcher.h" @@ -38,18 +39,18 @@ } // namespace //////////////////////////////////////////////////////////////////////////////// -// Gamepad::ThreadSafeGamepadChangeFetcher +// GamingSeat::ThreadSafeGamepadChangeFetcher // Implements all methods and resources running on the polling thread. // This class is reference counted to allow it to shut down safely on the // polling thread even if the Gamepad has been destroyed on the origin thread. -class Gamepad::ThreadSafeGamepadChangeFetcher +class GamingSeat::ThreadSafeGamepadChangeFetcher : public device::GamepadPadStateProvider, public base::RefCountedThreadSafe< - Gamepad::ThreadSafeGamepadChangeFetcher> { + GamingSeat::ThreadSafeGamepadChangeFetcher> { public: using ProcessGamepadChangesCallback = - base::Callback<void(const blink::WebGamepad)>; + base::Callback<void(int index, const blink::WebGamepad)>; ThreadSafeGamepadChangeFetcher( const ProcessGamepadChangesCallback& post_gamepad_changes, @@ -123,30 +124,33 @@ fetcher_->GetGamepadData( false /* No hardware changed notification from the system */); - device::PadState& pad_state = pad_states_.get()[0]; + for (size_t i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { + device::PadState& pad_state = pad_states_.get()[i]; - // After querying the gamepad clear the state if it did not have it's active - // state updated but is still listed as being associated with a specific - // source. This indicates the gamepad is disconnected. - if (!pad_state.active_state && - pad_state.source != device::GAMEPAD_SOURCE_NONE) { - ClearPadState(pad_state); + // After querying the gamepad clear the state if it did not have it's + // active + // state updated but is still listed as being associated with a specific + // source. This indicates the gamepad is disconnected. + if (!pad_state.active_state && + pad_state.source != device::GAMEPAD_SOURCE_NONE) { + ClearPadState(pad_state); + } + + MapAndSanitizeGamepadData(&pad_state, &new_state.items[i], + false /* Don't sanitize gamepad data */); + + // If the gamepad is still actively reporting the next call to + // GetGamepadData will set the active state to active again. + if (pad_state.active_state) + pad_state.active_state = device::GAMEPAD_INACTIVE; + + if (new_state.items[i].connected != state_.items[i].connected || + new_state.items[i].timestamp > state_.items[i].timestamp) { + origin_task_runner_->PostTask( + FROM_HERE, + base::Bind(process_gamepad_changes_, i, new_state.items[i])); + } } - - MapAndSanitizeGamepadData(&pad_state, &new_state.items[0], - false /* Don't sanitize gamepad data */); - - // If the gamepad is still actively reporting the next call to - // GetGamepadData will set the active state to active again. - if (pad_state.active_state) - pad_state.active_state = device::GAMEPAD_INACTIVE; - - if (new_state.items[0].connected != state_.items[0].connected || - new_state.items[0].timestamp > state_.items[0].timestamp) { - origin_task_runner_->PostTask( - FROM_HERE, base::Bind(process_gamepad_changes_, new_state.items[0])); - } - state_ = new_state; SchedulePollOnPollingThread(); } @@ -182,20 +186,23 @@ }; //////////////////////////////////////////////////////////////////////////////// -// Gamepad, public: +// GamingSeat, public: -Gamepad::Gamepad(GamepadDelegate* delegate, - base::SingleThreadTaskRunner* polling_task_runner) - : Gamepad(delegate, - polling_task_runner, - base::Bind(CreateGamepadPlatformDataFetcher)) {} +GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate, + base::SingleThreadTaskRunner* polling_task_runner) + : GamingSeat(gaming_seat_delegate, + polling_task_runner, + base::Bind(CreateGamepadPlatformDataFetcher)) {} -Gamepad::Gamepad(GamepadDelegate* delegate, - base::SingleThreadTaskRunner* polling_task_runner, - CreateGamepadDataFetcherCallback create_fetcher_callback) - : delegate_(delegate), weak_factory_(this) { +GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate, + base::SingleThreadTaskRunner* polling_task_runner, + CreateGamepadDataFetcherCallback create_fetcher_callback) + : delegate_(gaming_seat_delegate), + gamepad_delegates_{nullptr}, + weak_ptr_factory_(this) { gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher( - base::Bind(&Gamepad::ProcessGamepadChanges, weak_factory_.GetWeakPtr()), + base::Bind(&GamingSeat::ProcessGamepadChanges, + weak_ptr_factory_.GetWeakPtr()), create_fetcher_callback, polling_task_runner); auto* helper = WMHelper::GetInstance(); @@ -203,20 +210,25 @@ OnWindowFocused(helper->GetFocusedWindow(), nullptr); } -Gamepad::~Gamepad() { +GamingSeat::~GamingSeat() { // Disable polling. Since ThreadSafeGamepadChangeFetcher are reference // counted, we can safely have it shut down after Gamepad has been destroyed. gamepad_change_fetcher_->EnablePolling(false); - delegate_->OnGamepadDestroying(this); + delegate_->OnGamingSeatDestroying(this); + for (size_t i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { + if (gamepad_delegates_[i]) { + gamepad_delegates_[i]->OnRemoved(); + } + } WMHelper::GetInstance()->RemoveFocusObserver(this); } //////////////////////////////////////////////////////////////////////////////// // aura::client::FocusChangeObserver overrides: -void Gamepad::OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) { +void GamingSeat::OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) { DCHECK(thread_checker_.CalledOnValidThread()); Surface* target = nullptr; if (gained_focus) { @@ -229,52 +241,68 @@ } bool focused = target && delegate_->CanAcceptGamepadEventsForSurface(target); + gamepad_change_fetcher_->EnablePolling(focused); } //////////////////////////////////////////////////////////////////////////////// -// Gamepad, private: +// GamingSeat, private: -void Gamepad::ProcessGamepadChanges(const blink::WebGamepad new_pad) { +void GamingSeat::ProcessGamepadChanges(int index, + const blink::WebGamepad new_pad) { DCHECK(thread_checker_.CalledOnValidThread()); bool send_frame = false; + blink::WebGamepad& pad_state = pad_state_.items[index]; // Update connection state. - if (new_pad.connected != pad_state_.connected) { - delegate_->OnStateChange(new_pad.connected); + GamepadDelegate* delegate = gamepad_delegates_[index]; + if (new_pad.connected != pad_state.connected) { + // New pad is disconnected. + if (!new_pad.connected) { + // If gamepad is disconnected now, it should be connected before, then + // gamepad_delegate should not be null. + DCHECK(delegate); + delegate->OnRemoved(); + gamepad_delegates_[index] = nullptr; + pad_state = new_pad; + return; + } else if (new_pad.connected) { + gamepad_delegates_[index] = delegate_->GamepadAdded(); + } } - if (!new_pad.connected || new_pad.timestamp <= pad_state_.timestamp) { - pad_state_ = new_pad; + if (!delegate || !new_pad.connected || + new_pad.timestamp <= pad_state.timestamp) { + pad_state = new_pad; return; } // Notify delegate of updated axes. for (size_t axis = 0; - axis < std::max(pad_state_.axesLength, new_pad.axesLength); ++axis) { + axis < std::max(pad_state.axesLength, new_pad.axesLength); ++axis) { if (!GamepadButtonValuesAreEqual(new_pad.axes[axis], - pad_state_.axes[axis])) { + pad_state.axes[axis])) { send_frame = true; - delegate_->OnAxis(axis, new_pad.axes[axis]); + delegate->OnAxis(axis, new_pad.axes[axis]); } } // Notify delegate of updated buttons. for (size_t button_id = 0; - button_id < std::max(pad_state_.buttonsLength, new_pad.buttonsLength); + button_id < std::max(pad_state.buttonsLength, new_pad.buttonsLength); ++button_id) { - auto button = pad_state_.buttons[button_id]; + auto button = pad_state.buttons[button_id]; auto new_button = new_pad.buttons[button_id]; if (button.pressed != new_button.pressed || !GamepadButtonValuesAreEqual(button.value, new_button.value)) { send_frame = true; - delegate_->OnButton(button_id, new_button.pressed, new_button.value); + delegate->OnButton(button_id, new_button.pressed, new_button.value); } } if (send_frame) - delegate_->OnFrame(); + delegate->OnFrame(); - pad_state_ = new_pad; + pad_state = new_pad; } } // namespace exo
diff --git a/components/exo/gaming_seat.h b/components/exo/gaming_seat.h new file mode 100644 index 0000000..cc7aa9a --- /dev/null +++ b/components/exo/gaming_seat.h
@@ -0,0 +1,78 @@ +// Copyright 2016 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_EXO_GAMING_SEAT_H_ +#define COMPONENTS_EXO_GAMING_SEAT_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/exo/wm_helper.h" +#include "device/gamepad/gamepad_data_fetcher.h" +#include "ui/aura/client/focus_change_observer.h" + +namespace exo { +class GamingSeatDelegate; +class GamepadDelegate; + +using CreateGamepadDataFetcherCallback = + base::Callback<std::unique_ptr<device::GamepadDataFetcher>()>; + +// This class represents one gaming seat, it uses a background thread +// for polling gamepad devices and notifies the corresponding GampadDelegate of +// any changes. +class GamingSeat : public WMHelper::FocusObserver { + public: + // This class will post tasks to invoke the delegate on the thread runner + // which is associated with the thread that is creating this instance. + GamingSeat(GamingSeatDelegate* gaming_seat_delegate, + base::SingleThreadTaskRunner* polling_task_runner); + + // Allows test cases to specify a CreateGamepadDataFetcherCallback that + // overrides the default GamepadPlatformDataFetcher. + GamingSeat(GamingSeatDelegate* gaming_seat_delegate, + base::SingleThreadTaskRunner* polling_task_runner, + CreateGamepadDataFetcherCallback create_fetcher_callback); + + ~GamingSeat() override; + + // Overridden WMHelper::FocusObserver: + void OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) override; + + private: + class ThreadSafeGamepadChangeFetcher; + + // Processes updates of gamepad data and passes changes on to delegate. + void ProcessGamepadChanges(int index, const blink::WebGamepad new_pad); + + // Private implementation of methods and resources that are used on the + // polling thread. + scoped_refptr<ThreadSafeGamepadChangeFetcher> gamepad_change_fetcher_; + + // The delegate that handles gamepad_added. + GamingSeatDelegate* const delegate_; + + // The delegate instances that all other events are dispatched to. + GamepadDelegate* gamepad_delegates_[blink::WebGamepads::itemsLengthCap]; + + // The current state of the gamepad represented by this instance. + blink::WebGamepads pad_state_; + + // ThreadChecker for the origin thread. + base::ThreadChecker thread_checker_; + + base::WeakPtrFactory<GamingSeat> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(GamingSeat); +}; + +} // namespace exo + +#endif // COMPONENTS_EXO_GAMING_SEAT_H_
diff --git a/components/exo/gaming_seat_delegate.h b/components/exo/gaming_seat_delegate.h new file mode 100644 index 0000000..671c7e1 --- /dev/null +++ b/components/exo/gaming_seat_delegate.h
@@ -0,0 +1,34 @@ +// Copyright 2016 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_EXO_GAMING_SEAT_DELEGATE_H_ +#define COMPONENTS_EXO_GAMING_SEAT_DELEGATE_H_ + +namespace exo { +class Surface; +class GamepadDelegate; +class GamingSeat; + +// It send gamepad_added event and generate the GamepadDelegate. +class GamingSeatDelegate { + public: + // Gives the delegate a chance to clean up when the GamingSeat instance is + // destroyed + virtual void OnGamingSeatDestroying(GamingSeat* gaming_seat) = 0; + + // This should return true if |surface| is a valid target for this gaming + // seat. E.g. the surface is owned by the same client as the gaming seat. + virtual bool CanAcceptGamepadEventsForSurface(Surface* surface) const = 0; + + // When a new gamepad is connected, gaming seat call this to get the + // gamepad delegate. + virtual GamepadDelegate* GamepadAdded() = 0; + + protected: + virtual ~GamingSeatDelegate() {} +}; + +} // namespace exo + +#endif // COMPONENTS_EXO_GAMING_SEAT_DELEGATE_H_
diff --git a/components/exo/gaming_seat_unittest.cc b/components/exo/gaming_seat_unittest.cc new file mode 100644 index 0000000..fb22d28 --- /dev/null +++ b/components/exo/gaming_seat_unittest.cc
@@ -0,0 +1,325 @@ +// 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/exo/gaming_seat.h" +#include "ash/shell.h" +#include "base/command_line.h" +#include "base/run_loop.h" +#include "base/test/test_simple_task_runner.h" +#include "components/exo/buffer.h" +#include "components/exo/gamepad_delegate.h" +#include "components/exo/gaming_seat_delegate.h" +#include "components/exo/shell_surface.h" +#include "components/exo/surface.h" +#include "components/exo/test/exo_test_base.h" +#include "components/exo/test/exo_test_helper.h" +#include "device/gamepad/gamepad_test_helpers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/client/focus_client.h" + +namespace exo { +namespace { + +class MockGamingSeatDelegate : public GamingSeatDelegate { + public: + MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*)); + MOCK_METHOD0(GamepadAdded, GamepadDelegate*()); + MOCK_METHOD0(Die, void()); + void OnGamingSeatDestroying(GamingSeat*) override { delete this; }; + ~MockGamingSeatDelegate() { Die(); }; +}; + +class MockGamepadDelegate : public GamepadDelegate { + public: + MockGamepadDelegate() {} + + // Overridden from GamepadDelegate: + MOCK_METHOD0(OnRemoved, void()); + MOCK_METHOD2(OnAxis, void(int, double)); + MOCK_METHOD3(OnButton, void(int, bool, double)); + MOCK_METHOD0(OnFrame, void()); +}; + +class GamingSeatTest : public test::ExoTestBase { + public: + GamingSeatTest() {} + + std::unique_ptr<device::GamepadDataFetcher> MockDataFetcherFactory() { + blink::WebGamepads initial_data; + std::unique_ptr<device::MockGamepadDataFetcher> fetcher( + new device::MockGamepadDataFetcher(initial_data)); + mock_data_fetcher_ = fetcher.get(); + return std::move(fetcher); + } + + void InitializeGamingSeat(MockGamingSeatDelegate* delegate) { + polling_task_runner_ = new base::TestSimpleTaskRunner(); + gaming_seat_.reset( + new GamingSeat(delegate, polling_task_runner_.get(), + base::Bind(&GamingSeatTest::MockDataFetcherFactory, + base::Unretained(this)))); + // Run the polling task runner to have it create the data fetcher. + polling_task_runner_->RunPendingTasks(); + } + + void DestroyGamingSeat(MockGamingSeatDelegate* delegate) { + EXPECT_CALL(*delegate, Die()).Times(1); + mock_data_fetcher_ = nullptr; + gaming_seat_.reset(); + // Process tasks until polling is shut down. + polling_task_runner_->RunPendingTasks(); + polling_task_runner_ = nullptr; + } + + void SetDataAndPostToDelegate(const blink::WebGamepads& new_data) { + ASSERT_TRUE(mock_data_fetcher_ != nullptr); + mock_data_fetcher_->SetTestData(new_data); + // Run one polling cycle, which will post a task to the origin task runner. + polling_task_runner_->RunPendingTasks(); + // Run origin task runner to invoke delegate. + base::RunLoop().RunUntilIdle(); + } + + protected: + std::unique_ptr<GamingSeat> gaming_seat_; + + // Task runner to simulate the polling thread. + scoped_refptr<base::TestSimpleTaskRunner> polling_task_runner_; + + // Weak reference to the mock data fetcher provided by MockDataFetcherFactory. + // This instance is valid until both gamepad_ and polling_task_runner_ are + // shut down. + device::MockGamepadDataFetcher* mock_data_fetcher_; + + DISALLOW_COPY_AND_ASSIGN(GamingSeatTest); +}; + +TEST_F(GamingSeatTest, ConnectionChange) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = + new testing::StrictMock<MockGamingSeatDelegate>(); + EXPECT_CALL(*gaming_seat_delegate, + CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamingSeat(gaming_seat_delegate); + testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; + testing::StrictMock<MockGamepadDelegate> gamepad_delegate1; + testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; + + { // Test sequence + testing::InSequence s; + // connect gamepad 0 + // connect gamepad 2 + // connect gamepad 1 + EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) + .WillOnce(testing::Return(&gamepad_delegate0)) + .WillOnce(testing::Return(&gamepad_delegate2)) + .WillOnce(testing::Return(&gamepad_delegate1)); + // disconnect gamepad 1 + EXPECT_CALL(gamepad_delegate1, OnRemoved()).Times(1); + // disconnect other gamepads + EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); + EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); + } + // Gamepad connected. + blink::WebGamepads gamepad_connected; + gamepad_connected.items[0].connected = true; + gamepad_connected.items[0].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + gamepad_connected.items[2].connected = true; + gamepad_connected.items[2].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + gamepad_connected.items[1].connected = true; + gamepad_connected.items[1].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + // Gamepad 1 is dis connected + gamepad_connected.items[1].connected = false; + gamepad_connected.items[1].timestamp = 2; + + SetDataAndPostToDelegate(gamepad_connected); + + // Gamepad disconnected. + blink::WebGamepads all_disconnected; + SetDataAndPostToDelegate(all_disconnected); + + DestroyGamingSeat(gaming_seat_delegate); +} + +TEST_F(GamingSeatTest, OnAxis) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = + new testing::StrictMock<MockGamingSeatDelegate>(); + EXPECT_CALL(*gaming_seat_delegate, + CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamingSeat(gaming_seat_delegate); + testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; + testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; + + // connect gamepad 0 and 2 + EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) + .WillOnce(testing::Return(&gamepad_delegate0)) + .WillOnce(testing::Return(&gamepad_delegate2)); + + blink::WebGamepads gamepad_connected; + gamepad_connected.items[0].connected = true; + gamepad_connected.items[0].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + gamepad_connected.items[2].connected = true; + gamepad_connected.items[2].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + // send axis event to 2 and then 0 + blink::WebGamepads axis_moved; + axis_moved.items[0].connected = true; + axis_moved.items[0].timestamp = 1; + axis_moved.items[2].connected = true; + axis_moved.items[2].timestamp = 2; + axis_moved.items[2].axesLength = 1; + axis_moved.items[2].axes[0] = 1.0; + + EXPECT_CALL(gamepad_delegate2, OnAxis(0, 1.0)).Times(1); + EXPECT_CALL(gamepad_delegate2, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + axis_moved.items[0].timestamp = 2; + axis_moved.items[0].axesLength = 1; + axis_moved.items[0].axes[0] = 2.0; + + EXPECT_CALL(gamepad_delegate0, OnAxis(0, 2.0)).Times(1); + EXPECT_CALL(gamepad_delegate0, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); + EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); + DestroyGamingSeat(gaming_seat_delegate); +} + +TEST_F(GamingSeatTest, OnButton) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = + new testing::StrictMock<MockGamingSeatDelegate>(); + EXPECT_CALL(*gaming_seat_delegate, + CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamingSeat(gaming_seat_delegate); + testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; + testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; + + // connect gamepad 0 and 2 + EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) + .WillOnce(testing::Return(&gamepad_delegate0)) + .WillOnce(testing::Return(&gamepad_delegate2)); + + blink::WebGamepads gamepad_connected; + gamepad_connected.items[0].connected = true; + gamepad_connected.items[0].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + gamepad_connected.items[2].connected = true; + gamepad_connected.items[2].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + // send axis event to 2 and then 0 + blink::WebGamepads axis_moved; + axis_moved.items[0].connected = true; + axis_moved.items[0].timestamp = 1; + axis_moved.items[2].connected = true; + axis_moved.items[2].timestamp = 2; + + axis_moved.items[2].buttonsLength = 1; + axis_moved.items[2].buttons[0].pressed = true; + axis_moved.items[2].buttons[0].value = 1.0; + + EXPECT_CALL(gamepad_delegate2, OnButton(0, true, 1.0)).Times(1); + EXPECT_CALL(gamepad_delegate2, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + axis_moved.items[0].timestamp = 2; + axis_moved.items[0].buttonsLength = 1; + axis_moved.items[0].buttons[0].pressed = true; + axis_moved.items[0].buttons[0].value = 2.0; + + EXPECT_CALL(gamepad_delegate0, OnButton(0, true, 2.0)).Times(1); + EXPECT_CALL(gamepad_delegate0, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); + EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); + + DestroyGamingSeat(gaming_seat_delegate); +} + +TEST_F(GamingSeatTest, OnWindowFocused) { + // Create surface and move focus to it. + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = + new testing::StrictMock<MockGamingSeatDelegate>(); + EXPECT_CALL(*gaming_seat_delegate, + CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamingSeat(gaming_seat_delegate); + + // In focus. Should be polling indefinitely, check a couple of time that the + // poll task is re-posted. + for (size_t i = 0; i < 5; ++i) { + polling_task_runner_->RunPendingTasks(); + ASSERT_TRUE(polling_task_runner_->HasPendingTask()); + } + + // Remove focus from window. + aura::client::FocusClient* focus_client = + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); + focus_client->FocusWindow(nullptr); + + // Run EnablePolling and OnPoll task, no more polls should be scheduled. + // In the first round of RunPendingTasks we will execute + // EnablePollingOnPollingThread, which will cause the polling to stop being + // scheduled in the next round. + polling_task_runner_->RunPendingTasks(); + polling_task_runner_->RunPendingTasks(); + ASSERT_FALSE(polling_task_runner_->HasPendingTask()); + + DestroyGamingSeat(gaming_seat_delegate); +} + +} // namespace +} // namespace exo
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 4386237..b7a37dc 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -6,6 +6,7 @@ #include <alpha-compositing-unstable-v1-server-protocol.h> #include <gaming-input-unstable-v1-server-protocol.h> +#include <gaming-input-unstable-v2-server-protocol.h> #include <grp.h> #include <keyboard-configuration-unstable-v1-server-protocol.h> #include <linux/input.h> @@ -44,8 +45,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "components/exo/buffer.h" #include "components/exo/display.h" -#include "components/exo/gamepad.h" #include "components/exo/gamepad_delegate.h" +#include "components/exo/gaming_seat.h" +#include "components/exo/gaming_seat_delegate.h" #include "components/exo/keyboard.h" #include "components/exo/keyboard_delegate.h" #include "components/exo/keyboard_device_configuration_delegate.h" @@ -3356,42 +3358,65 @@ explicit WaylandGamepadDelegate(wl_resource* gamepad_resource) : gamepad_resource_(gamepad_resource) {} - // Overridden from GamepadDelegate: - void OnGamepadDestroying(Gamepad* gamepad) override { delete this; } - bool CanAcceptGamepadEventsForSurface(Surface* surface) const override { - wl_resource* surface_resource = GetSurfaceResource(surface); - return surface_resource && - wl_resource_get_client(surface_resource) == client(); + // If gamepad_resource_ is destroyed first, ResetGamepadResource will + // be called to remove the resource from delegate, and delegate won't + // do anything after that. If delegate is destructed first, it will + // set the data to null in the gamepad_resource_, then the resource + // destroy won't reset the delegate (cause it's gone). + static void ResetGamepadResource(wl_resource* resource) { + WaylandGamepadDelegate* delegate = + GetUserDataAs<WaylandGamepadDelegate>(resource); + if (delegate) { + delegate->gamepad_resource_ = nullptr; + } } - void OnStateChange(bool connected) override { - uint32_t status = connected ? ZCR_GAMEPAD_V1_GAMEPAD_STATE_ON - : ZCR_GAMEPAD_V1_GAMEPAD_STATE_OFF; - zcr_gamepad_v1_send_state_change(gamepad_resource_, status); + + // Override from GamepadDelegate: + void OnRemoved() override { + if (!gamepad_resource_) { + return; + } + zcr_gamepad_v2_send_removed(gamepad_resource_); wl_client_flush(client()); + // Reset the user data in gamepad_resource. + wl_resource_set_user_data(gamepad_resource_, nullptr); + delete this; } void OnAxis(int axis, double value) override { - zcr_gamepad_v1_send_axis(gamepad_resource_, NowInMilliseconds(), axis, + if (!gamepad_resource_) { + return; + } + zcr_gamepad_v2_send_axis(gamepad_resource_, NowInMilliseconds(), axis, wl_fixed_from_double(value)); } void OnButton(int button, bool pressed, double value) override { - uint32_t state = pressed ? ZCR_GAMEPAD_V1_BUTTON_STATE_PRESSED - : ZCR_GAMEPAD_V1_BUTTON_STATE_RELEASED; - zcr_gamepad_v1_send_button(gamepad_resource_, NowInMilliseconds(), button, + if (!gamepad_resource_) { + return; + } + uint32_t state = pressed ? ZCR_GAMEPAD_V2_BUTTON_STATE_PRESSED + : ZCR_GAMEPAD_V2_BUTTON_STATE_RELEASED; + zcr_gamepad_v2_send_button(gamepad_resource_, NowInMilliseconds(), button, state, wl_fixed_from_double(value)); } void OnFrame() override { - zcr_gamepad_v1_send_frame(gamepad_resource_, NowInMilliseconds()); + if (!gamepad_resource_) { + return; + } + zcr_gamepad_v2_send_frame(gamepad_resource_, NowInMilliseconds()); wl_client_flush(client()); } private: + // The object should be deleted by OnRemoved(). + ~WaylandGamepadDelegate() override {} + // The client who own this gamepad instance. wl_client* client() const { return wl_resource_get_client(gamepad_resource_); } // The gamepad resource associated with the gamepad. - wl_resource* const gamepad_resource_; + wl_resource* gamepad_resource_; DISALLOW_COPY_AND_ASSIGN(WaylandGamepadDelegate); }; @@ -3400,33 +3425,85 @@ wl_resource_destroy(resource); } -const struct zcr_gamepad_v1_interface gamepad_implementation = { +const struct zcr_gamepad_v2_interface gamepad_implementation = { gamepad_destroy}; -void gaming_input_get_gamepad(wl_client* client, - wl_resource* resource, - uint32_t id, - wl_resource* seat) { - wl_resource* gamepad_resource = wl_resource_create( - client, &zcr_gamepad_v1_interface, wl_resource_get_version(resource), id); +// GamingSeat delegate that provide gamepad added. +class WaylandGamingSeatDelegate : public GamingSeatDelegate { + public: + explicit WaylandGamingSeatDelegate(wl_resource* gaming_seat_resource) + : gaming_seat_resource_{gaming_seat_resource} {} + + // Override from GamingSeatDelegate: + void OnGamingSeatDestroying(GamingSeat*) override { delete this; } + bool CanAcceptGamepadEventsForSurface(Surface* surface) const override { + wl_resource* surface_resource = GetSurfaceResource(surface); + return surface_resource && + wl_resource_get_client(surface_resource) == + wl_resource_get_client(gaming_seat_resource_); + } + GamepadDelegate* GamepadAdded() override { + wl_resource* gamepad_resource = + wl_resource_create(wl_resource_get_client(gaming_seat_resource_), + &zcr_gamepad_v2_interface, + wl_resource_get_version(gaming_seat_resource_), 0); + + GamepadDelegate* gamepad_delegate = + new WaylandGamepadDelegate(gamepad_resource); + + wl_resource_set_implementation( + gamepad_resource, &gamepad_implementation, gamepad_delegate, + &WaylandGamepadDelegate::ResetGamepadResource); + + zcr_gaming_seat_v2_send_gamepad_added(gaming_seat_resource_, + gamepad_resource); + + return gamepad_delegate; + } + + private: + // The gaming seat resource associated with the gaming seat. + wl_resource* const gaming_seat_resource_; + + DISALLOW_COPY_AND_ASSIGN(WaylandGamingSeatDelegate); +}; + +void gaming_seat_destroy(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zcr_gaming_seat_v2_interface gaming_seat_implementation = { + gaming_seat_destroy}; + +void gaming_input_get_gaming_seat(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* seat) { + wl_resource* gaming_seat_resource = + wl_resource_create(client, &zcr_gaming_seat_v2_interface, + wl_resource_get_version(resource), id); base::Thread* gaming_input_thread = GetUserDataAs<base::Thread>(resource); - SetImplementation( - gamepad_resource, &gamepad_implementation, - base::MakeUnique<Gamepad>(new WaylandGamepadDelegate(gamepad_resource), - gaming_input_thread->task_runner().get())); + SetImplementation(gaming_seat_resource, &gaming_seat_implementation, + base::MakeUnique<GamingSeat>( + new WaylandGamingSeatDelegate(gaming_seat_resource), + gaming_input_thread->task_runner().get())); } -const struct zcr_gaming_input_v1_interface gaming_input_implementation = { - gaming_input_get_gamepad}; +void gaming_input_destroy(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zcr_gaming_input_v2_interface gaming_input_implementation = { + gaming_input_get_gaming_seat, gaming_input_destroy}; void bind_gaming_input(wl_client* client, void* data, uint32_t version, uint32_t id) { wl_resource* resource = - wl_resource_create(client, &zcr_gaming_input_v1_interface, version, id); + wl_resource_create(client, &zcr_gaming_input_v2_interface, version, id); std::unique_ptr<base::Thread> gaming_input_thread( new base::Thread("Exo gaming input polling thread.")); @@ -3438,6 +3515,46 @@ } //////////////////////////////////////////////////////////////////////////////// +// dummy interface for gaming_input_v1: +/* Following is a dummy interface for gaming_input_v1. + * It makes sure the "old" android with v1 interface won't break. However, "old" + * android will not receive any gamepad input. This interface implementation + * should be removed once android is updated. + */ +// TODO(jkwang): Remove the following interface function once android updated. +void gamepad_v1_destroy_DEPRECATED(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zcr_gamepad_v1_interface gamepad_v1_implementation = { + gamepad_v1_destroy_DEPRECATED}; + +void gaming_input_v1_get_gamepad_DEPRECATED(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* seat) { + wl_resource* gamepad_resource = wl_resource_create( + client, &zcr_gamepad_v1_interface, wl_resource_get_version(resource), id); + + wl_resource_set_implementation(gamepad_resource, &gamepad_v1_implementation, + NULL, NULL); +} + +const struct zcr_gaming_input_v1_interface gaming_input_v1_implementation = { + gaming_input_v1_get_gamepad_DEPRECATED}; + +void bind_gaming_input_v1_DEPRECATED(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* resource = + wl_resource_create(client, &zcr_gaming_input_v1_interface, version, id); + + wl_resource_set_implementation(resource, &gaming_input_v1_implementation, + NULL, NULL); +} + +//////////////////////////////////////////////////////////////////////////////// // touch_stylus interface: class WaylandTouchStylusDelegate : public TouchStylusDelegate { @@ -3693,6 +3810,8 @@ wl_global_create(wl_display_.get(), &zcr_remote_shell_v1_interface, remote_shell_version, display_, bind_remote_shell); wl_global_create(wl_display_.get(), &zcr_gaming_input_v1_interface, 1, + display_, bind_gaming_input_v1_DEPRECATED); + wl_global_create(wl_display_.get(), &zcr_gaming_input_v2_interface, 1, display_, bind_gaming_input); wl_global_create(wl_display_.get(), &zcr_stylus_v1_interface, 2, display_, bind_stylus_v1_DEPRECATED);
diff --git a/components/offline_pages/core/background/cleanup_task_unittest.cc b/components/offline_pages/core/background/cleanup_task_unittest.cc index acfb33b..84529066 100644 --- a/components/offline_pages/core/background/cleanup_task_unittest.cc +++ b/components/offline_pages/core/background/cleanup_task_unittest.cc
@@ -58,6 +58,9 @@ total_expired_requests_++; } + void NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override {} + const SavePageRequest& last_expired_request() { return last_expired_request_; }
diff --git a/components/offline_pages/core/background/offliner.h b/components/offline_pages/core/background/offliner.h index c50df35..2f15128 100644 --- a/components/offline_pages/core/background/offliner.h +++ b/components/offline_pages/core/background/offliner.h
@@ -59,6 +59,9 @@ STATUS_COUNT }; + // Reports the load progress of a request. + typedef base::Callback<void(const SavePageRequest&, int64_t received_bytes)> + ProgressCallback; // Reports the completion status of a request. // TODO(dougarnett): consider passing back a request id instead of request. typedef base::Callback<void(const SavePageRequest&, RequestStatus)> @@ -71,10 +74,13 @@ virtual ~Offliner() {} // Processes |request| to load and save an offline page. - // Returns whether the request was accepted or not. |callback| is guaranteed - // to be called if the request was accepted and |Cancel()| is not called. + // Returns whether the request was accepted or not. |completion_callback| is + // guaranteed to be called if the request was accepted and |Cancel()| is not + // called on it. |progress_callback| is invoked periodically to report the + // number of bytes received from the network (for UI purposes). virtual bool LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) = 0; + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) = 0; // Clears the currently processing request, if any, and skips running its // CompletionCallback.
diff --git a/components/offline_pages/core/background/offliner_stub.cc b/components/offline_pages/core/background/offliner_stub.cc index c007ae0a..04fe6ea 100644 --- a/components/offline_pages/core/background/offliner_stub.cc +++ b/components/offline_pages/core/background/offliner_stub.cc
@@ -19,17 +19,22 @@ OfflinerStub::~OfflinerStub() {} bool OfflinerStub::LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) { + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) { if (disable_loading_) return false; - callback_ = callback; + completion_callback_ = completion_callback; + progress_callback_ = progress_callback; // Post the callback on the run loop. if (enable_callback_) { + const int64_t arbitrary_size = 153LL; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(callback, request, Offliner::RequestStatus::SAVED)); + FROM_HERE, base::Bind(progress_callback_, request, arbitrary_size)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(completion_callback_, request, + Offliner::RequestStatus::SAVED)); } return true; } @@ -42,8 +47,8 @@ bool OfflinerStub::HandleTimeout(const SavePageRequest& request) { if (snapshot_on_last_retry_) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(callback_, request, Offliner::RequestStatus::SAVED)); + FROM_HERE, base::Bind(completion_callback_, request, + Offliner::RequestStatus::SAVED)); return true; } return false;
diff --git a/components/offline_pages/core/background/offliner_stub.h b/components/offline_pages/core/background/offliner_stub.h index 16abb8f7..2d7f72a 100644 --- a/components/offline_pages/core/background/offliner_stub.h +++ b/components/offline_pages/core/background/offliner_stub.h
@@ -17,7 +17,8 @@ ~OfflinerStub() override; bool LoadAndSave(const SavePageRequest& request, - const CompletionCallback& callback) override; + const CompletionCallback& completion_callback, + const ProgressCallback& progress_callback) override; void Cancel(const CancelCallback& callback) override; @@ -34,7 +35,8 @@ void enable_snapshot_on_last_retry() { snapshot_on_last_retry_ = true; } private: - CompletionCallback callback_; + CompletionCallback completion_callback_; + ProgressCallback progress_callback_; bool disable_loading_; bool enable_callback_; bool cancel_called_;
diff --git a/components/offline_pages/core/background/pick_request_task_unittest.cc b/components/offline_pages/core/background/pick_request_task_unittest.cc index f1e249b..1b3ca46 100644 --- a/components/offline_pages/core/background/pick_request_task_unittest.cc +++ b/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -67,6 +67,9 @@ total_expired_requests_++; } + void NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override {} + const SavePageRequest& last_expired_request() { return last_expired_request_; }
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc index f729bc51..cc80a342 100644 --- a/components/offline_pages/core/background/request_coordinator.cc +++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -883,6 +883,8 @@ if (offliner_->LoadAndSave( update_result->updated_items.at(0), base::Bind(&RequestCoordinator::OfflinerDoneCallback, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&RequestCoordinator::OfflinerProgressCallback, weak_ptr_factory_.GetWeakPtr()))) { base::TimeDelta timeout; if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) { @@ -934,6 +936,14 @@ scheduler_callback_.Run(true); } +void RequestCoordinator::OfflinerProgressCallback( + const SavePageRequest& request, + int64_t received_bytes) { + DVLOG(2) << "offliner progress, received bytes: " << received_bytes; + DCHECK(received_bytes >= 0); + NotifyNetworkProgress(request, received_bytes); +} + void RequestCoordinator::UpdateRequestForCompletedAttempt( const SavePageRequest& request, Offliner::RequestStatus status) { @@ -1066,6 +1076,12 @@ observer.OnChanged(request); } +void RequestCoordinator::NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) { + for (Observer& observer : observers_) + observer.OnNetworkProgress(request, received_bytes); +} + ClientPolicyController* RequestCoordinator::GetPolicyController() { return policy_controller_.get(); }
diff --git a/components/offline_pages/core/background/request_coordinator.h b/components/offline_pages/core/background/request_coordinator.h index 770cae3..d4b91009 100644 --- a/components/offline_pages/core/background/request_coordinator.h +++ b/components/offline_pages/core/background/request_coordinator.h
@@ -53,6 +53,8 @@ const SavePageRequest& request, RequestNotifier::BackgroundSavePageResult status) = 0; virtual void OnChanged(const SavePageRequest& request) = 0; + virtual void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) = 0; }; enum class RequestAvailability { @@ -184,6 +186,8 @@ const SavePageRequest& request, RequestNotifier::BackgroundSavePageResult status) override; void NotifyChanged(const SavePageRequest& request) override; + void NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override; // Returns the request queue used for requests. Coordinator keeps ownership. RequestQueue* queue() { return queue_.get(); } @@ -346,6 +350,11 @@ void OfflinerDoneCallback(const SavePageRequest& request, Offliner::RequestStatus status); + // Called by the offliner periodically to report the accumulated count of + // bytes received from the network. + void OfflinerProgressCallback(const SavePageRequest& request, + int64_t received_bytes); + // Records a completed attempt for the request and update it in the queue // (possibly removing it). void UpdateRequestForCompletedAttempt(const SavePageRequest& request,
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc index 753dd883..0850bef 100644 --- a/components/offline_pages/core/background/request_coordinator_unittest.cc +++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -60,6 +60,8 @@ : added_called_(false), completed_called_(false), changed_called_(false), + network_progress_called_(false), + network_progress_bytes_(0), last_status_(RequestCoordinator::BackgroundSavePageResult::SUCCESS), state_(SavePageRequest::RequestState::OFFLINING) {} @@ -67,6 +69,8 @@ added_called_ = false; completed_called_ = false; changed_called_ = false; + network_progress_called_ = false; + network_progress_bytes_ = 0; state_ = SavePageRequest::RequestState::OFFLINING; last_status_ = RequestCoordinator::BackgroundSavePageResult::SUCCESS; } @@ -87,9 +91,17 @@ state_ = request.request_state(); } + void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override { + network_progress_called_ = true; + network_progress_bytes_ = received_bytes; + } + bool added_called() { return added_called_; } bool completed_called() { return completed_called_; } bool changed_called() { return changed_called_; } + bool network_progress_called() { return network_progress_called_; } + int64_t network_progress_bytes() { return network_progress_bytes_; } RequestCoordinator::BackgroundSavePageResult last_status() { return last_status_; } @@ -99,6 +111,8 @@ bool added_called_; bool completed_called_; bool changed_called_; + bool network_progress_called_; + int64_t network_progress_bytes_; RequestCoordinator::BackgroundSavePageResult last_status_; SavePageRequest::RequestState state_; }; @@ -455,6 +469,13 @@ } } +TEST_F(RequestCoordinatorTest, NetworkProgressCallback) { + EXPECT_NE(0, SavePageLater()); + PumpLoop(); + EXPECT_TRUE(observer().network_progress_called()); + EXPECT_GT(observer().network_progress_bytes(), 0LL); +} + TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithRequestInProgress) { // Start processing for this request. EXPECT_NE(0, SavePageLater());
diff --git a/components/offline_pages/core/background/request_notifier.h b/components/offline_pages/core/background/request_notifier.h index ef3c62f..95fbb09 100644 --- a/components/offline_pages/core/background/request_notifier.h +++ b/components/offline_pages/core/background/request_notifier.h
@@ -38,6 +38,11 @@ // Notifies observers that |request| has been changed. virtual void NotifyChanged(const SavePageRequest& request) = 0; + + // Notifies observers of progress on |request|, which received + // |received_bytes| at that point. + virtual void NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) = 0; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/background/request_queue_unittest.cc b/components/offline_pages/core/background/request_queue_unittest.cc index 3f5dc4556..ed9054b 100644 --- a/components/offline_pages/core/background/request_queue_unittest.cc +++ b/components/offline_pages/core/background/request_queue_unittest.cc
@@ -63,6 +63,11 @@ total_expired_requests_++; } + void NotifyNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override { + // This has nothing to do with the queue (progress is ephemeral) - no test. + } + const SavePageRequest& last_expired_request() { return last_expired_request_; }
diff --git a/components/offline_pages/core/downloads/download_notifying_observer.cc b/components/offline_pages/core/downloads/download_notifying_observer.cc index cca7406a..37836088 100644 --- a/components/offline_pages/core/downloads/download_notifying_observer.cc +++ b/components/offline_pages/core/downloads/download_notifying_observer.cc
@@ -64,6 +64,14 @@ NotifyRequestStateChange(request); } +void DownloadNotifyingObserver::OnNetworkProgress( + const SavePageRequest& request, + int64_t received_bytes) { + DownloadUIItem item(request); + item.download_progress_bytes = received_bytes; + notifier_->NotifyDownloadProgress(item); +} + void DownloadNotifyingObserver::OnCompleted( const SavePageRequest& request, RequestCoordinator::BackgroundSavePageResult status) {
diff --git a/components/offline_pages/core/downloads/download_notifying_observer.h b/components/offline_pages/core/downloads/download_notifying_observer.h index 6980102..cf86042 100644 --- a/components/offline_pages/core/downloads/download_notifying_observer.h +++ b/components/offline_pages/core/downloads/download_notifying_observer.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/downloads/download_ui_item.h" namespace offline_pages { @@ -38,6 +39,8 @@ void OnCompleted( const SavePageRequest& request, RequestCoordinator::BackgroundSavePageResult status) override; + void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override; private: friend class DownloadNotifyingObserverTest;
diff --git a/components/offline_pages/core/downloads/download_ui_adapter.cc b/components/offline_pages/core/downloads/download_ui_adapter.cc index 8543314..35910a0f 100644 --- a/components/offline_pages/core/downloads/download_ui_adapter.cc +++ b/components/offline_pages/core/downloads/download_ui_adapter.cc
@@ -164,6 +164,22 @@ observer.ItemUpdated(download_ui_item); } +void DownloadUIAdapter::OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) { + for (auto& item : items_) { + if (item.second->is_request && + item.second->offline_id == request.request_id()) { + if (received_bytes == item.second->ui_item->download_progress_bytes) + return; + + item.second->ui_item->download_progress_bytes = received_bytes; + for (Observer& observer : observers_) + observer.ItemUpdated(*(item.second->ui_item)); + return; + } + } +} + void DownloadUIAdapter::TemporaryHiddenStatusChanged( const ClientId& client_id) { bool hidden = delegate_->IsTemporarilyHiddenInUI(client_id); @@ -226,19 +242,6 @@ return 0; } -void DownloadUIAdapter::UpdateProgress(int64_t offline_id, int64_t bytes) { - for (auto& item : items_) { - if (item.second->is_request && item.second->offline_id == offline_id) { - if (bytes == item.second->ui_item->download_progress_bytes) - return; - - item.second->ui_item->download_progress_bytes = bytes; - for (Observer& observer : observers_) - observer.ItemUpdated(*(item.second->ui_item)); - } - } -} - // Note that several LoadCache calls may be issued before the async GetAllPages // comes back. void DownloadUIAdapter::LoadCache() {
diff --git a/components/offline_pages/core/downloads/download_ui_adapter.h b/components/offline_pages/core/downloads/download_ui_adapter.h index 4fef8e1b..2744f0b 100644 --- a/components/offline_pages/core/downloads/download_ui_adapter.h +++ b/components/offline_pages/core/downloads/download_ui_adapter.h
@@ -103,7 +103,6 @@ // via Observer or directly by the user (as in 'open'). void DeleteItem(const std::string& guid); int64_t GetOfflineIdByGuid(const std::string& guid) const; - void UpdateProgress(int64_t offline_id, int64_t bytes); // OfflinePageModel::Observer void OfflinePageModelLoaded(OfflinePageModel* model) override; @@ -117,6 +116,8 @@ void OnCompleted(const SavePageRequest& request, RequestNotifier::BackgroundSavePageResult status) override; void OnChanged(const SavePageRequest& request) override; + void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override; // For the DownloadUIAdapter::Delegate, to report the temporary hidden status // change.
diff --git a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc index 181bb3d..a52a10e 100644 --- a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc +++ b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
@@ -173,6 +173,7 @@ bool items_loaded; std::vector<std::string> added_guids, updated_guids, deleted_guids; + int64_t download_progress_bytes; std::unique_ptr<MockOfflinePageModel> model; DownloadUIAdapterDelegate* adapter_delegate; std::unique_ptr<DownloadUIAdapter> adapter; @@ -220,6 +221,7 @@ void DownloadUIAdapterTest::ItemUpdated(const DownloadUIItem& item) { updated_guids.push_back(item.guid); + download_progress_bytes += item.download_progress_bytes; } void DownloadUIAdapterTest::ItemDeleted(const std::string& guid) { @@ -462,16 +464,14 @@ AddRequest(GURL(kTestUrl), kTestClientId1); PumpLoop(); - int64_t offline_id = adapter->GetOfflineIdByGuid(kTestGuid1); const DownloadUIItem* item = adapter->GetItem(kTestGuid1); ASSERT_NE(nullptr, item); - EXPECT_EQ(item->download_progress_bytes, 0); - updated_guids.clear(); - - adapter->UpdateProgress(offline_id, 15); + EXPECT_GT(item->download_progress_bytes, 0LL); + // Updated 2 times - with progress and to 'completed'. + EXPECT_EQ(2UL, updated_guids.size()); EXPECT_EQ(kTestGuid1, updated_guids[0]); - EXPECT_EQ(item->download_progress_bytes, 15); + EXPECT_EQ(kTestGuid1, updated_guids[1]); } } // namespace offline_pages
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn index ff7c7899..3e00ac2 100644 --- a/components/policy/BUILD.gn +++ b/components/policy/BUILD.gn
@@ -50,6 +50,9 @@ # for policies of the same type, so that less classes have to be generated # and compiled. cloud_policy_proto_path = "$target_gen_dir/proto/cloud_policy.proto" + +# This file is used by tools/traffic_annotation/traffic_annotation.proto as it +# needs a version without LITE_RUNTIME optimization. cloud_policy_full_runtime_proto_path = "$target_gen_dir/proto/cloud_policy_full_runtime.proto" @@ -57,6 +60,11 @@ # policy. It is also the format currently used by the server. chrome_settings_proto_path = "$target_gen_dir/proto/chrome_settings.proto" +# This file is used by tools/traffic_annotation/traffic_annotation.proto as it +# needs a version without LITE_RUNTIME optimization. +chrome_settings_full_runtime_proto_path = + "$target_gen_dir/proto/chrome_settings_full_runtime.proto" + constants_header_path = "$target_gen_dir/policy_constants.h" constants_source_path = "$target_gen_dir/policy_constants.cc" protobuf_decoder_path = "$target_gen_dir/cloud_policy_generated.cc" @@ -113,7 +121,7 @@ ] } -action("cloud_policy_full_runtime_code_generate") { +action("full_runtime_code_generate") { script = "tools/generate_policy_source.py" chrome_version_abspath = "//chrome/VERSION" chrome_version_path = rebase_path(chrome_version_abspath, root_build_dir) @@ -130,11 +138,14 @@ ] outputs = [ cloud_policy_full_runtime_proto_path, + chrome_settings_full_runtime_proto_path, ] args = [ "--cloud-policy-full-runtime-protobuf=" + rebase_path(cloud_policy_full_runtime_proto_path, root_build_dir), + "--chrome-settings-full-runtime-protobuf=" + + rebase_path(chrome_settings_full_runtime_proto_path, root_build_dir), chrome_version_path, target_os, chromeos_flag,
diff --git a/components/policy/core/common/remote_commands/remote_command_job.cc b/components/policy/core/common/remote_commands/remote_command_job.cc index c32381ce..bf43a59 100644 --- a/components/policy/core/common/remote_commands/remote_command_job.cc +++ b/components/policy/core/common/remote_commands/remote_command_job.cc
@@ -54,8 +54,11 @@ issued_time_ = now; } - if (!ParseCommandPayload(command.payload())) + if (!ParseCommandPayload(command.payload())) { + SYSLOG(ERROR) << "Unable to parse command payload for type " + << command.type() << ": " << command.payload(); return false; + } switch (command.type()) { case em::RemoteCommand_Type_COMMAND_ECHO_TEST: { @@ -72,6 +75,11 @@ << " initialized."; break; } + case em::RemoteCommand_Type_DEVICE_SET_VOLUME: { + SYSLOG(INFO) << "Remote set volume command " << unique_id_ + << " initialized."; + break; + } } status_ = NOT_STARTED; return true;
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index d35f3268..845a752 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -1055,6 +1055,9 @@ // Take a screenshot. DEVICE_SCREENSHOT = 1; + + // Set device volume. + DEVICE_SET_VOLUME = 2; } // The command type.
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py index 88cf22a..ffde6a8d 100755 --- a/components/policy/tools/generate_policy_source.py +++ b/components/policy/tools/generate_policy_source.py
@@ -190,6 +190,10 @@ dest='chrome_settings_proto_path', help='generate chrome settings protobuf file', metavar='FILE') + parser.add_option('--csfrp', '--chrome-settings-full-runtime-protobuf', + dest='chrome_settings_full_runtime_proto_path', + help='generate chrome settings full runtime protobuf', + metavar='FILE') parser.add_option('--cpd', '--cloud-policy-decoder', dest='cloud_policy_decoder_path', help='generate C++ code decoding the cloud policy protobuf', @@ -245,6 +249,9 @@ _WriteCloudPolicyFullRuntimeProtobuf) if opts.chrome_settings_proto_path: GenerateFile(opts.chrome_settings_proto_path, _WriteChromeSettingsProtobuf) + if opts.chrome_settings_full_runtime_proto_path: + GenerateFile(opts.chrome_settings_full_runtime_proto_path, + _WriteChromeSettingsFullRuntimeProtobuf) if opts.cloud_policy_decoder_path: GenerateFile(opts.cloud_policy_decoder_path, _WriteCloudPolicyDecoder) @@ -986,50 +993,6 @@ ''' -CLOUD_POLICY_FULL_RUNTIME_PROTO_HEAD = ''' -syntax = "proto2"; - -package enterprise_management; - -message StringList { - repeated string entries = 1; -} - -message PolicyOptions { - enum PolicyMode { - // The given settings are applied regardless of user choice. - MANDATORY = 0; - // The user may choose to override the given settings. - RECOMMENDED = 1; - // No policy value is present and the policy should be ignored. - UNSET = 2; - } - optional PolicyMode mode = 1 [default = MANDATORY]; -} - -message BooleanPolicyProto { - optional PolicyOptions policy_options = 1; - optional bool value = 2; -} - -message IntegerPolicyProto { - optional PolicyOptions policy_options = 1; - optional int64 value = 2; -} - -message StringPolicyProto { - optional PolicyOptions policy_options = 1; - optional string value = 2; -} - -message StringListPolicyProto { - optional PolicyOptions policy_options = 1; - optional StringList value = 2; -} - -''' - - # Field IDs [1..RESERVED_IDS] will not be used in the wrapping protobuf. RESERVED_IDS = 2 @@ -1058,7 +1021,30 @@ def _WriteChromeSettingsProtobuf(policies, os, f, riskTags): f.write(CHROME_SETTINGS_PROTO_HEAD) + fields = [] + f.write('// PBs for individual settings.\n\n') + for policy in policies: + # Note: This protobuf also gets the unsupported policies, since it's an + # exhaustive list of all the supported user policies on any platform. + if not policy.is_device_only: + _WritePolicyProto(f, policy, fields) + f.write('// --------------------------------------------------\n' + '// Big wrapper PB containing the above groups.\n\n' + 'message ChromeSettingsProto {\n') + f.write(''.join(fields)) + f.write('}\n\n') + + +def _WriteChromeSettingsFullRuntimeProtobuf(policies, os, f, riskTags): + # For full runtime, disable LITE_RUNTIME switch and import full runtime + # version of cloud_policy.proto. + f.write(CHROME_SETTINGS_PROTO_HEAD.replace( + "option optimize_for = LITE_RUNTIME;", + "//option optimize_for = LITE_RUNTIME;").replace( + "import \"cloud_policy.proto\";", + "import \"cloud_policy_full_runtime.proto\";" + )) fields = [] f.write('// PBs for individual settings.\n\n') for policy in policies: @@ -1086,7 +1072,10 @@ def _WriteCloudPolicyFullRuntimeProtobuf(policies, os, f, riskTags): - f.write(CLOUD_POLICY_FULL_RUNTIME_PROTO_HEAD) + # For full runtime, disable LITE_RUNTIME switch + f.write(CLOUD_POLICY_PROTO_HEAD.replace( + "option optimize_for = LITE_RUNTIME;", + "//option optimize_for = LITE_RUNTIME;")) f.write('message CloudPolicySettings {\n') for policy in policies: if policy.is_supported and not policy.is_device_only:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 2d3d66f..a6ef29c 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -166,7 +166,7 @@ // RAF aligned touch input events support. const base::Feature kRafAlignedTouchInputEvents{ - "RafAlignedTouchInput", base::FEATURE_DISABLED_BY_DEFAULT}; + "RafAlignedTouchInput", base::FEATURE_ENABLED_BY_DEFAULT}; // If Pepper 3D Image Chromium is allowed, this feature controls whether it is // enabled.
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 76d8f48c..41a376d 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -57,7 +57,6 @@ "procedural_block_types.h", "root_coordinator.h", "root_coordinator.mm", - "storekit_launcher.h", "tab_parenting_global_observer.cc", "tab_parenting_global_observer.h", "web_data_service_factory.cc",
diff --git a/ios/chrome/browser/itunes_links/BUILD.gn b/ios/chrome/browser/itunes_links/BUILD.gn index 7faa8c1..7552a6b 100644 --- a/ios/chrome/browser/itunes_links/BUILD.gn +++ b/ios/chrome/browser/itunes_links/BUILD.gn
@@ -10,7 +10,7 @@ ] deps = [ "//base", - "//ios/chrome/browser", + "//ios/chrome/browser/store_kit", "//ios/web", "//url", ] @@ -25,7 +25,7 @@ deps = [ ":itunes_links", "//base", - "//ios/chrome/browser", + "//ios/chrome/browser/store_kit", "//ios/web:test_support", "//testing/gtest", "//third_party/ocmock",
diff --git a/ios/chrome/browser/itunes_links/itunes_links_observer.mm b/ios/chrome/browser/itunes_links/itunes_links_observer.mm index fc39792..e0533dd6 100644 --- a/ios/chrome/browser/itunes_links/itunes_links_observer.mm +++ b/ios/chrome/browser/itunes_links/itunes_links_observer.mm
@@ -8,9 +8,9 @@ #include "base/logging.h" #include "base/strings/sys_string_conversions.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" +#import "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" -#include "ios/web/public/web_state/web_state.h" #include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -28,7 +28,7 @@ @end @implementation ITunesLinksObserver { - __weak id<StoreKitLauncher> _storeKitLauncher; + web::WebState* _webState; std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; } @@ -37,15 +37,11 @@ if (self) { _webStateObserverBridge.reset( new web::WebStateObserverBridge(webState, self)); + _webState = webState; } return self; } -- (instancetype)init { - NOTREACHED(); - return nil; -} - + (NSString*)productIDFromURL:(const GURL&)URL { if (!URL.SchemeIsHTTPOrHTTPS() || !URL.DomainIs("itunes.apple.com")) return nil; @@ -57,17 +53,22 @@ return base::SysUTF8ToNSString(productID); } -#pragma mark - CRWWebStateObserver +#pragma mark - WebStateObserverBridge - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success { GURL URL = webState->GetLastCommittedURL(); NSString* productID = [ITunesLinksObserver productIDFromURL:URL]; - if (productID) - [_storeKitLauncher openAppStore:productID]; + if (productID) { + StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState); + if (tabHelper) + tabHelper->OpenAppStore(productID); + } } - (void)setStoreKitLauncher:(id<StoreKitLauncher>)storeKitLauncher { - _storeKitLauncher = storeKitLauncher; + StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState); + if (tabHelper) + tabHelper->SetLauncher(storeKitLauncher); } @end
diff --git a/ios/chrome/browser/itunes_links/itunes_links_observer_unittest.mm b/ios/chrome/browser/itunes_links/itunes_links_observer_unittest.mm index 10d882f..a375467 100644 --- a/ios/chrome/browser/itunes_links/itunes_links_observer_unittest.mm +++ b/ios/chrome/browser/itunes_links/itunes_links_observer_unittest.mm
@@ -6,7 +6,7 @@ #import "ios/chrome/browser/itunes_links/itunes_links_observer.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/web/public/test/fakes/test_web_state.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -23,6 +23,7 @@ class ITunesLinksObserverTest : public PlatformTest { protected: void SetUp() override { + StoreKitTabHelper::CreateForWebState(&web_state_); mocked_store_kit_launcher_ = [OCMockObject mockForProtocol:@protocol(StoreKitLauncher)]; link_observer_ = [[ITunesLinksObserver alloc] initWithWebState:&web_state_];
diff --git a/ios/chrome/browser/native_app_launcher/BUILD.gn b/ios/chrome/browser/native_app_launcher/BUILD.gn index b312559..813ad6d 100644 --- a/ios/chrome/browser/native_app_launcher/BUILD.gn +++ b/ios/chrome/browser/native_app_launcher/BUILD.gn
@@ -66,6 +66,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/infobars", "//ios/chrome/browser/net", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/tabs", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/native_app_launcher",
diff --git a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.h b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.h index 3beb9c6..9ddac65 100644 --- a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.h +++ b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.h
@@ -7,12 +7,6 @@ #import <Foundation/Foundation.h> -@class Tab; - -namespace net { -class URLRequestContextGetter; -} // namespace net - namespace web { class WebState; } // namespace web @@ -22,12 +16,8 @@ // display. @interface NativeAppNavigationController : NSObject -// Designated initializer. The use of |tab| will be phased out in the future -// when all the information needed can be fulfilled by |webState|. Use this -// instead of -init. - (instancetype)initWithWebState:(web::WebState*)webState - requestContextGetter:(net::URLRequestContextGetter*)context - tab:(Tab*)tab NS_DESIGNATED_INITIALIZER; + NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.mm b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.mm index 3e6a784..e9fac9d 100644 --- a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.mm +++ b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller.mm
@@ -18,11 +18,14 @@ #import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.h" #include "ios/chrome/browser/native_app_launcher/native_app_navigation_util.h" #import "ios/chrome/browser/open_url_util.h" +#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" +#import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_metadata.h" #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h" #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_whitelist_manager.h" +#include "ios/web/public/browser_state.h" #include "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" #include "ios/web/public/web_thread.h" @@ -51,15 +54,10 @@ @end @implementation NativeAppNavigationController { - // WebState provides access to the *TabHelper objects. This will eventually - // replace the need to have |_tab| in this object. + // WebState provides access to the *TabHelper objects. web::WebState* _webState; // ImageFetcher needed to fetch the icons. std::unique_ptr<image_fetcher::IOSImageDataFetcherWrapper> _imageFetcher; - // DEPRECATED: Tab hosting the infobar and is also used for accessing Tab - // states such as navigation manager and whether it is a pre-rendered tab. - // Use |webState| whenever possible. - __weak Tab* _tab; id<NativeAppMetadata> _metadata; // A set of appIds encoded as NSStrings. NSMutableSet* _appsPossiblyBeingInstalled; @@ -68,20 +66,14 @@ } // Designated initializer. Use this instead of -init. -- (instancetype)initWithWebState:(web::WebState*)webState - requestContextGetter:(net::URLRequestContextGetter*)context - tab:(Tab*)tab { +- (instancetype)initWithWebState:(web::WebState*)webState { self = [super init]; if (self) { - DCHECK(context); - _imageFetcher = base::MakeUnique<image_fetcher::IOSImageDataFetcherWrapper>( - context, web::WebThread::GetBlockingPool()); DCHECK(webState); _webState = webState; - // Allows |tab| to be nil for unit testing. If not nil, it should have the - // same webState. - DCHECK(!tab || [tab webState] == webState); - _tab = tab; + _imageFetcher = base::MakeUnique<image_fetcher::IOSImageDataFetcherWrapper>( + _webState->GetBrowserState()->GetRequestContext(), + web::WebThread::GetBlockingPool()); _appsPossiblyBeingInstalled = [[NSMutableSet alloc] init]; _webStateObserver = base::MakeUnique<web::WebStateObserverBridge>(webState, self); @@ -194,9 +186,9 @@ return; DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]); [_appsPossiblyBeingInstalled addObject:appIdString]; - // TODO(crbug.com/684063): Preferred method is to add a helper object to - // WebState and use the helper object to launch Store Kit. - [_tab openAppStore:appIdString]; + StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState); + if (tabHelper) + tabHelper->OpenAppStore(appIdString); } - (void)launchApp:(const GURL&)URL { @@ -215,7 +207,8 @@ #pragma mark - CRWWebStateObserver methods - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success { - if (success && ![_tab isPrerenderTab]) + Tab* tab = LegacyTabHelper::GetTabForWebState(_webState); + if (success && ![tab isPrerenderTab]) [self showInfoBarIfNecessary]; }
diff --git a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_unittest.mm b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_unittest.mm index aa23143..a703114 100644 --- a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_unittest.mm +++ b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_unittest.mm
@@ -48,10 +48,8 @@ protected: void SetUp() override { ChromeWebTest::SetUp(); - controller_.reset([[NativeAppNavigationController alloc] - initWithWebState:web_state() - requestContextGetter:GetBrowserState()->GetRequestContext() - tab:nil]); + controller_.reset( + [[NativeAppNavigationController alloc] initWithWebState:web_state()]); action_callback_ = base::Bind(&NativeAppNavigationControllerTest::OnUserAction,
diff --git a/ios/chrome/browser/store_kit/BUILD.gn b/ios/chrome/browser/store_kit/BUILD.gn new file mode 100644 index 0000000..02e9d06 --- /dev/null +++ b/ios/chrome/browser/store_kit/BUILD.gn
@@ -0,0 +1,32 @@ +# Copyright 2017 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("store_kit") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "store_kit_launcher.h", + "store_kit_tab_helper.h", + "store_kit_tab_helper.mm", + ] + deps = [ + "//base", + "//ios/web", + ] +} + +source_set("unit_tests") { + testonly = true + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "store_kit_tab_helper_unittest.mm", + ] + deps = [ + ":store_kit", + "//base", + "//ios/web", + "//ios/web:test_support", + "//testing/gtest", + "//third_party/ocmock:ocmock", + ] +}
diff --git a/ios/chrome/browser/storekit_launcher.h b/ios/chrome/browser/store_kit/store_kit_launcher.h similarity index 70% rename from ios/chrome/browser/storekit_launcher.h rename to ios/chrome/browser/store_kit/store_kit_launcher.h index c3365f29..41d8c9e 100644 --- a/ios/chrome/browser/storekit_launcher.h +++ b/ios/chrome/browser/store_kit/store_kit_launcher.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 IOS_CHROME_BROWSER_STOREKIT_LAUNCHER_H_ -#define IOS_CHROME_BROWSER_STOREKIT_LAUNCHER_H_ +#ifndef IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_LAUNCHER_H_ +#define IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_LAUNCHER_H_ @class NSString; @@ -16,4 +16,4 @@ @end -#endif // IOS_CHROME_BROWSER_STOREKIT_LAUNCHER_H_ +#endif // IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_LAUNCHER_H_
diff --git a/ios/chrome/browser/store_kit/store_kit_tab_helper.h b/ios/chrome/browser/store_kit/store_kit_tab_helper.h new file mode 100644 index 0000000..ecd0754 --- /dev/null +++ b/ios/chrome/browser/store_kit/store_kit_tab_helper.h
@@ -0,0 +1,31 @@ +// Copyright 2017 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 IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_TAB_HELPER_H_ +#define IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_TAB_HELPER_H_ + +#include "base/ios/weak_nsobject.h" +#include "base/macros.h" +#import "ios/chrome/browser/store_kit/store_kit_launcher.h" +#import "ios/web/public/web_state/web_state_user_data.h" + +// A Tab Helper object that can open to a page on iOS App Store for a given +// app product ID. +class StoreKitTabHelper : public web::WebStateUserData<StoreKitTabHelper> { + public: + explicit StoreKitTabHelper(web::WebState* web_state); + ~StoreKitTabHelper() override; + + void SetLauncher(id<StoreKitLauncher> launcher); + id<StoreKitLauncher> GetLauncher(); + + void OpenAppStore(NSString* app_id); + + private: + base::WeakNSProtocol<id<StoreKitLauncher>> store_kit_launcher_; + + DISALLOW_COPY_AND_ASSIGN(StoreKitTabHelper); +}; + +#endif // IOS_CHROME_BROWSER_STORE_KIT_STORE_KIT_TAB_HELPER_H_
diff --git a/ios/chrome/browser/store_kit/store_kit_tab_helper.mm b/ios/chrome/browser/store_kit/store_kit_tab_helper.mm new file mode 100644 index 0000000..970742a6 --- /dev/null +++ b/ios/chrome/browser/store_kit/store_kit_tab_helper.mm
@@ -0,0 +1,27 @@ +// Copyright 2017 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 "ios/chrome/browser/store_kit/store_kit_tab_helper.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +DEFINE_WEB_STATE_USER_DATA_KEY(StoreKitTabHelper); + +StoreKitTabHelper::StoreKitTabHelper(web::WebState* web_state) {} + +StoreKitTabHelper::~StoreKitTabHelper() {} + +void StoreKitTabHelper::SetLauncher(id<StoreKitLauncher> launcher) { + store_kit_launcher_.reset(launcher); +} + +id<StoreKitLauncher> StoreKitTabHelper::GetLauncher() { + return store_kit_launcher_; +} + +void StoreKitTabHelper::OpenAppStore(NSString* app_id) { + [store_kit_launcher_ openAppStore:app_id]; +}
diff --git a/ios/chrome/browser/store_kit/store_kit_tab_helper_unittest.mm b/ios/chrome/browser/store_kit/store_kit_tab_helper_unittest.mm new file mode 100644 index 0000000..0075c9c8 --- /dev/null +++ b/ios/chrome/browser/store_kit/store_kit_tab_helper_unittest.mm
@@ -0,0 +1,34 @@ +// Copyright 2017 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 "ios/chrome/browser/store_kit/store_kit_tab_helper.h" + +#include "base/macros.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +class StoreKitTabHelperTest : public web::WebTestWithWebState { + public: + StoreKitTabHelperTest() = default; + ~StoreKitTabHelperTest() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(StoreKitTabHelperTest); +}; + +TEST_F(StoreKitTabHelperTest, Constructor) { + StoreKitTabHelper::CreateForWebState(web_state()); + StoreKitTabHelper* tab_helper = StoreKitTabHelper::FromWebState(web_state()); + ASSERT_TRUE(tab_helper); + + id mock_launcher = + [OCMockObject niceMockForProtocol:@protocol(StoreKitLauncher)]; + // Verifies that GetLauncher returns the mock launcher object that was set. + tab_helper->SetLauncher(mock_launcher); + EXPECT_EQ(mock_launcher, tab_helper->GetLauncher()); +}
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index 343af87..7fb895df 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -83,6 +83,7 @@ "//ios/chrome/browser/snapshots", "//ios/chrome/browser/snapshots:snapshots_internal", "//ios/chrome/browser/ssl", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/sync", "//ios/chrome/browser/translate", "//ios/chrome/browser/u2f",
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h index 2a22dcdf..b8abdc9f 100644 --- a/ios/chrome/browser/tabs/tab.h +++ b/ios/chrome/browser/tabs/tab.h
@@ -33,7 +33,6 @@ @class PasswordController; @class SnapshotManager; @protocol SnapshotOverlayProvider; -@protocol StoreKitLauncher; @class FormSuggestionController; @protocol TabDelegate; @protocol TabDialogDelegate; @@ -143,7 +142,6 @@ // Whether or not desktop user agent is used for the currently visible page. @property(nonatomic, readonly) BOOL usesDesktopUserAgent; -@property(nonatomic, assign) id<StoreKitLauncher> storeKitLauncher; @property(nonatomic, assign) id<FullScreenControllerDelegate> fullScreenControllerDelegate; @property(nonatomic, readonly) @@ -242,10 +240,6 @@ // Dismisses all modals owned by the tab. - (void)dismissModals; -// Opens StoreKit modal to download a native application identified with -// |appId|. -- (void)openAppStore:(NSString*)appId; - // Returns the NavigationManager for this tab's WebState. Requires WebState to // be populated. Can return null. // TODO(crbug.com/620465): remove navigationManagerImpl once Tab no longer uses
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index 2ba5b8c..7636952 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -85,7 +85,7 @@ #import "ios/chrome/browser/snapshots/snapshot_overlay_provider.h" #import "ios/chrome/browser/snapshots/web_controller_snapshot_helper.h" #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #include "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h" #import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab_delegate.h" @@ -222,9 +222,6 @@ base::scoped_nsobject<OpenInController> openInController_; base::WeakNSProtocol<id<PassKitDialogProvider>> passKitDialogProvider_; - // TODO(crbug.com/546213): Move this out of Tab, probably to native app - // launcher since that's the only thing that uses it. - base::WeakNSProtocol<id<StoreKitLauncher>> storeKitLauncher_; // Whether or not this tab is currently being displayed. BOOL visible_; @@ -565,6 +562,7 @@ RepostFormTabHelper::CreateForWebState(self.webState); BlockedPopupTabHelper::CreateForWebState(self.webState); FindTabHelper::CreateForWebState(self.webState, self); + StoreKitTabHelper::CreateForWebState(self.webState); if (reading_list::switches::IsReadingListEnabled()) { ReadingListModel* model = @@ -880,14 +878,6 @@ return webStateImpl_ ? &(webStateImpl_->GetNavigationManagerImpl()) : nullptr; } -- (id<StoreKitLauncher>)storeKitLauncher { - return storeKitLauncher_.get(); -} - -- (void)setStoreKitLauncher:(id<StoreKitLauncher>)storeKitLauncher { - storeKitLauncher_.reset(storeKitLauncher); -} - // Swap out the existing session history with a new list of navigations. Forces // the tab to reload to update the UI accordingly. This is ok because none of // the session history is stored in the tab; it's always fetched through the @@ -1216,7 +1206,6 @@ self.overscrollActionsControllerDelegate = nil; self.passKitDialogProvider = nil; self.snapshotOverlayProvider = nil; - self.storeKitLauncher = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -1455,11 +1444,17 @@ } - (id<CRWNativeContent>)controllerForUnhandledContentAtURL:(const GURL&)url { + StoreKitTabHelper* helper = StoreKitTabHelper::FromWebState(self.webState); + if (!helper) + return nil; + id<StoreKitLauncher> storeKitLauncher = helper->GetLauncher(); + if (!storeKitLauncher) + return nil; DownloadManagerController* downloadController = [[[DownloadManagerController alloc] initWithURL:url requestContextGetter:browserState_->GetRequestContext() - storeKitLauncher:self.storeKitLauncher] autorelease]; + storeKitLauncher:storeKitLauncher] autorelease]; [downloadController start]; return downloadController; } @@ -1560,10 +1555,6 @@ #pragma mark - -- (void)openAppStore:(NSString*)appId { - [storeKitLauncher_ openAppStore:appId]; -} - - (BOOL)usesDesktopUserAgent { if (!self.navigationManager) return NO; @@ -2194,10 +2185,8 @@ if (browserState_->IsOffTheRecord()) return; DCHECK(!nativeAppNavigationController_); - nativeAppNavigationController_.reset([[NativeAppNavigationController alloc] - initWithWebState:self.webState - requestContextGetter:browserState_->GetRequestContext() - tab:self]); + nativeAppNavigationController_.reset( + [[NativeAppNavigationController alloc] initWithWebState:self.webState]); DCHECK(nativeAppNavigationController_); }
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index fc35f69b..f762646 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -46,6 +46,7 @@ "//base:i18n", "//ios/chrome/browser", "//ios/chrome/browser/favicon", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/ui/commands", "//ios/web", "//ui/base", @@ -99,6 +100,7 @@ "//ios/chrome/browser/find_in_page", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/sessions", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/alert_coordinator", @@ -271,6 +273,7 @@ "//ios/chrome/browser/sessions", "//ios/chrome/browser/snapshots", "//ios/chrome/browser/snapshots:snapshots_internal", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/alert_coordinator", @@ -418,6 +421,7 @@ "//ios/chrome/browser/autocomplete", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/search_engines", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/tabs", "//ios/chrome/browser/tabs:tabs_internal", "//ios/chrome/browser/ui/omnibox:omnibox_internal",
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 934f840..2399ec4 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -80,7 +80,7 @@ #import "ios/chrome/browser/snapshots/snapshot_cache.h" #import "ios/chrome/browser/snapshots/snapshot_overlay.h" #import "ios/chrome/browser/snapshots/snapshot_overlay_provider.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/tabs/tab_dialog_delegate.h" @@ -2115,7 +2115,6 @@ // deallocation. tab.dialogDelegate = self; tab.snapshotOverlayProvider = self; - tab.storeKitLauncher = self; tab.passKitDialogProvider = self; tab.fullScreenControllerDelegate = self; if (!IsIPadIdiom()) { @@ -2126,6 +2125,11 @@ // Install the proper CRWWebController delegates. tab.webController.nativeProvider = self; tab.webController.swipeRecognizerProvider = self.sideSwipeController; + // BrowserViewController presents SKStoreKitViewController on behalf of a + // tab. + StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(tab.webState); + if (tabHelper) + tabHelper->SetLauncher(self); // Delegate will remove itself on destruction. tab.webState->SetDelegate(_webStateDelegate.get()); }
diff --git a/ios/chrome/browser/ui/downloads/BUILD.gn b/ios/chrome/browser/ui/downloads/BUILD.gn index 685cea45..6813700d 100644 --- a/ios/chrome/browser/ui/downloads/BUILD.gn +++ b/ios/chrome/browser/ui/downloads/BUILD.gn
@@ -47,6 +47,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/native_app_launcher", "//ios/chrome/browser/native_app_launcher:native_app_launcher_internal", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/colors", @@ -73,6 +74,7 @@ ":downloads", "//base", "//ios/chrome/browser", + "//ios/chrome/browser/store_kit", "//ios/web:test_support", "//net:test_support", "//testing/gtest",
diff --git a/ios/chrome/browser/ui/downloads/download_manager_controller.mm b/ios/chrome/browser/ui/downloads/download_manager_controller.mm index 96cede0..c17dc19 100644 --- a/ios/chrome/browser/ui/downloads/download_manager_controller.mm +++ b/ios/chrome/browser/ui/downloads/download_manager_controller.mm
@@ -16,7 +16,6 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/sys_string_conversions.h" @@ -24,7 +23,7 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/installation_notifier.h" #include "ios/chrome/browser/native_app_launcher/ios_appstore_ids.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_launcher.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/network_activity_indicator_manager.h"
diff --git a/ios/chrome/browser/ui/downloads/download_manager_controller_unittest.mm b/ios/chrome/browser/ui/downloads/download_manager_controller_unittest.mm index 42732999..30aef37 100644 --- a/ios/chrome/browser/ui/downloads/download_manager_controller_unittest.mm +++ b/ios/chrome/browser/ui/downloads/download_manager_controller_unittest.mm
@@ -10,7 +10,7 @@ #import "base/mac/scoped_nsobject.h" #include "base/message_loop/message_loop.h" -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_launcher.h" #include "ios/web/public/test/test_web_thread.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h"
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 389ea9d..ea7a7b21 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -151,6 +151,7 @@ "//ios/chrome/browser/prefs", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/sync", "//ios/chrome/browser/translate", "//ios/chrome/browser/ui", @@ -219,6 +220,7 @@ "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/signin", "//ios/chrome/browser/signin:test_support", + "//ios/chrome/browser/store_kit", "//ios/chrome/browser/sync", "//ios/chrome/browser/sync:test_support", "//ios/chrome/browser/ui/collection_view:test_support",
diff --git a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h index a235d4b..9e8db3e 100644 --- a/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_NATIVE_APPS_COLLECTION_VIEW_CONTROLLER_H_ -#import "ios/chrome/browser/storekit_launcher.h" +#import "ios/chrome/browser/store_kit/store_kit_launcher.h" #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" namespace net {
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index cadef7b..3a151d1 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -136,6 +136,7 @@ "//ios/chrome/browser/signin:unit_tests", "//ios/chrome/browser/snapshots:unit_tests", "//ios/chrome/browser/ssl:unit_tests", + "//ios/chrome/browser/store_kit:unit_tests", "//ios/chrome/browser/suggestions:unit_tests", "//ios/chrome/browser/sync:unit_tests", "//ios/chrome/browser/tabs:unit_tests",
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index 418c8be..cd97ce8b 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc
@@ -22,7 +22,6 @@ #include "third_party/skia/include/core/SkImageGenerator.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/GrPaint.h" -#include "third_party/skia/include/gpu/SkGr.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/skia_util.h"
diff --git a/mojo/public/js/new_bindings/bindings.js b/mojo/public/js/new_bindings/bindings.js new file mode 100644 index 0000000..f3e40d29 --- /dev/null +++ b/mojo/public/js/new_bindings/bindings.js
@@ -0,0 +1,285 @@ +// 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. + +define("mojo/public/js/bindings", [ + "mojo/public/js/core", + "mojo/public/js/lib/control_message_proxy", + "mojo/public/js/interface_types", + "mojo/public/js/router", +], function(core, controlMessageProxy, types, router) { + + // --------------------------------------------------------------------------- + + function makeRequest(interfacePtr) { + var pipe = core.createMessagePipe(); + interfacePtr.ptr.bind(new types.InterfacePtrInfo(pipe.handle0, 0)); + return new types.InterfaceRequest(pipe.handle1); + } + + // --------------------------------------------------------------------------- + + // Operations used to setup/configure an interface pointer. Exposed as the + // |ptr| field of generated interface pointer classes. + // |ptrInfoOrHandle| could be omitted and passed into bind() later. + function InterfacePtrController(interfaceType, ptrInfoOrHandle) { + this.version = 0; + + this.interfaceType_ = interfaceType; + this.router_ = null; + this.proxy_ = null; + + // |router_| is lazily initialized. |handle_| is valid between bind() and + // the initialization of |router_|. + this.handle_ = null; + this.controlMessageProxy_ = null; + + if (ptrInfoOrHandle) + this.bind(ptrInfoOrHandle); + } + + InterfacePtrController.prototype.bind = function(ptrInfoOrHandle) { + this.reset(); + + if (ptrInfoOrHandle instanceof types.InterfacePtrInfo) { + this.version = ptrInfoOrHandle.version; + this.handle_ = ptrInfoOrHandle.handle; + } else { + this.handle_ = ptrInfoOrHandle; + } + }; + + InterfacePtrController.prototype.isBound = function() { + return this.router_ !== null || this.handle_ !== null; + }; + + // Although users could just discard the object, reset() closes the pipe + // immediately. + InterfacePtrController.prototype.reset = function() { + this.version = 0; + if (this.router_) { + this.router_.close(); + this.router_ = null; + + this.proxy_ = null; + } + if (this.handle_) { + core.close(this.handle_); + this.handle_ = null; + } + }; + + InterfacePtrController.prototype.setConnectionErrorHandler + = function(callback) { + if (!this.isBound()) + throw new Error("Cannot set connection error handler if not bound."); + + this.configureProxyIfNecessary_(); + this.router_.setErrorHandler(callback); + }; + + InterfacePtrController.prototype.passInterface = function() { + var result; + if (this.router_) { + // TODO(yzshen): Fix Router interface to support extracting handle. + result = new types.InterfacePtrInfo( + this.router_.connector_.handle_, this.version); + this.router_.connector_.handle_ = null; + } else { + // This also handles the case when this object is not bound. + result = new types.InterfacePtrInfo(this.handle_, this.version); + this.handle_ = null; + } + + this.reset(); + return result; + }; + + InterfacePtrController.prototype.getProxy = function() { + this.configureProxyIfNecessary_(); + return this.proxy_; + }; + + InterfacePtrController.prototype.enableTestingMode = function() { + this.configureProxyIfNecessary_(); + return this.router_.enableTestingMode(); + }; + + InterfacePtrController.prototype.configureProxyIfNecessary_ = function() { + if (!this.handle_) + return; + + this.router_ = new router.Router(this.handle_); + this.handle_ = null; + this.router_ .setPayloadValidators([this.interfaceType_.validateResponse]); + + this.controlMessageProxy_ = new + controlMessageProxy.ControlMessageProxy(this.router_); + + this.proxy_ = new this.interfaceType_.proxyClass(this.router_); + }; + + InterfacePtrController.prototype.queryVersion = function() { + function onQueryVersion(version) { + this.version = version; + return version; + } + + this.configureProxyIfNecessary_(); + return this.controlMessageProxy_.queryVersion().then( + onQueryVersion.bind(this)); + }; + + InterfacePtrController.prototype.requireVersion = function(version) { + this.configureProxyIfNecessary_(); + + if (this.version >= version) { + return; + } + this.version = version; + this.controlMessageProxy_.requireVersion(version); + }; + + // --------------------------------------------------------------------------- + + // |request| could be omitted and passed into bind() later. + // + // Example: + // + // // FooImpl implements mojom.Foo. + // function FooImpl() { ... } + // FooImpl.prototype.fooMethod1 = function() { ... } + // FooImpl.prototype.fooMethod2 = function() { ... } + // + // var fooPtr = new mojom.FooPtr(); + // var request = makeRequest(fooPtr); + // var binding = new Binding(mojom.Foo, new FooImpl(), request); + // fooPtr.fooMethod1(); + function Binding(interfaceType, impl, requestOrHandle) { + this.interfaceType_ = interfaceType; + this.impl_ = impl; + this.router_ = null; + this.stub_ = null; + + if (requestOrHandle) + this.bind(requestOrHandle); + } + + Binding.prototype.isBound = function() { + return this.router_ !== null; + }; + + Binding.prototype.createInterfacePtrAndBind = function() { + var ptr = new this.interfaceType_.ptrClass(); + // TODO(yzshen): Set the version of the interface pointer. + this.bind(makeRequest(ptr)); + return ptr; + } + + Binding.prototype.bind = function(requestOrHandle) { + this.close(); + + var handle = requestOrHandle instanceof types.InterfaceRequest ? + requestOrHandle.handle : requestOrHandle; + if (!core.isHandle(handle)) + return; + + this.stub_ = new this.interfaceType_.stubClass(this.impl_); + this.router_ = new router.Router(handle, this.interfaceType_.kVersion); + this.router_.setIncomingReceiver(this.stub_); + this.router_ .setPayloadValidators([this.interfaceType_.validateRequest]); + }; + + Binding.prototype.close = function() { + if (!this.isBound()) + return; + + this.router_.close(); + this.router_ = null; + this.stub_ = null; + }; + + Binding.prototype.setConnectionErrorHandler + = function(callback) { + if (!this.isBound()) + throw new Error("Cannot set connection error handler if not bound."); + this.router_.setErrorHandler(callback); + }; + + Binding.prototype.unbind = function() { + if (!this.isBound()) + return new types.InterfaceRequest(null); + + var result = new types.InterfaceRequest(this.router_.connector_.handle_); + this.router_.connector_.handle_ = null; + this.close(); + return result; + }; + + Binding.prototype.enableTestingMode = function() { + return this.router_.enableTestingMode(); + }; + + // --------------------------------------------------------------------------- + + function BindingSetEntry(bindingSet, interfaceType, impl, requestOrHandle, + bindingId) { + this.bindingSet_ = bindingSet; + this.bindingId_ = bindingId; + this.binding_ = new Binding(interfaceType, impl, requestOrHandle); + + this.binding_.setConnectionErrorHandler(function() { + this.bindingSet_.onConnectionError(bindingId); + }.bind(this)); + } + + BindingSetEntry.prototype.close = function() { + this.binding_.close(); + }; + + function BindingSet(interfaceType) { + this.interfaceType_ = interfaceType; + this.nextBindingId_ = 0; + this.bindings_ = new Map(); + this.errorHandler_ = null; + } + + BindingSet.prototype.isEmpty = function() { + return this.bindings_.size == 0; + }; + + BindingSet.prototype.addBinding = function(impl, requestOrHandle) { + this.bindings_.set( + this.nextBindingId_, + new BindingSetEntry(this, this.interfaceType_, impl, requestOrHandle, + this.nextBindingId_)); + ++this.nextBindingId_; + }; + + BindingSet.prototype.closeAllBindings = function() { + for (var entry of this.bindings_.values()) + entry.close(); + this.bindings_.clear(); + }; + + BindingSet.prototype.setConnectionErrorHandler = function(callback) { + this.errorHandler_ = callback; + }; + + BindingSet.prototype.onConnectionError = function(bindingId) { + this.bindings_.delete(bindingId); + + if (this.errorHandler_) + this.errorHandler_(); + }; + + var exports = {}; + exports.InterfacePtrInfo = types.InterfacePtrInfo; + exports.InterfaceRequest = types.InterfaceRequest; + exports.makeRequest = makeRequest; + exports.InterfacePtrController = InterfacePtrController; + exports.Binding = Binding; + exports.BindingSet = BindingSet; + + return exports; +});
diff --git a/mojo/public/js/new_bindings/buffer.js b/mojo/public/js/new_bindings/buffer.js new file mode 100644 index 0000000..e35f6951 --- /dev/null +++ b/mojo/public/js/new_bindings/buffer.js
@@ -0,0 +1,156 @@ +// 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. + +define("mojo/public/js/buffer", function() { + + var kHostIsLittleEndian = (function () { + var endianArrayBuffer = new ArrayBuffer(2); + var endianUint8Array = new Uint8Array(endianArrayBuffer); + var endianUint16Array = new Uint16Array(endianArrayBuffer); + endianUint16Array[0] = 1; + return endianUint8Array[0] == 1; + })(); + + var kHighWordMultiplier = 0x100000000; + + function Buffer(sizeOrArrayBuffer) { + if (sizeOrArrayBuffer instanceof ArrayBuffer) + this.arrayBuffer = sizeOrArrayBuffer; + else + this.arrayBuffer = new ArrayBuffer(sizeOrArrayBuffer); + + this.dataView = new DataView(this.arrayBuffer); + this.next = 0; + } + + Object.defineProperty(Buffer.prototype, "byteLength", { + get: function() { return this.arrayBuffer.byteLength; } + }); + + Buffer.prototype.alloc = function(size) { + var pointer = this.next; + this.next += size; + if (this.next > this.byteLength) { + var newSize = (1.5 * (this.byteLength + size)) | 0; + this.grow(newSize); + } + return pointer; + }; + + function copyArrayBuffer(dstArrayBuffer, srcArrayBuffer) { + (new Uint8Array(dstArrayBuffer)).set(new Uint8Array(srcArrayBuffer)); + } + + Buffer.prototype.grow = function(size) { + var newArrayBuffer = new ArrayBuffer(size); + copyArrayBuffer(newArrayBuffer, this.arrayBuffer); + this.arrayBuffer = newArrayBuffer; + this.dataView = new DataView(this.arrayBuffer); + }; + + Buffer.prototype.trim = function() { + this.arrayBuffer = this.arrayBuffer.slice(0, this.next); + this.dataView = new DataView(this.arrayBuffer); + }; + + Buffer.prototype.getUint8 = function(offset) { + return this.dataView.getUint8(offset); + } + Buffer.prototype.getUint16 = function(offset) { + return this.dataView.getUint16(offset, kHostIsLittleEndian); + } + Buffer.prototype.getUint32 = function(offset) { + return this.dataView.getUint32(offset, kHostIsLittleEndian); + } + Buffer.prototype.getUint64 = function(offset) { + var lo, hi; + if (kHostIsLittleEndian) { + lo = this.dataView.getUint32(offset, kHostIsLittleEndian); + hi = this.dataView.getUint32(offset + 4, kHostIsLittleEndian); + } else { + hi = this.dataView.getUint32(offset, kHostIsLittleEndian); + lo = this.dataView.getUint32(offset + 4, kHostIsLittleEndian); + } + return lo + hi * kHighWordMultiplier; + } + + Buffer.prototype.getInt8 = function(offset) { + return this.dataView.getInt8(offset); + } + Buffer.prototype.getInt16 = function(offset) { + return this.dataView.getInt16(offset, kHostIsLittleEndian); + } + Buffer.prototype.getInt32 = function(offset) { + return this.dataView.getInt32(offset, kHostIsLittleEndian); + } + Buffer.prototype.getInt64 = function(offset) { + var lo, hi; + if (kHostIsLittleEndian) { + lo = this.dataView.getUint32(offset, kHostIsLittleEndian); + hi = this.dataView.getInt32(offset + 4, kHostIsLittleEndian); + } else { + hi = this.dataView.getInt32(offset, kHostIsLittleEndian); + lo = this.dataView.getUint32(offset + 4, kHostIsLittleEndian); + } + return lo + hi * kHighWordMultiplier; + } + + Buffer.prototype.getFloat32 = function(offset) { + return this.dataView.getFloat32(offset, kHostIsLittleEndian); + } + Buffer.prototype.getFloat64 = function(offset) { + return this.dataView.getFloat64(offset, kHostIsLittleEndian); + } + + Buffer.prototype.setUint8 = function(offset, value) { + this.dataView.setUint8(offset, value); + } + Buffer.prototype.setUint16 = function(offset, value) { + this.dataView.setUint16(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setUint32 = function(offset, value) { + this.dataView.setUint32(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setUint64 = function(offset, value) { + var hi = (value / kHighWordMultiplier) | 0; + if (kHostIsLittleEndian) { + this.dataView.setInt32(offset, value, kHostIsLittleEndian); + this.dataView.setInt32(offset + 4, hi, kHostIsLittleEndian); + } else { + this.dataView.setInt32(offset, hi, kHostIsLittleEndian); + this.dataView.setInt32(offset + 4, value, kHostIsLittleEndian); + } + } + + Buffer.prototype.setInt8 = function(offset, value) { + this.dataView.setInt8(offset, value); + } + Buffer.prototype.setInt16 = function(offset, value) { + this.dataView.setInt16(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setInt32 = function(offset, value) { + this.dataView.setInt32(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setInt64 = function(offset, value) { + var hi = Math.floor(value / kHighWordMultiplier); + if (kHostIsLittleEndian) { + this.dataView.setInt32(offset, value, kHostIsLittleEndian); + this.dataView.setInt32(offset + 4, hi, kHostIsLittleEndian); + } else { + this.dataView.setInt32(offset, hi, kHostIsLittleEndian); + this.dataView.setInt32(offset + 4, value, kHostIsLittleEndian); + } + } + + Buffer.prototype.setFloat32 = function(offset, value) { + this.dataView.setFloat32(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setFloat64 = function(offset, value) { + this.dataView.setFloat64(offset, value, kHostIsLittleEndian); + } + + var exports = {}; + exports.Buffer = Buffer; + return exports; +});
diff --git a/mojo/public/js/new_bindings/codec.js b/mojo/public/js/new_bindings/codec.js new file mode 100644 index 0000000..ff5d31a --- /dev/null +++ b/mojo/public/js/new_bindings/codec.js
@@ -0,0 +1,922 @@ +// 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. + +define("mojo/public/js/codec", [ + "mojo/public/js/buffer", + "mojo/public/js/interface_types", + "mojo/public/js/unicode", +], function(buffer, types, unicode) { + + var kErrorUnsigned = "Passing negative value to unsigned"; + var kErrorArray = "Passing non Array for array type"; + var kErrorString = "Passing non String for string type"; + var kErrorMap = "Passing non Map for map type"; + + // Memory ------------------------------------------------------------------- + + var kAlignment = 8; + + function align(size) { + return size + (kAlignment - (size % kAlignment)) % kAlignment; + } + + function isAligned(offset) { + return offset >= 0 && (offset % kAlignment) === 0; + } + + // Constants ---------------------------------------------------------------- + + var kArrayHeaderSize = 8; + var kStructHeaderSize = 8; + var kMessageHeaderSize = 24; + var kMessageWithRequestIDHeaderSize = 32; + var kMapStructPayloadSize = 16; + + var kStructHeaderNumBytesOffset = 0; + var kStructHeaderVersionOffset = 4; + + var kEncodedInvalidHandleValue = 0xFFFFFFFF; + + // Decoder ------------------------------------------------------------------ + + function Decoder(buffer, handles, base) { + this.buffer = buffer; + this.handles = handles; + this.base = base; + this.next = base; + } + + Decoder.prototype.align = function() { + this.next = align(this.next); + }; + + Decoder.prototype.skip = function(offset) { + this.next += offset; + }; + + Decoder.prototype.readInt8 = function() { + var result = this.buffer.getInt8(this.next); + this.next += 1; + return result; + }; + + Decoder.prototype.readUint8 = function() { + var result = this.buffer.getUint8(this.next); + this.next += 1; + return result; + }; + + Decoder.prototype.readInt16 = function() { + var result = this.buffer.getInt16(this.next); + this.next += 2; + return result; + }; + + Decoder.prototype.readUint16 = function() { + var result = this.buffer.getUint16(this.next); + this.next += 2; + return result; + }; + + Decoder.prototype.readInt32 = function() { + var result = this.buffer.getInt32(this.next); + this.next += 4; + return result; + }; + + Decoder.prototype.readUint32 = function() { + var result = this.buffer.getUint32(this.next); + this.next += 4; + return result; + }; + + Decoder.prototype.readInt64 = function() { + var result = this.buffer.getInt64(this.next); + this.next += 8; + return result; + }; + + Decoder.prototype.readUint64 = function() { + var result = this.buffer.getUint64(this.next); + this.next += 8; + return result; + }; + + Decoder.prototype.readFloat = function() { + var result = this.buffer.getFloat32(this.next); + this.next += 4; + return result; + }; + + Decoder.prototype.readDouble = function() { + var result = this.buffer.getFloat64(this.next); + this.next += 8; + return result; + }; + + Decoder.prototype.decodePointer = function() { + // TODO(abarth): To correctly decode a pointer, we need to know the real + // base address of the array buffer. + var offsetPointer = this.next; + var offset = this.readUint64(); + if (!offset) + return 0; + return offsetPointer + offset; + }; + + Decoder.prototype.decodeAndCreateDecoder = function(pointer) { + return new Decoder(this.buffer, this.handles, pointer); + }; + + Decoder.prototype.decodeHandle = function() { + return this.handles[this.readUint32()] || null; + }; + + Decoder.prototype.decodeString = function() { + var numberOfBytes = this.readUint32(); + var numberOfElements = this.readUint32(); + var base = this.next; + this.next += numberOfElements; + return unicode.decodeUtf8String( + new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements)); + }; + + Decoder.prototype.decodeArray = function(cls) { + var numberOfBytes = this.readUint32(); + var numberOfElements = this.readUint32(); + var val = new Array(numberOfElements); + if (cls === PackedBool) { + var byte; + for (var i = 0; i < numberOfElements; ++i) { + if (i % 8 === 0) + byte = this.readUint8(); + val[i] = (byte & (1 << i % 8)) ? true : false; + } + } else { + for (var i = 0; i < numberOfElements; ++i) { + val[i] = cls.decode(this); + } + } + return val; + }; + + Decoder.prototype.decodeStruct = function(cls) { + return cls.decode(this); + }; + + Decoder.prototype.decodeStructPointer = function(cls) { + var pointer = this.decodePointer(); + if (!pointer) { + return null; + } + return cls.decode(this.decodeAndCreateDecoder(pointer)); + }; + + Decoder.prototype.decodeArrayPointer = function(cls) { + var pointer = this.decodePointer(); + if (!pointer) { + return null; + } + return this.decodeAndCreateDecoder(pointer).decodeArray(cls); + }; + + Decoder.prototype.decodeStringPointer = function() { + var pointer = this.decodePointer(); + if (!pointer) { + return null; + } + return this.decodeAndCreateDecoder(pointer).decodeString(); + }; + + Decoder.prototype.decodeMap = function(keyClass, valueClass) { + this.skip(4); // numberOfBytes + this.skip(4); // version + var keys = this.decodeArrayPointer(keyClass); + var values = this.decodeArrayPointer(valueClass); + var val = new Map(); + for (var i = 0; i < keys.length; i++) + val.set(keys[i], values[i]); + return val; + }; + + Decoder.prototype.decodeMapPointer = function(keyClass, valueClass) { + var pointer = this.decodePointer(); + if (!pointer) { + return null; + } + var decoder = this.decodeAndCreateDecoder(pointer); + return decoder.decodeMap(keyClass, valueClass); + }; + + // Encoder ------------------------------------------------------------------ + + function Encoder(buffer, handles, base) { + this.buffer = buffer; + this.handles = handles; + this.base = base; + this.next = base; + } + + Encoder.prototype.align = function() { + this.next = align(this.next); + }; + + Encoder.prototype.skip = function(offset) { + this.next += offset; + }; + + Encoder.prototype.writeInt8 = function(val) { + this.buffer.setInt8(this.next, val); + this.next += 1; + }; + + Encoder.prototype.writeUint8 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.setUint8(this.next, val); + this.next += 1; + }; + + Encoder.prototype.writeInt16 = function(val) { + this.buffer.setInt16(this.next, val); + this.next += 2; + }; + + Encoder.prototype.writeUint16 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.setUint16(this.next, val); + this.next += 2; + }; + + Encoder.prototype.writeInt32 = function(val) { + this.buffer.setInt32(this.next, val); + this.next += 4; + }; + + Encoder.prototype.writeUint32 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.setUint32(this.next, val); + this.next += 4; + }; + + Encoder.prototype.writeInt64 = function(val) { + this.buffer.setInt64(this.next, val); + this.next += 8; + }; + + Encoder.prototype.writeUint64 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.setUint64(this.next, val); + this.next += 8; + }; + + Encoder.prototype.writeFloat = function(val) { + this.buffer.setFloat32(this.next, val); + this.next += 4; + }; + + Encoder.prototype.writeDouble = function(val) { + this.buffer.setFloat64(this.next, val); + this.next += 8; + }; + + Encoder.prototype.encodePointer = function(pointer) { + if (!pointer) + return this.writeUint64(0); + // TODO(abarth): To correctly encode a pointer, we need to know the real + // base address of the array buffer. + var offset = pointer - this.next; + this.writeUint64(offset); + }; + + Encoder.prototype.createAndEncodeEncoder = function(size) { + var pointer = this.buffer.alloc(align(size)); + this.encodePointer(pointer); + return new Encoder(this.buffer, this.handles, pointer); + }; + + Encoder.prototype.encodeHandle = function(handle) { + if (handle) { + this.handles.push(handle); + this.writeUint32(this.handles.length - 1); + } else { + this.writeUint32(kEncodedInvalidHandleValue); + } + }; + + Encoder.prototype.encodeString = function(val) { + var base = this.next + kArrayHeaderSize; + var numberOfElements = unicode.encodeUtf8String( + val, new Uint8Array(this.buffer.arrayBuffer, base)); + var numberOfBytes = kArrayHeaderSize + numberOfElements; + this.writeUint32(numberOfBytes); + this.writeUint32(numberOfElements); + this.next += numberOfElements; + }; + + Encoder.prototype.encodeArray = + function(cls, val, numberOfElements, encodedSize) { + if (numberOfElements === undefined) + numberOfElements = val.length; + if (encodedSize === undefined) + encodedSize = kArrayHeaderSize + cls.encodedSize * numberOfElements; + + this.writeUint32(encodedSize); + this.writeUint32(numberOfElements); + + if (cls === PackedBool) { + var byte = 0; + for (i = 0; i < numberOfElements; ++i) { + if (val[i]) + byte |= (1 << i % 8); + if (i % 8 === 7 || i == numberOfElements - 1) { + Uint8.encode(this, byte); + byte = 0; + } + } + } else { + for (var i = 0; i < numberOfElements; ++i) + cls.encode(this, val[i]); + } + }; + + Encoder.prototype.encodeStruct = function(cls, val) { + return cls.encode(this, val); + }; + + Encoder.prototype.encodeStructPointer = function(cls, val) { + if (val == null) { + // Also handles undefined, since undefined == null. + this.encodePointer(val); + return; + } + var encoder = this.createAndEncodeEncoder(cls.encodedSize); + cls.encode(encoder, val); + }; + + Encoder.prototype.encodeArrayPointer = function(cls, val) { + if (val == null) { + // Also handles undefined, since undefined == null. + this.encodePointer(val); + return; + } + + var numberOfElements = val.length; + if (!Number.isSafeInteger(numberOfElements) || numberOfElements < 0) + throw new Error(kErrorArray); + + var encodedSize = kArrayHeaderSize + ((cls === PackedBool) ? + Math.ceil(numberOfElements / 8) : cls.encodedSize * numberOfElements); + var encoder = this.createAndEncodeEncoder(encodedSize); + encoder.encodeArray(cls, val, numberOfElements, encodedSize); + }; + + Encoder.prototype.encodeStringPointer = function(val) { + if (val == null) { + // Also handles undefined, since undefined == null. + this.encodePointer(val); + return; + } + // Only accepts string primivites, not String Objects like new String("foo") + if (typeof(val) !== "string") { + throw new Error(kErrorString); + } + var encodedSize = kArrayHeaderSize + unicode.utf8Length(val); + var encoder = this.createAndEncodeEncoder(encodedSize); + encoder.encodeString(val); + }; + + Encoder.prototype.encodeMap = function(keyClass, valueClass, val) { + var keys = new Array(val.size); + var values = new Array(val.size); + var i = 0; + val.forEach(function(value, key) { + values[i] = value; + keys[i++] = key; + }); + this.writeUint32(kStructHeaderSize + kMapStructPayloadSize); + this.writeUint32(0); // version + this.encodeArrayPointer(keyClass, keys); + this.encodeArrayPointer(valueClass, values); + } + + Encoder.prototype.encodeMapPointer = function(keyClass, valueClass, val) { + if (val == null) { + // Also handles undefined, since undefined == null. + this.encodePointer(val); + return; + } + if (!(val instanceof Map)) { + throw new Error(kErrorMap); + } + var encodedSize = kStructHeaderSize + kMapStructPayloadSize; + var encoder = this.createAndEncodeEncoder(encodedSize); + encoder.encodeMap(keyClass, valueClass, val); + }; + + // Message ------------------------------------------------------------------ + + var kMessageInterfaceIdOffset = kStructHeaderSize; + var kMessageNameOffset = kMessageInterfaceIdOffset + 4; + var kMessageFlagsOffset = kMessageNameOffset + 4; + var kMessageRequestIDOffset = kMessageFlagsOffset + 8; + + var kMessageExpectsResponse = 1 << 0; + var kMessageIsResponse = 1 << 1; + + function Message(buffer, handles) { + this.buffer = buffer; + this.handles = handles; + } + + Message.prototype.getHeaderNumBytes = function() { + return this.buffer.getUint32(kStructHeaderNumBytesOffset); + }; + + Message.prototype.getHeaderVersion = function() { + return this.buffer.getUint32(kStructHeaderVersionOffset); + }; + + Message.prototype.getName = function() { + return this.buffer.getUint32(kMessageNameOffset); + }; + + Message.prototype.getFlags = function() { + return this.buffer.getUint32(kMessageFlagsOffset); + }; + + Message.prototype.isResponse = function() { + return (this.getFlags() & kMessageIsResponse) != 0; + }; + + Message.prototype.expectsResponse = function() { + return (this.getFlags() & kMessageExpectsResponse) != 0; + }; + + Message.prototype.setRequestID = function(requestID) { + // TODO(darin): Verify that space was reserved for this field! + this.buffer.setUint64(kMessageRequestIDOffset, requestID); + }; + + + // MessageBuilder ----------------------------------------------------------- + + function MessageBuilder(messageName, payloadSize) { + // Currently, we don't compute the payload size correctly ahead of time. + // Instead, we resize the buffer at the end. + var numberOfBytes = kMessageHeaderSize + payloadSize; + this.buffer = new buffer.Buffer(numberOfBytes); + this.handles = []; + var encoder = this.createEncoder(kMessageHeaderSize); + encoder.writeUint32(kMessageHeaderSize); + encoder.writeUint32(0); // version. + encoder.writeUint32(0); // interface ID. + encoder.writeUint32(messageName); + encoder.writeUint32(0); // flags. + encoder.writeUint32(0); // padding. + } + + MessageBuilder.prototype.createEncoder = function(size) { + var pointer = this.buffer.alloc(size); + return new Encoder(this.buffer, this.handles, pointer); + }; + + MessageBuilder.prototype.encodeStruct = function(cls, val) { + cls.encode(this.createEncoder(cls.encodedSize), val); + }; + + MessageBuilder.prototype.finish = function() { + // TODO(abarth): Rather than resizing the buffer at the end, we could + // compute the size we need ahead of time, like we do in C++. + this.buffer.trim(); + var message = new Message(this.buffer, this.handles); + this.buffer = null; + this.handles = null; + this.encoder = null; + return message; + }; + + // MessageWithRequestIDBuilder ----------------------------------------------- + + function MessageWithRequestIDBuilder(messageName, payloadSize, flags, + requestID) { + // Currently, we don't compute the payload size correctly ahead of time. + // Instead, we resize the buffer at the end. + var numberOfBytes = kMessageWithRequestIDHeaderSize + payloadSize; + this.buffer = new buffer.Buffer(numberOfBytes); + this.handles = []; + var encoder = this.createEncoder(kMessageWithRequestIDHeaderSize); + encoder.writeUint32(kMessageWithRequestIDHeaderSize); + encoder.writeUint32(1); // version. + encoder.writeUint32(0); // interface ID. + encoder.writeUint32(messageName); + encoder.writeUint32(flags); + encoder.writeUint32(0); // padding. + encoder.writeUint64(requestID); + } + + MessageWithRequestIDBuilder.prototype = + Object.create(MessageBuilder.prototype); + + MessageWithRequestIDBuilder.prototype.constructor = + MessageWithRequestIDBuilder; + + // MessageReader ------------------------------------------------------------ + + function MessageReader(message) { + this.decoder = new Decoder(message.buffer, message.handles, 0); + var messageHeaderSize = this.decoder.readUint32(); + this.payloadSize = message.buffer.byteLength - messageHeaderSize; + var version = this.decoder.readUint32(); + var interface_id = this.decoder.readUint32(); + if (interface_id != 0) { + throw new Error("Receiving non-zero interface ID. Associated interfaces " + + "are not yet supported."); + } + this.messageName = this.decoder.readUint32(); + this.flags = this.decoder.readUint32(); + // Skip the padding. + this.decoder.skip(4); + if (version >= 1) + this.requestID = this.decoder.readUint64(); + this.decoder.skip(messageHeaderSize - this.decoder.next); + } + + MessageReader.prototype.decodeStruct = function(cls) { + return cls.decode(this.decoder); + }; + + // Built-in types ----------------------------------------------------------- + + // This type is only used with ArrayOf(PackedBool). + function PackedBool() { + } + + function Int8() { + } + + Int8.encodedSize = 1; + + Int8.decode = function(decoder) { + return decoder.readInt8(); + }; + + Int8.encode = function(encoder, val) { + encoder.writeInt8(val); + }; + + Uint8.encode = function(encoder, val) { + encoder.writeUint8(val); + }; + + function Uint8() { + } + + Uint8.encodedSize = 1; + + Uint8.decode = function(decoder) { + return decoder.readUint8(); + }; + + Uint8.encode = function(encoder, val) { + encoder.writeUint8(val); + }; + + function Int16() { + } + + Int16.encodedSize = 2; + + Int16.decode = function(decoder) { + return decoder.readInt16(); + }; + + Int16.encode = function(encoder, val) { + encoder.writeInt16(val); + }; + + function Uint16() { + } + + Uint16.encodedSize = 2; + + Uint16.decode = function(decoder) { + return decoder.readUint16(); + }; + + Uint16.encode = function(encoder, val) { + encoder.writeUint16(val); + }; + + function Int32() { + } + + Int32.encodedSize = 4; + + Int32.decode = function(decoder) { + return decoder.readInt32(); + }; + + Int32.encode = function(encoder, val) { + encoder.writeInt32(val); + }; + + function Uint32() { + } + + Uint32.encodedSize = 4; + + Uint32.decode = function(decoder) { + return decoder.readUint32(); + }; + + Uint32.encode = function(encoder, val) { + encoder.writeUint32(val); + }; + + function Int64() { + } + + Int64.encodedSize = 8; + + Int64.decode = function(decoder) { + return decoder.readInt64(); + }; + + Int64.encode = function(encoder, val) { + encoder.writeInt64(val); + }; + + function Uint64() { + } + + Uint64.encodedSize = 8; + + Uint64.decode = function(decoder) { + return decoder.readUint64(); + }; + + Uint64.encode = function(encoder, val) { + encoder.writeUint64(val); + }; + + function String() { + }; + + String.encodedSize = 8; + + String.decode = function(decoder) { + return decoder.decodeStringPointer(); + }; + + String.encode = function(encoder, val) { + encoder.encodeStringPointer(val); + }; + + function NullableString() { + } + + NullableString.encodedSize = String.encodedSize; + + NullableString.decode = String.decode; + + NullableString.encode = String.encode; + + function Float() { + } + + Float.encodedSize = 4; + + Float.decode = function(decoder) { + return decoder.readFloat(); + }; + + Float.encode = function(encoder, val) { + encoder.writeFloat(val); + }; + + function Double() { + } + + Double.encodedSize = 8; + + Double.decode = function(decoder) { + return decoder.readDouble(); + }; + + Double.encode = function(encoder, val) { + encoder.writeDouble(val); + }; + + function Enum(cls) { + this.cls = cls; + } + + Enum.prototype.encodedSize = 4; + + Enum.prototype.decode = function(decoder) { + return decoder.readInt32(); + }; + + Enum.prototype.encode = function(encoder, val) { + encoder.writeInt32(val); + }; + + function PointerTo(cls) { + this.cls = cls; + } + + PointerTo.prototype.encodedSize = 8; + + PointerTo.prototype.decode = function(decoder) { + var pointer = decoder.decodePointer(); + if (!pointer) { + return null; + } + return this.cls.decode(decoder.decodeAndCreateDecoder(pointer)); + }; + + PointerTo.prototype.encode = function(encoder, val) { + if (!val) { + encoder.encodePointer(val); + return; + } + var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize); + this.cls.encode(objectEncoder, val); + }; + + function NullablePointerTo(cls) { + PointerTo.call(this, cls); + } + + NullablePointerTo.prototype = Object.create(PointerTo.prototype); + + function ArrayOf(cls, length) { + this.cls = cls; + this.length = length || 0; + } + + ArrayOf.prototype.encodedSize = 8; + + ArrayOf.prototype.dimensions = function() { + return [this.length].concat( + (this.cls instanceof ArrayOf) ? this.cls.dimensions() : []); + } + + ArrayOf.prototype.decode = function(decoder) { + return decoder.decodeArrayPointer(this.cls); + }; + + ArrayOf.prototype.encode = function(encoder, val) { + encoder.encodeArrayPointer(this.cls, val); + }; + + function NullableArrayOf(cls) { + ArrayOf.call(this, cls); + } + + NullableArrayOf.prototype = Object.create(ArrayOf.prototype); + + function Handle() { + } + + Handle.encodedSize = 4; + + Handle.decode = function(decoder) { + return decoder.decodeHandle(); + }; + + Handle.encode = function(encoder, val) { + encoder.encodeHandle(val); + }; + + function NullableHandle() { + } + + NullableHandle.encodedSize = Handle.encodedSize; + + NullableHandle.decode = Handle.decode; + + NullableHandle.encode = Handle.encode; + + function Interface(cls) { + this.cls = cls; + } + + Interface.prototype.encodedSize = 8; + + Interface.prototype.decode = function(decoder) { + var interfacePtrInfo = new types.InterfacePtrInfo( + decoder.decodeHandle(), decoder.readUint32()); + var interfacePtr = new this.cls(); + interfacePtr.ptr.bind(interfacePtrInfo); + return interfacePtr; + }; + + Interface.prototype.encode = function(encoder, val) { + var interfacePtrInfo = + val ? val.ptr.passInterface() : new types.InterfacePtrInfo(null, 0); + encoder.encodeHandle(interfacePtrInfo.handle); + encoder.writeUint32(interfacePtrInfo.version); + }; + + function NullableInterface(cls) { + Interface.call(this, cls); + } + + NullableInterface.prototype = Object.create(Interface.prototype); + + function InterfaceRequest() { + } + + InterfaceRequest.encodedSize = 4; + + InterfaceRequest.decode = function(decoder) { + return new types.InterfaceRequest(decoder.decodeHandle()); + }; + + InterfaceRequest.encode = function(encoder, val) { + encoder.encodeHandle(val ? val.handle : null); + }; + + function NullableInterfaceRequest() { + } + + NullableInterfaceRequest.encodedSize = InterfaceRequest.encodedSize; + + NullableInterfaceRequest.decode = InterfaceRequest.decode; + + NullableInterfaceRequest.encode = InterfaceRequest.encode; + + function MapOf(keyClass, valueClass) { + this.keyClass = keyClass; + this.valueClass = valueClass; + } + + MapOf.prototype.encodedSize = 8; + + MapOf.prototype.decode = function(decoder) { + return decoder.decodeMapPointer(this.keyClass, this.valueClass); + }; + + MapOf.prototype.encode = function(encoder, val) { + encoder.encodeMapPointer(this.keyClass, this.valueClass, val); + }; + + function NullableMapOf(keyClass, valueClass) { + MapOf.call(this, keyClass, valueClass); + } + + NullableMapOf.prototype = Object.create(MapOf.prototype); + + var exports = {}; + exports.align = align; + exports.isAligned = isAligned; + exports.Message = Message; + exports.MessageBuilder = MessageBuilder; + exports.MessageWithRequestIDBuilder = MessageWithRequestIDBuilder; + exports.MessageReader = MessageReader; + exports.kArrayHeaderSize = kArrayHeaderSize; + exports.kMapStructPayloadSize = kMapStructPayloadSize; + exports.kStructHeaderSize = kStructHeaderSize; + exports.kEncodedInvalidHandleValue = kEncodedInvalidHandleValue; + exports.kMessageHeaderSize = kMessageHeaderSize; + exports.kMessageWithRequestIDHeaderSize = kMessageWithRequestIDHeaderSize; + exports.kMessageExpectsResponse = kMessageExpectsResponse; + exports.kMessageIsResponse = kMessageIsResponse; + exports.Int8 = Int8; + exports.Uint8 = Uint8; + exports.Int16 = Int16; + exports.Uint16 = Uint16; + exports.Int32 = Int32; + exports.Uint32 = Uint32; + exports.Int64 = Int64; + exports.Uint64 = Uint64; + exports.Float = Float; + exports.Double = Double; + exports.String = String; + exports.Enum = Enum; + exports.NullableString = NullableString; + exports.PointerTo = PointerTo; + exports.NullablePointerTo = NullablePointerTo; + exports.ArrayOf = ArrayOf; + exports.NullableArrayOf = NullableArrayOf; + exports.PackedBool = PackedBool; + exports.Handle = Handle; + exports.NullableHandle = NullableHandle; + exports.Interface = Interface; + exports.NullableInterface = NullableInterface; + exports.InterfaceRequest = InterfaceRequest; + exports.NullableInterfaceRequest = NullableInterfaceRequest; + exports.MapOf = MapOf; + exports.NullableMapOf = NullableMapOf; + return exports; +});
diff --git a/mojo/public/js/new_bindings/connector.js b/mojo/public/js/new_bindings/connector.js new file mode 100644 index 0000000..ee16be8 --- /dev/null +++ b/mojo/public/js/new_bindings/connector.js
@@ -0,0 +1,115 @@ +// 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. + +define("mojo/public/js/connector", [ + "mojo/public/js/buffer", + "mojo/public/js/codec", + "mojo/public/js/core", + "mojo/public/js/support", +], function(buffer, codec, core, support) { + + function Connector(handle) { + if (!core.isHandle(handle)) + throw new Error("Connector: not a handle " + handle); + this.handle_ = handle; + this.dropWrites_ = false; + this.error_ = false; + this.incomingReceiver_ = null; + this.readWatcher_ = null; + this.errorHandler_ = null; + + if (handle) { + this.readWatcher_ = support.watch(handle, + core.HANDLE_SIGNAL_READABLE, + this.readMore_.bind(this)); + } + } + + Connector.prototype.close = function() { + if (this.readWatcher_) { + support.cancelWatch(this.readWatcher_); + this.readWatcher_ = null; + } + if (this.handle_ != null) { + core.close(this.handle_); + this.handle_ = null; + } + }; + + Connector.prototype.accept = function(message) { + if (this.error_) + return false; + + if (this.dropWrites_) + return true; + + var result = core.writeMessage(this.handle_, + new Uint8Array(message.buffer.arrayBuffer), + message.handles, + core.WRITE_MESSAGE_FLAG_NONE); + switch (result) { + case core.RESULT_OK: + // The handles were successfully transferred, so we don't own them + // anymore. + message.handles = []; + break; + case core.RESULT_FAILED_PRECONDITION: + // There's no point in continuing to write to this pipe since the other + // end is gone. Avoid writing any future messages. Hide write failures + // from the caller since we'd like them to continue consuming any + // backlog of incoming messages before regarding the message pipe as + // closed. + this.dropWrites_ = true; + break; + default: + // This particular write was rejected, presumably because of bad input. + // The pipe is not necessarily in a bad state. + return false; + } + return true; + }; + + Connector.prototype.setIncomingReceiver = function(receiver) { + this.incomingReceiver_ = receiver; + }; + + Connector.prototype.setErrorHandler = function(handler) { + this.errorHandler_ = handler; + }; + + Connector.prototype.encounteredError = function() { + return this.error_; + }; + + Connector.prototype.waitForNextMessageForTesting = function() { + var wait = core.wait(this.handle_, core.HANDLE_SIGNAL_READABLE, + core.DEADLINE_INDEFINITE); + this.readMore_(wait.result); + }; + + Connector.prototype.readMore_ = function(result) { + for (;;) { + var read = core.readMessage(this.handle_, + core.READ_MESSAGE_FLAG_NONE); + if (this.handle_ == null) // The connector has been closed. + return; + if (read.result == core.RESULT_SHOULD_WAIT) + return; + if (read.result != core.RESULT_OK) { + this.error_ = true; + if (this.errorHandler_) + this.errorHandler_.onError(read.result); + return; + } + var messageBuffer = new buffer.Buffer(read.buffer); + var message = new codec.Message(messageBuffer, read.handles); + if (this.incomingReceiver_) + this.incomingReceiver_.accept(message); + } + }; + + var exports = {}; + exports.Connector = Connector; + return exports; +});
diff --git a/mojo/public/js/new_bindings/interface_types.js b/mojo/public/js/new_bindings/interface_types.js new file mode 100644 index 0000000..01ea2d1 --- /dev/null +++ b/mojo/public/js/new_bindings/interface_types.js
@@ -0,0 +1,52 @@ +// Copyright 2016 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. + +define("mojo/public/js/interface_types", [ + "mojo/public/js/core", +], function(core) { + + // --------------------------------------------------------------------------- + + function InterfacePtrInfo(handle, version) { + this.handle = handle; + this.version = version; + } + + InterfacePtrInfo.prototype.isValid = function() { + return core.isHandle(this.handle); + }; + + InterfacePtrInfo.prototype.close = function() { + if (!this.isValid()) + return; + + core.close(this.handle); + this.handle = null; + this.version = 0; + }; + + // --------------------------------------------------------------------------- + + function InterfaceRequest(handle) { + this.handle = handle; + } + + InterfaceRequest.prototype.isValid = function() { + return core.isHandle(this.handle); + }; + + InterfaceRequest.prototype.close = function() { + if (!this.isValid()) + return; + + core.close(this.handle); + this.handle = null; + }; + + var exports = {}; + exports.InterfacePtrInfo = InterfacePtrInfo; + exports.InterfaceRequest = InterfaceRequest; + + return exports; +});
diff --git a/mojo/public/js/new_bindings/lib/control_message_handler.js b/mojo/public/js/new_bindings/lib/control_message_handler.js new file mode 100644 index 0000000..81d9002 --- /dev/null +++ b/mojo/public/js/new_bindings/lib/control_message_handler.js
@@ -0,0 +1,111 @@ +// Copyright 2017 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. + +define("mojo/public/js/lib/control_message_handler", [ + "mojo/public/js/codec", + "mojo/public/interfaces/bindings/interface_control_messages.mojom", + "mojo/public/js/validator", +], function(codec, controlMessages, validator) { + + var Validator = validator.Validator; + + function validateControlRequestWithResponse(message) { + var messageValidator = new Validator(message); + var error = messageValidator.validateMessageIsRequestExpectingResponse(); + if (error !== validator.validationError.NONE) { + throw error; + } + + if (message.getName() != controlMessages.kRunMessageId) { + throw new Error("Control message name is not kRunMessageId"); + } + + // Validate payload. + error = controlMessages.RunMessageParams.validate(messageValidator, + message.getHeaderNumBytes()); + if (error != validator.validationError.NONE) { + throw error; + } + } + + function validateControlRequestWithoutResponse(message) { + var messageValidator = new Validator(message); + var error = messageValidator.validateMessageIsRequestWithoutResponse(); + if (error != validator.validationError.NONE) { + throw error; + } + + if (message.getName() != controlMessages.kRunOrClosePipeMessageId) { + throw new Error("Control message name is not kRunOrClosePipeMessageId"); + } + + // Validate payload. + error = controlMessages.RunOrClosePipeMessageParams.validate( + messageValidator, message.getHeaderNumBytes()); + if (error != validator.validationError.NONE) { + throw error; + } + } + + function runOrClosePipe(message, interface_version) { + var reader = new codec.MessageReader(message); + var runOrClosePipeMessageParams = reader.decodeStruct( + controlMessages.RunOrClosePipeMessageParams); + return interface_version >= + runOrClosePipeMessageParams.input.require_version.version; + } + + function run(message, responder, interface_version) { + var reader = new codec.MessageReader(message); + var runMessageParams = + reader.decodeStruct(controlMessages.RunMessageParams); + var runOutput = null; + + if (runMessageParams.input.query_version) { + runOutput = new controlMessages.RunOutput(); + runOutput.query_version_result = new + controlMessages.QueryVersionResult({'version': interface_version}); + } + + var runResponseMessageParams = new + controlMessages.RunResponseMessageParams(); + runResponseMessageParams.output = runOutput; + + var messageName = controlMessages.kRunMessageId; + var payloadSize = controlMessages.RunResponseMessageParams.encodedSize; + var requestID = reader.requestID; + var builder = new codec.MessageWithRequestIDBuilder(messageName, + payloadSize, codec.kMessageIsResponse, requestID); + builder.encodeStruct(controlMessages.RunResponseMessageParams, + runResponseMessageParams); + responder.accept(builder.finish()); + return true; + } + + function isControlMessage(message) { + return message.getName() == controlMessages.kRunMessageId || + message.getName() == controlMessages.kRunOrClosePipeMessageId; + } + + function ControlMessageHandler(interface_version) { + this.interface_version = interface_version; + } + + ControlMessageHandler.prototype.accept = function(message) { + validateControlRequestWithoutResponse(message); + return runOrClosePipe(message, this.interface_version); + }; + + ControlMessageHandler.prototype.acceptWithResponder = function(message, + responder) { + validateControlRequestWithResponse(message); + return run(message, responder, this.interface_version); + }; + + var exports = {}; + exports.ControlMessageHandler = ControlMessageHandler; + exports.isControlMessage = isControlMessage; + + return exports; +});
diff --git a/mojo/public/js/new_bindings/lib/control_message_proxy.js b/mojo/public/js/new_bindings/lib/control_message_proxy.js new file mode 100644 index 0000000..d6c0734f --- /dev/null +++ b/mojo/public/js/new_bindings/lib/control_message_proxy.js
@@ -0,0 +1,102 @@ +// Copyright 2017 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. + +define("mojo/public/js/lib/control_message_proxy", [ + "mojo/public/interfaces/bindings/interface_control_messages.mojom", + "mojo/public/js/codec", + "mojo/public/js/validator", +], function(controlMessages, codec, validator) { + + var Validator = validator.Validator; + + function sendRunOrClosePipeMessage(receiver, runOrClosePipeMessageParams) { + var messageName = controlMessages.kRunOrClosePipeMessageId; + var payloadSize = controlMessages.RunOrClosePipeMessageParams.encodedSize; + var builder = new codec.MessageBuilder(messageName, payloadSize); + builder.encodeStruct(controlMessages.RunOrClosePipeMessageParams, + runOrClosePipeMessageParams); + var message = builder.finish(); + receiver.accept(message); + } + + function validateControlResponse(message) { + var messageValidator = new Validator(message); + var error = messageValidator.validateMessageIsResponse(); + if (error != validator.validationError.NONE) { + throw error; + } + + if (message.getName() != controlMessages.kRunMessageId) { + throw new Error("Control message name is not kRunMessageId"); + } + + // Validate payload. + error = controlMessages.RunResponseMessageParams.validate( + messageValidator, message.getHeaderNumBytes()); + if (error != validator.validationError.NONE) { + throw error; + } + } + + function acceptRunResponse(message) { + validateControlResponse(message); + + var reader = new codec.MessageReader(message); + var runResponseMessageParams = reader.decodeStruct( + controlMessages.RunResponseMessageParams); + + return Promise.resolve(runResponseMessageParams); + } + + /** + * Sends the given run message through the receiver. + * Accepts the response message from the receiver and decodes the message + * struct to RunResponseMessageParams. + * + * @param {Router} receiver. + * @param {RunMessageParams} runMessageParams to be sent via a message. + * @return {Promise} that resolves to a RunResponseMessageParams. + */ + function sendRunMessage(receiver, runMessageParams) { + var messageName = controlMessages.kRunMessageId; + var payloadSize = controlMessages.RunMessageParams.encodedSize; + // |requestID| is set to 0, but is later properly set by Router. + var builder = new codec.MessageWithRequestIDBuilder(messageName, + payloadSize, codec.kMessageExpectsResponse, 0); + builder.encodeStruct(controlMessages.RunMessageParams, runMessageParams); + var message = builder.finish(); + + return receiver.acceptAndExpectResponse(message).then(acceptRunResponse); + } + + function ControlMessageProxy(receiver) { + this.receiver = receiver; + } + + ControlMessageProxy.prototype.queryVersion = function() { + var runMessageParams = new controlMessages.RunMessageParams(); + runMessageParams.input = new controlMessages.RunInput(); + runMessageParams.input.query_version = new controlMessages.QueryVersion(); + + return sendRunMessage(this.receiver, runMessageParams).then(function( + runResponseMessageParams) { + return runResponseMessageParams.output.query_version_result.version; + }); + }; + + ControlMessageProxy.prototype.requireVersion = function(version) { + var runOrClosePipeMessageParams = new + controlMessages.RunOrClosePipeMessageParams(); + runOrClosePipeMessageParams.input = new + controlMessages.RunOrClosePipeInput(); + runOrClosePipeMessageParams.input.require_version = new + controlMessages.RequireVersion({'version': version}); + sendRunOrClosePipeMessage(this.receiver, runOrClosePipeMessageParams); + }; + + var exports = {}; + exports.ControlMessageProxy = ControlMessageProxy; + + return exports; +});
diff --git a/mojo/public/js/new_bindings/router.js b/mojo/public/js/new_bindings/router.js new file mode 100644 index 0000000..e94c5eb --- /dev/null +++ b/mojo/public/js/new_bindings/router.js
@@ -0,0 +1,203 @@ +// 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. + +define("mojo/public/js/router", [ + "console", + "mojo/public/js/codec", + "mojo/public/js/core", + "mojo/public/js/connector", + "mojo/public/js/lib/control_message_handler", + "mojo/public/js/validator", +], function(console, codec, core, connector, controlMessageHandler, validator) { + + var Connector = connector.Connector; + var MessageReader = codec.MessageReader; + var Validator = validator.Validator; + var ControlMessageHandler = controlMessageHandler.ControlMessageHandler; + + function Router(handle, interface_version, connectorFactory) { + if (!core.isHandle(handle)) + throw new Error("Router constructor: Not a handle"); + if (connectorFactory === undefined) + connectorFactory = Connector; + this.connector_ = new connectorFactory(handle); + this.incomingReceiver_ = null; + this.errorHandler_ = null; + this.nextRequestID_ = 0; + this.completers_ = new Map(); + this.payloadValidators_ = []; + this.testingController_ = null; + + if (interface_version !== undefined) { + this.controlMessageHandler_ = new + ControlMessageHandler(interface_version); + } + + this.connector_.setIncomingReceiver({ + accept: this.handleIncomingMessage_.bind(this), + }); + this.connector_.setErrorHandler({ + onError: this.handleConnectionError_.bind(this), + }); + } + + Router.prototype.close = function() { + this.completers_.clear(); // Drop any responders. + this.connector_.close(); + this.testingController_ = null; + }; + + Router.prototype.accept = function(message) { + this.connector_.accept(message); + }; + + Router.prototype.reject = function(message) { + // TODO(mpcomplete): no way to trasmit errors over a Connection. + }; + + Router.prototype.acceptAndExpectResponse = function(message) { + // Reserve 0 in case we want it to convey special meaning in the future. + var requestID = this.nextRequestID_++; + if (requestID == 0) + requestID = this.nextRequestID_++; + + message.setRequestID(requestID); + var result = this.connector_.accept(message); + if (!result) + return Promise.reject(Error("Connection error")); + + var completer = {}; + this.completers_.set(requestID, completer); + return new Promise(function(resolve, reject) { + completer.resolve = resolve; + completer.reject = reject; + }); + }; + + Router.prototype.setIncomingReceiver = function(receiver) { + this.incomingReceiver_ = receiver; + }; + + Router.prototype.setPayloadValidators = function(payloadValidators) { + this.payloadValidators_ = payloadValidators; + }; + + Router.prototype.setErrorHandler = function(handler) { + this.errorHandler_ = handler; + }; + + Router.prototype.encounteredError = function() { + return this.connector_.encounteredError(); + }; + + Router.prototype.enableTestingMode = function() { + this.testingController_ = new RouterTestingController(this.connector_); + return this.testingController_; + }; + + Router.prototype.handleIncomingMessage_ = function(message) { + var noError = validator.validationError.NONE; + var messageValidator = new Validator(message); + var err = messageValidator.validateMessageHeader(); + for (var i = 0; err === noError && i < this.payloadValidators_.length; ++i) + err = this.payloadValidators_[i](messageValidator); + + if (err == noError) + this.handleValidIncomingMessage_(message); + else + this.handleInvalidIncomingMessage_(message, err); + }; + + Router.prototype.handleValidIncomingMessage_ = function(message) { + if (this.testingController_) + return; + + if (message.expectsResponse()) { + if (controlMessageHandler.isControlMessage(message)) { + if (this.controlMessageHandler_) { + this.controlMessageHandler_.acceptWithResponder(message, this); + } else { + this.close(); + } + } else if (this.incomingReceiver_) { + this.incomingReceiver_.acceptWithResponder(message, this); + } else { + // If we receive a request expecting a response when the client is not + // listening, then we have no choice but to tear down the pipe. + this.close(); + } + } else if (message.isResponse()) { + var reader = new MessageReader(message); + var requestID = reader.requestID; + var completer = this.completers_.get(requestID); + if (completer) { + this.completers_.delete(requestID); + completer.resolve(message); + } else { + console.log("Unexpected response with request ID: " + requestID); + } + } else { + if (controlMessageHandler.isControlMessage(message)) { + if (this.controlMessageHandler_) { + var ok = this.controlMessageHandler_.accept(message); + if (ok) return; + } + this.close(); + } else if (this.incomingReceiver_) { + this.incomingReceiver_.accept(message); + } + } + }; + + Router.prototype.handleInvalidIncomingMessage_ = function(message, error) { + if (!this.testingController_) { + // TODO(yzshen): Consider notifying the embedder. + // TODO(yzshen): This should also trigger connection error handler. + // Consider making accept() return a boolean and let the connector deal + // with this, as the C++ code does. + console.log("Invalid message: " + validator.validationError[error]); + + this.close(); + return; + } + + this.testingController_.onInvalidIncomingMessage(error); + }; + + Router.prototype.handleConnectionError_ = function(result) { + this.completers_.forEach(function(value) { + value.reject(result); + }); + if (this.errorHandler_) + this.errorHandler_(); + this.close(); + }; + + // The RouterTestingController is used in unit tests. It defeats valid message + // handling and delgates invalid message handling. + + function RouterTestingController(connector) { + this.connector_ = connector; + this.invalidMessageHandler_ = null; + } + + RouterTestingController.prototype.waitForNextMessage = function() { + this.connector_.waitForNextMessageForTesting(); + }; + + RouterTestingController.prototype.setInvalidIncomingMessageHandler = + function(callback) { + this.invalidMessageHandler_ = callback; + }; + + RouterTestingController.prototype.onInvalidIncomingMessage = + function(error) { + if (this.invalidMessageHandler_) + this.invalidMessageHandler_(error); + }; + + var exports = {}; + exports.Router = Router; + return exports; +});
diff --git a/mojo/public/js/new_bindings/unicode.js b/mojo/public/js/new_bindings/unicode.js new file mode 100644 index 0000000..be2ba0e --- /dev/null +++ b/mojo/public/js/new_bindings/unicode.js
@@ -0,0 +1,51 @@ +// 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. + +/** + * Defines functions for translating between JavaScript strings and UTF8 strings + * stored in ArrayBuffers. There is much room for optimization in this code if + * it proves necessary. + */ +define("mojo/public/js/unicode", function() { + /** + * Decodes the UTF8 string from the given buffer. + * @param {ArrayBufferView} buffer The buffer containing UTF8 string data. + * @return {string} The corresponding JavaScript string. + */ + function decodeUtf8String(buffer) { + return decodeURIComponent(escape(String.fromCharCode.apply(null, buffer))); + } + + /** + * Encodes the given JavaScript string into UTF8. + * @param {string} str The string to encode. + * @param {ArrayBufferView} outputBuffer The buffer to contain the result. + * Should be pre-allocated to hold enough space. Use |utf8Length| to determine + * how much space is required. + * @return {number} The number of bytes written to |outputBuffer|. + */ + function encodeUtf8String(str, outputBuffer) { + var utf8String = unescape(encodeURIComponent(str)); + if (outputBuffer.length < utf8String.length) + throw new Error("Buffer too small for encodeUtf8String"); + for (var i = 0; i < outputBuffer.length && i < utf8String.length; i++) + outputBuffer[i] = utf8String.charCodeAt(i); + return i; + } + + /** + * Returns the number of bytes that a UTF8 encoding of the JavaScript string + * |str| would occupy. + */ + function utf8Length(str) { + var utf8String = unescape(encodeURIComponent(str)); + return utf8String.length; + } + + var exports = {}; + exports.decodeUtf8String = decodeUtf8String; + exports.encodeUtf8String = encodeUtf8String; + exports.utf8Length = utf8Length; + return exports; +});
diff --git a/mojo/public/js/new_bindings/validator.js b/mojo/public/js/new_bindings/validator.js new file mode 100644 index 0000000..fee742d0 --- /dev/null +++ b/mojo/public/js/new_bindings/validator.js
@@ -0,0 +1,512 @@ +// 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. + +define("mojo/public/js/validator", [ + "mojo/public/js/codec", +], function(codec) { + + var validationError = { + NONE: 'VALIDATION_ERROR_NONE', + MISALIGNED_OBJECT: 'VALIDATION_ERROR_MISALIGNED_OBJECT', + ILLEGAL_MEMORY_RANGE: 'VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE', + UNEXPECTED_STRUCT_HEADER: 'VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER', + UNEXPECTED_ARRAY_HEADER: 'VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER', + ILLEGAL_HANDLE: 'VALIDATION_ERROR_ILLEGAL_HANDLE', + UNEXPECTED_INVALID_HANDLE: 'VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE', + ILLEGAL_POINTER: 'VALIDATION_ERROR_ILLEGAL_POINTER', + UNEXPECTED_NULL_POINTER: 'VALIDATION_ERROR_UNEXPECTED_NULL_POINTER', + MESSAGE_HEADER_INVALID_FLAGS: + 'VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS', + MESSAGE_HEADER_MISSING_REQUEST_ID: + 'VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID', + DIFFERENT_SIZED_ARRAYS_IN_MAP: + 'VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP', + INVALID_UNION_SIZE: 'VALIDATION_ERROR_INVALID_UNION_SIZE', + UNEXPECTED_NULL_UNION: 'VALIDATION_ERROR_UNEXPECTED_NULL_UNION', + UNKNOWN_ENUM_VALUE: 'VALIDATION_ERROR_UNKNOWN_ENUM_VALUE', + }; + + var NULL_MOJO_POINTER = "NULL_MOJO_POINTER"; + + function isEnumClass(cls) { + return cls instanceof codec.Enum; + } + + function isStringClass(cls) { + return cls === codec.String || cls === codec.NullableString; + } + + function isHandleClass(cls) { + return cls === codec.Handle || cls === codec.NullableHandle; + } + + function isInterfaceClass(cls) { + return cls instanceof codec.Interface; + } + + function isInterfaceRequestClass(cls) { + return cls === codec.InterfaceRequest || + cls === codec.NullableInterfaceRequest; + } + + function isNullable(type) { + return type === codec.NullableString || type === codec.NullableHandle || + type === codec.NullableInterface || + type === codec.NullableInterfaceRequest || + type instanceof codec.NullableArrayOf || + type instanceof codec.NullablePointerTo; + } + + function Validator(message) { + this.message = message; + this.offset = 0; + this.handleIndex = 0; + } + + Object.defineProperty(Validator.prototype, "offsetLimit", { + get: function() { return this.message.buffer.byteLength; } + }); + + Object.defineProperty(Validator.prototype, "handleIndexLimit", { + get: function() { return this.message.handles.length; } + }); + + // True if we can safely allocate a block of bytes from start to + // to start + numBytes. + Validator.prototype.isValidRange = function(start, numBytes) { + // Only positive JavaScript integers that are less than 2^53 + // (Number.MAX_SAFE_INTEGER) can be represented exactly. + if (start < this.offset || numBytes <= 0 || + !Number.isSafeInteger(start) || + !Number.isSafeInteger(numBytes)) + return false; + + var newOffset = start + numBytes; + if (!Number.isSafeInteger(newOffset) || newOffset > this.offsetLimit) + return false; + + return true; + }; + + Validator.prototype.claimRange = function(start, numBytes) { + if (this.isValidRange(start, numBytes)) { + this.offset = start + numBytes; + return true; + } + return false; + }; + + Validator.prototype.claimHandle = function(index) { + if (index === codec.kEncodedInvalidHandleValue) + return true; + + if (index < this.handleIndex || index >= this.handleIndexLimit) + return false; + + // This is safe because handle indices are uint32. + this.handleIndex = index + 1; + return true; + }; + + Validator.prototype.validateEnum = function(offset, enumClass) { + // Note: Assumes that enums are always 32 bits! But this matches + // mojom::generate::pack::PackedField::GetSizeForKind, so it should be okay. + var value = this.message.buffer.getInt32(offset); + return enumClass.validate(value); + } + + Validator.prototype.validateHandle = function(offset, nullable) { + var index = this.message.buffer.getUint32(offset); + + if (index === codec.kEncodedInvalidHandleValue) + return nullable ? + validationError.NONE : validationError.UNEXPECTED_INVALID_HANDLE; + + if (!this.claimHandle(index)) + return validationError.ILLEGAL_HANDLE; + + return validationError.NONE; + }; + + Validator.prototype.validateInterface = function(offset, nullable) { + return this.validateHandle(offset, nullable); + }; + + Validator.prototype.validateInterfaceRequest = function(offset, nullable) { + return this.validateHandle(offset, nullable); + }; + + Validator.prototype.validateStructHeader = function(offset, minNumBytes) { + if (!codec.isAligned(offset)) + return validationError.MISALIGNED_OBJECT; + + if (!this.isValidRange(offset, codec.kStructHeaderSize)) + return validationError.ILLEGAL_MEMORY_RANGE; + + var numBytes = this.message.buffer.getUint32(offset); + + if (numBytes < minNumBytes) + return validationError.UNEXPECTED_STRUCT_HEADER; + + if (!this.claimRange(offset, numBytes)) + return validationError.ILLEGAL_MEMORY_RANGE; + + return validationError.NONE; + }; + + Validator.prototype.validateStructVersion = function(offset, versionSizes) { + var numBytes = this.message.buffer.getUint32(offset); + var version = this.message.buffer.getUint32(offset + 4); + + if (version <= versionSizes[versionSizes.length - 1].version) { + // Scan in reverse order to optimize for more recent versionSizes. + for (var i = versionSizes.length - 1; i >= 0; --i) { + if (version >= versionSizes[i].version) { + if (numBytes == versionSizes[i].numBytes) + break; + return validationError.UNEXPECTED_STRUCT_HEADER; + } + } + } else if (numBytes < versionSizes[versionSizes.length-1].numBytes) { + return validationError.UNEXPECTED_STRUCT_HEADER; + } + + return validationError.NONE; + }; + + Validator.prototype.isFieldInStructVersion = function(offset, fieldVersion) { + var structVersion = this.message.buffer.getUint32(offset + 4); + return fieldVersion <= structVersion; + }; + + Validator.prototype.validateMessageHeader = function() { + + var err = this.validateStructHeader(0, codec.kMessageHeaderSize); + if (err != validationError.NONE) + return err; + + var numBytes = this.message.getHeaderNumBytes(); + var version = this.message.getHeaderVersion(); + + var validVersionAndNumBytes = + (version == 0 && numBytes == codec.kMessageHeaderSize) || + (version == 1 && + numBytes == codec.kMessageWithRequestIDHeaderSize) || + (version > 1 && + numBytes >= codec.kMessageWithRequestIDHeaderSize); + if (!validVersionAndNumBytes) + return validationError.UNEXPECTED_STRUCT_HEADER; + + var expectsResponse = this.message.expectsResponse(); + var isResponse = this.message.isResponse(); + + if (version == 0 && (expectsResponse || isResponse)) + return validationError.MESSAGE_HEADER_MISSING_REQUEST_ID; + + if (isResponse && expectsResponse) + return validationError.MESSAGE_HEADER_INVALID_FLAGS; + + return validationError.NONE; + }; + + Validator.prototype.validateMessageIsRequestWithoutResponse = function() { + if (this.message.isResponse() || this.message.expectsResponse()) { + return validationError.MESSAGE_HEADER_INVALID_FLAGS; + } + return validationError.NONE; + }; + + Validator.prototype.validateMessageIsRequestExpectingResponse = function() { + if (this.message.isResponse() || !this.message.expectsResponse()) { + return validationError.MESSAGE_HEADER_INVALID_FLAGS; + } + return validationError.NONE; + }; + + Validator.prototype.validateMessageIsResponse = function() { + if (this.message.expectsResponse() || !this.message.isResponse()) { + return validationError.MESSAGE_HEADER_INVALID_FLAGS; + } + return validationError.NONE; + }; + + // Returns the message.buffer relative offset this pointer "points to", + // NULL_MOJO_POINTER if the pointer represents a null, or JS null if the + // pointer's value is not valid. + Validator.prototype.decodePointer = function(offset) { + var pointerValue = this.message.buffer.getUint64(offset); + if (pointerValue === 0) + return NULL_MOJO_POINTER; + var bufferOffset = offset + pointerValue; + return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; + }; + + Validator.prototype.decodeUnionSize = function(offset) { + return this.message.buffer.getUint32(offset); + }; + + Validator.prototype.decodeUnionTag = function(offset) { + return this.message.buffer.getUint32(offset + 4); + }; + + Validator.prototype.validateArrayPointer = function( + offset, elementSize, elementType, nullable, expectedDimensionSizes, + currentDimension) { + var arrayOffset = this.decodePointer(offset); + if (arrayOffset === null) + return validationError.ILLEGAL_POINTER; + + if (arrayOffset === NULL_MOJO_POINTER) + return nullable ? + validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; + + return this.validateArray(arrayOffset, elementSize, elementType, + expectedDimensionSizes, currentDimension); + }; + + Validator.prototype.validateStructPointer = function( + offset, structClass, nullable) { + var structOffset = this.decodePointer(offset); + if (structOffset === null) + return validationError.ILLEGAL_POINTER; + + if (structOffset === NULL_MOJO_POINTER) + return nullable ? + validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; + + return structClass.validate(this, structOffset); + }; + + Validator.prototype.validateUnion = function( + offset, unionClass, nullable) { + var size = this.message.buffer.getUint32(offset); + if (size == 0) { + return nullable ? + validationError.NONE : validationError.UNEXPECTED_NULL_UNION; + } + + return unionClass.validate(this, offset); + }; + + Validator.prototype.validateNestedUnion = function( + offset, unionClass, nullable) { + var unionOffset = this.decodePointer(offset); + if (unionOffset === null) + return validationError.ILLEGAL_POINTER; + + if (unionOffset === NULL_MOJO_POINTER) + return nullable ? + validationError.NONE : validationError.UNEXPECTED_NULL_UNION; + + return this.validateUnion(unionOffset, unionClass, nullable); + }; + + // This method assumes that the array at arrayPointerOffset has + // been validated. + + Validator.prototype.arrayLength = function(arrayPointerOffset) { + var arrayOffset = this.decodePointer(arrayPointerOffset); + return this.message.buffer.getUint32(arrayOffset + 4); + }; + + Validator.prototype.validateMapPointer = function( + offset, mapIsNullable, keyClass, valueClass, valueIsNullable) { + // Validate the implicit map struct: + // struct {array<keyClass> keys; array<valueClass> values}; + var structOffset = this.decodePointer(offset); + if (structOffset === null) + return validationError.ILLEGAL_POINTER; + + if (structOffset === NULL_MOJO_POINTER) + return mapIsNullable ? + validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; + + var mapEncodedSize = codec.kStructHeaderSize + codec.kMapStructPayloadSize; + var err = this.validateStructHeader(structOffset, mapEncodedSize); + if (err !== validationError.NONE) + return err; + + // Validate the keys array. + var keysArrayPointerOffset = structOffset + codec.kStructHeaderSize; + err = this.validateArrayPointer( + keysArrayPointerOffset, keyClass.encodedSize, keyClass, false, [0], 0); + if (err !== validationError.NONE) + return err; + + // Validate the values array. + var valuesArrayPointerOffset = keysArrayPointerOffset + 8; + var valuesArrayDimensions = [0]; // Validate the actual length below. + if (valueClass instanceof codec.ArrayOf) + valuesArrayDimensions = + valuesArrayDimensions.concat(valueClass.dimensions()); + var err = this.validateArrayPointer(valuesArrayPointerOffset, + valueClass.encodedSize, + valueClass, + valueIsNullable, + valuesArrayDimensions, + 0); + if (err !== validationError.NONE) + return err; + + // Validate the lengths of the keys and values arrays. + var keysArrayLength = this.arrayLength(keysArrayPointerOffset); + var valuesArrayLength = this.arrayLength(valuesArrayPointerOffset); + if (keysArrayLength != valuesArrayLength) + return validationError.DIFFERENT_SIZED_ARRAYS_IN_MAP; + + return validationError.NONE; + }; + + Validator.prototype.validateStringPointer = function(offset, nullable) { + return this.validateArrayPointer( + offset, codec.Uint8.encodedSize, codec.Uint8, nullable, [0], 0); + }; + + // Similar to Array_Data<T>::Validate() + // mojo/public/cpp/bindings/lib/array_internal.h + + Validator.prototype.validateArray = + function (offset, elementSize, elementType, expectedDimensionSizes, + currentDimension) { + if (!codec.isAligned(offset)) + return validationError.MISALIGNED_OBJECT; + + if (!this.isValidRange(offset, codec.kArrayHeaderSize)) + return validationError.ILLEGAL_MEMORY_RANGE; + + var numBytes = this.message.buffer.getUint32(offset); + var numElements = this.message.buffer.getUint32(offset + 4); + + // Note: this computation is "safe" because elementSize <= 8 and + // numElements is a uint32. + var elementsTotalSize = (elementType === codec.PackedBool) ? + Math.ceil(numElements / 8) : (elementSize * numElements); + + if (numBytes < codec.kArrayHeaderSize + elementsTotalSize) + return validationError.UNEXPECTED_ARRAY_HEADER; + + if (expectedDimensionSizes[currentDimension] != 0 && + numElements != expectedDimensionSizes[currentDimension]) { + return validationError.UNEXPECTED_ARRAY_HEADER; + } + + if (!this.claimRange(offset, numBytes)) + return validationError.ILLEGAL_MEMORY_RANGE; + + // Validate the array's elements if they are pointers or handles. + + var elementsOffset = offset + codec.kArrayHeaderSize; + var nullable = isNullable(elementType); + + if (isHandleClass(elementType)) + return this.validateHandleElements(elementsOffset, numElements, nullable); + if (isInterfaceClass(elementType)) + return this.validateInterfaceElements( + elementsOffset, numElements, nullable); + if (isInterfaceRequestClass(elementType)) + return this.validateInterfaceRequestElements( + elementsOffset, numElements, nullable); + if (isStringClass(elementType)) + return this.validateArrayElements( + elementsOffset, numElements, codec.Uint8, nullable, [0], 0); + if (elementType instanceof codec.PointerTo) + return this.validateStructElements( + elementsOffset, numElements, elementType.cls, nullable); + if (elementType instanceof codec.ArrayOf) + return this.validateArrayElements( + elementsOffset, numElements, elementType.cls, nullable, + expectedDimensionSizes, currentDimension + 1); + if (isEnumClass(elementType)) + return this.validateEnumElements(elementsOffset, numElements, + elementType.cls); + + return validationError.NONE; + }; + + // Note: the |offset + i * elementSize| computation in the validateFooElements + // methods below is "safe" because elementSize <= 8, offset and + // numElements are uint32, and 0 <= i < numElements. + + Validator.prototype.validateHandleElements = + function(offset, numElements, nullable) { + var elementSize = codec.Handle.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = this.validateHandle(elementOffset, nullable); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + Validator.prototype.validateInterfaceElements = + function(offset, numElements, nullable) { + var elementSize = codec.Interface.prototype.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = this.validateInterface(elementOffset, nullable); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + Validator.prototype.validateInterfaceRequestElements = + function(offset, numElements, nullable) { + var elementSize = codec.InterfaceRequest.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = this.validateInterfaceRequest(elementOffset, nullable); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + // The elementClass parameter is the element type of the element arrays. + Validator.prototype.validateArrayElements = + function(offset, numElements, elementClass, nullable, + expectedDimensionSizes, currentDimension) { + var elementSize = codec.PointerTo.prototype.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = this.validateArrayPointer( + elementOffset, elementClass.encodedSize, elementClass, nullable, + expectedDimensionSizes, currentDimension); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + Validator.prototype.validateStructElements = + function(offset, numElements, structClass, nullable) { + var elementSize = codec.PointerTo.prototype.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = + this.validateStructPointer(elementOffset, structClass, nullable); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + Validator.prototype.validateEnumElements = + function(offset, numElements, enumClass) { + var elementSize = codec.Enum.prototype.encodedSize; + for (var i = 0; i < numElements; i++) { + var elementOffset = offset + i * elementSize; + var err = this.validateEnum(elementOffset, enumClass); + if (err != validationError.NONE) + return err; + } + return validationError.NONE; + }; + + var exports = {}; + exports.validationError = validationError; + exports.Validator = Validator; + return exports; +});
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index de1a7c1..eb778132 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -272,18 +272,11 @@ return; } - CertificateList certs = - CreateCertificateListFromFile(GetTestCertsDirectory(), "comodo.chain.pem", - X509Certificate::FORMAT_PEM_CERT_SEQUENCE); - ASSERT_EQ(3U, certs.size()); - - X509Certificate::OSCertHandles intermediates; - intermediates.push_back(certs[1]->os_cert_handle()); - intermediates.push_back(certs[2]->os_cert_handle()); - - scoped_refptr<X509Certificate> comodo_chain = - X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), - intermediates); + scoped_refptr<X509Certificate> comodo_chain = CreateCertificateChainFromFile( + GetTestCertsDirectory(), "comodo.chain.pem", + X509Certificate::FORMAT_PEM_CERT_SEQUENCE); + ASSERT_TRUE(comodo_chain); + ASSERT_EQ(2U, comodo_chain->GetIntermediateCertificates().size()); scoped_refptr<CRLSet> crl_set(CRLSet::ForTesting(false, NULL, "")); CertVerifyResult verify_result; @@ -383,13 +376,10 @@ ScopedTestRoot test_root( ImportCertFromFile(certs_dir, "root_ca_cert.pem").get()); - CertificateList certs = CreateCertificateListFromFile( + scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile( certs_dir, "expired_cert.pem", X509Certificate::FORMAT_AUTO); - ASSERT_EQ(1U, certs.size()); - - X509Certificate::OSCertHandles intermediates; - scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( - certs[0]->os_cert_handle(), intermediates); + ASSERT_TRUE(cert); + ASSERT_EQ(0U, cert->GetIntermediateCertificates().size()); int flags = 0; CertVerifyResult verify_result; @@ -612,14 +602,11 @@ ASSERT_EQ(1U, ca_cert_list.size()); ScopedTestRoot test_root(ca_cert_list[0].get()); - CertificateList cert_list = CreateCertificateListFromFile( + scoped_refptr<X509Certificate> leaf = CreateCertificateChainFromFile( GetTestCertsDirectory(), "name_constraint_good.pem", X509Certificate::FORMAT_AUTO); - ASSERT_EQ(1U, cert_list.size()); - - X509Certificate::OSCertHandles intermediates; - scoped_refptr<X509Certificate> leaf = X509Certificate::CreateFromHandle( - cert_list[0]->os_cert_handle(), intermediates); + ASSERT_TRUE(leaf); + ASSERT_EQ(0U, leaf->GetIntermediateCertificates().size()); int flags = 0; CertVerifyResult verify_result;
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index eb05205..e0ec323 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -122,12 +122,6 @@ crbug.com/659192 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality-pixel.html [ NeedsManualRebaseline ] -# https://skia-review.googlesource.com/c/9341 -crbug.com/699098 fast/replaced/border-radius-clip-content-edge.html [ NeedsManualRebaseline ] -crbug.com/699098 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png.html [ NeedsManualRebaseline ] -crbug.com/699098 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ NeedsManualRebaseline ] -crbug.com/699098 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ NeedsManualRebaseline ] - crbug.com/664850 virtual/display_list_2d_canvas/fast/canvas/canvas-createImageBitmap-webgl.html [ Pass Failure ] crbug.com/664850 virtual/display_list_2d_canvas/fast/canvas/OffscreenCanvas-2d-drawImage.html [ Pass Failure ] crbug.com/664850 virtual/display_list_2d_canvas/fast/canvas/OffscreenCanvas-commit-invalid-call.html [ Pass Failure ] @@ -1822,6 +1816,7 @@ crbug.com/695270 [ Linux ] external/csswg-test/css-writing-modes-3/overconstrained-rel-pos-rtl-top-bottom-vrl-006.xht [ Failure ] # ====== New tests from w3c-test-autoroller added here ====== +crbug.com/626703 [ Android Win10 ] external/wpt/fullscreen/api/document-exit-fullscreen-nested-in-iframe-manual.html [ Timeout ] crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Timeout ] crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html [ Timeout ] crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08-expected.txt b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08-expected.txt deleted file mode 100644 index 00fe9a26..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ -Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodelookupnamespaceuri08 -Status Success
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.js b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.js deleted file mode 100644 index 14334b6..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.js +++ /dev/null
@@ -1,107 +0,0 @@ -/* -Copyright © 2001-2004 World Wide Web Consortium, -(Massachusetts Institute of Technology, European Research Consortium -for Informatics and Mathematics, Keio University). All -Rights Reserved. This work is distributed under the W3C® Software License [1] in the -hope that it will be useful, but WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 -*/ - - /** - * Gets URI that identifies the test. - * @return uri identifier of test - */ -function getTargetURI() { - return "http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodelookupnamespaceuri08"; - } - -var docsLoaded = -1000000; -var builder = null; - -// -// This function is called by the testing framework before -// running the test suite. -// -// If there are no configuration exceptions, asynchronous -// document loading is started. Otherwise, the status -// is set to complete and the exception is immediately -// raised when entering the body of the test. -// -function setUpPage() { - setUpPageStatus = 'running'; - try { - // - // creates test document builder, may throw exception - // - builder = createConfiguredBuilder(); - setImplementationAttribute("namespaceAware", true); - - docsLoaded = 0; - - var docRef = null; - if (typeof(this.doc) != 'undefined') { - docRef = this.doc; - } - docsLoaded += preload(docRef, "doc", "hc_staff"); - - if (docsLoaded == 1) { - setUpPageStatus = 'complete'; - } - } catch(ex) { - catchInitializationError(builder, ex); - setUpPageStatus = 'complete'; - } -} - -// -// This method is called on the completion of -// each asychronous load started in setUpTests. -// -// When every synchronous loaded document has completed, -// the page status is changed which allows the -// body of the test to be executed. -function loadComplete() { - if (++docsLoaded == 1) { - setUpPageStatus = 'complete'; - } -} - -/** -* - Invoke lookupNamespaceURI on an Element node with no prefix, which has 2 namespace - attribute declarations with and without namespace prefixes and check if the value of the prefix - returned by using a valid prefix and an empty prefix as a parameter is a valid - namespaceURI or null. - -* @author IBM -* @author Neil Delima -* @see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core#Node3-lookupNamespaceURI -*/ -function nodelookupnamespaceuri08() { - var success; - if(checkInitialization(builder, "nodelookupnamespaceuri08") != null) return; - var doc; - var elem; - var elemList; - var namespaceURI; - var namespaceURIEmpty; - - var docRef = null; - if (typeof(this.doc) != 'undefined') { - docRef = this.doc; - } - doc = load(docRef, "doc", "hc_staff"); - elemList = doc.getElementsByTagName("p"); - elem = elemList.item(0); - namespaceURI = elem.lookupNamespaceURI("dmstc"); - assertEquals("nodelookupnamespaceuri08","http://www.usa.com",namespaceURI); - namespaceURIEmpty = elem.lookupNamespaceURI(""); - assertNull("nodelookupnamespaceprefixEmpty08",namespaceURIEmpty); - -} - -function runTest() { - nodelookupnamespaceuri08(); -}
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.xhtml b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.xhtml deleted file mode 100644 index 1189bc7..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri08.xhtml +++ /dev/null
@@ -1,73 +0,0 @@ -<?xml version="1.0"?><?TEST-STYLE PIDATA?> -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "xhtml1-strict.dtd" [ - <!ENTITY alpha "α"> - <!ENTITY beta "β"> - <!ENTITY gamma "γ"> - <!ENTITY delta "δ"> - <!ENTITY epsilon "ε"> - <!ENTITY alpha "ζ"> - <!NOTATION notation1 PUBLIC "notation1File"> - <!NOTATION notation2 SYSTEM "notation2File"> - <!ATTLIST p - dir CDATA 'rtl' - xmlns:dmstc CDATA #IMPLIED - xmlns:nm CDATA #IMPLIED - xmlns:emp2 CDATA #IMPLIED> - <!ATTLIST html - xmlns:xsi CDATA #IMPLIED - xsi:schemaLocation CDATA #IMPLIED> - <!ATTLIST acronym xsi:noNamespaceSchemaLocation CDATA #IMPLIED> - <!ENTITY ent4 "<span xmlns='http://www.w3.org/1999/xhtml'>Element data</span><?PItarget PIdata?>"> - <!ATTLIST span xmlns CDATA #IMPLIED> -]> -<!-- This is comment number 1.--> -<html xmlns='http://www.w3.org/1999/xhtml' - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.w3.org/1999/xhtml hc_staff.xsd"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>hc_staff</title><script type="text/javascript" src="selfxhtml.js"/><script charset="UTF-8" type="text/javascript" src="nodelookupnamespaceuri08.js"/><script type='text/javascript'>function loadComplete() { startTest(); }</script></head><body onload="loadComplete()"> - <p xmlns:dmstc="http://www.usa.com"> - <em>EMP0001</em> - <strong>Margaret Martin</strong> - <code>Accountant</code> - <sup>56,000</sup> - <var>Female</var> - <acronym title="Yes" xsi:noNamespaceSchemaLocation="Yes">1230 North Ave. Dallas, Texas 98551</acronym> - </p> - <p xmlns:dmstc="http://www.usa.com"> - <em>EMP0002</em> - <strong>Martha Raynolds -<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> -<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></strong> - <code>Secretary</code> - <sup>35,000</sup> - <var>Female</var> - <acronym title="Yes" class="Yes" xsi:noNamespaceSchemaLocation="Yes">β Dallas, γ - 98554</acronym> - </p> - <p xmlns:dmstc="http://www.netzero.com"> - <em>EMP0003</em> - <strong>Roger - Jones</strong> - <code>Department Manager</code> - <sup>100,000</sup> - <var>&ent4;</var> - <acronym title="Yes" class="No" id="_98553" xsi:noNamespaceSchemaLocation="Yes">PO Box 27 Irving, texas 98553</acronym> - </p> - <p xmlns:nm="http://www.altavista.com"> - <em>EMP0004</em> - <strong>Jeny Oconnor</strong> - <code>Personnel Director</code> - <sup>95,000</sup> - <var>Female</var> - <acronym title="Yes" class="Yα" id="_98556" xsi:noNamespaceSchemaLocation="Yes">27 South Road. Dallas, Texas 98556</acronym> - </p> - <p xmlns:emp2="http://www.nist.gov"> - <em>EMP0005</em> - <strong>Robert Myers</strong> - <code>Computer Specialist</code> - <sup>90,000</sup> - <var>male</var> - <acronym title="Yes" class="Yes" xsi:noNamespaceSchemaLocation="Yes">1821 Nordic. Road, Irving Texas 98558</acronym> - </p> -</body></html>
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09-expected.txt b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09-expected.txt deleted file mode 100644 index b3bf1a16..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ -Test http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodelookupnamespaceuri09 -Status Success
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.js b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.js deleted file mode 100644 index 7d50d9d..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.js +++ /dev/null
@@ -1,106 +0,0 @@ -/* -Copyright © 2001-2004 World Wide Web Consortium, -(Massachusetts Institute of Technology, European Research Consortium -for Informatics and Mathematics, Keio University). All -Rights Reserved. This work is distributed under the W3C® Software License [1] in the -hope that it will be useful, but WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 -*/ - - /** - * Gets URI that identifies the test. - * @return uri identifier of test - */ -function getTargetURI() { - return "http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodelookupnamespaceuri09"; - } - -var docsLoaded = -1000000; -var builder = null; - -// -// This function is called by the testing framework before -// running the test suite. -// -// If there are no configuration exceptions, asynchronous -// document loading is started. Otherwise, the status -// is set to complete and the exception is immediately -// raised when entering the body of the test. -// -function setUpPage() { - setUpPageStatus = 'running'; - try { - // - // creates test document builder, may throw exception - // - builder = createConfiguredBuilder(); - setImplementationAttribute("namespaceAware", true); - - docsLoaded = 0; - - var docRef = null; - if (typeof(this.doc) != 'undefined') { - docRef = this.doc; - } - docsLoaded += preload(docRef, "doc", "hc_staff"); - - if (docsLoaded == 1) { - setUpPageStatus = 'complete'; - } - } catch(ex) { - catchInitializationError(builder, ex); - setUpPageStatus = 'complete'; - } -} - -// -// This method is called on the completion of -// each asychronous load started in setUpTests. -// -// When every synchronous loaded document has completed, -// the page status is changed which allows the -// body of the test to be executed. -function loadComplete() { - if (++docsLoaded == 1) { - setUpPageStatus = 'complete'; - } -} - -/** -* - Invoke lookupNamespaceURI on an Element node with no prefix, whose parent has no prefix and - 2 namespace attribute declarations with and without namespace prefixes and check if the value of - the namespaceURI returned by using each prefix as a parameter is valid. - -* @author IBM -* @author Neil Delima -* @see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core#Node3-lookupNamespaceURI -*/ -function nodelookupnamespaceuri09() { - var success; - if(checkInitialization(builder, "nodelookupnamespaceuri09") != null) return; - var doc; - var elem; - var elemList; - var namespaceURI; - var namespaceURIEmpty; - - var docRef = null; - if (typeof(this.doc) != 'undefined') { - docRef = this.doc; - } - doc = load(docRef, "doc", "hc_staff"); - elemList = doc.getElementsByTagName("em"); - elem = elemList.item(0); - namespaceURI = elem.lookupNamespaceURI("dmstc"); - assertEquals("nodelookupnamespaceuri09","http://www.usa.com",namespaceURI); - namespaceURIEmpty = elem.lookupNamespaceURI(""); - assertNull("nodelookupnamespaceprefixEmpty09",namespaceURIEmpty); - -} - -function runTest() { - nodelookupnamespaceuri09(); -}
diff --git a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.xhtml b/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.xhtml deleted file mode 100644 index 8e1af52..0000000 --- a/third_party/WebKit/LayoutTests/dom/legacy_dom_conformance/xhtml/level3/core/nodelookupnamespaceuri09.xhtml +++ /dev/null
@@ -1,73 +0,0 @@ -<?xml version="1.0"?><?TEST-STYLE PIDATA?> -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "xhtml1-strict.dtd" [ - <!ENTITY alpha "α"> - <!ENTITY beta "β"> - <!ENTITY gamma "γ"> - <!ENTITY delta "δ"> - <!ENTITY epsilon "ε"> - <!ENTITY alpha "ζ"> - <!NOTATION notation1 PUBLIC "notation1File"> - <!NOTATION notation2 SYSTEM "notation2File"> - <!ATTLIST p - dir CDATA 'rtl' - xmlns:dmstc CDATA #IMPLIED - xmlns:nm CDATA #IMPLIED - xmlns:emp2 CDATA #IMPLIED> - <!ATTLIST html - xmlns:xsi CDATA #IMPLIED - xsi:schemaLocation CDATA #IMPLIED> - <!ATTLIST acronym xsi:noNamespaceSchemaLocation CDATA #IMPLIED> - <!ENTITY ent4 "<span xmlns='http://www.w3.org/1999/xhtml'>Element data</span><?PItarget PIdata?>"> - <!ATTLIST span xmlns CDATA #IMPLIED> -]> -<!-- This is comment number 1.--> -<html xmlns='http://www.w3.org/1999/xhtml' - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.w3.org/1999/xhtml hc_staff.xsd"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>hc_staff</title><script type="text/javascript" src="selfxhtml.js"/><script charset="UTF-8" type="text/javascript" src="nodelookupnamespaceuri09.js"/><script type='text/javascript'>function loadComplete() { startTest(); }</script></head><body onload="loadComplete()"> - <p xmlns:dmstc="http://www.usa.com"> - <em>EMP0001</em> - <strong>Margaret Martin</strong> - <code>Accountant</code> - <sup>56,000</sup> - <var>Female</var> - <acronym title="Yes" xsi:noNamespaceSchemaLocation="Yes">1230 North Ave. Dallas, Texas 98551</acronym> - </p> - <p xmlns:dmstc="http://www.usa.com"> - <em>EMP0002</em> - <strong>Martha Raynolds -<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]> -<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></strong> - <code>Secretary</code> - <sup>35,000</sup> - <var>Female</var> - <acronym title="Yes" class="Yes" xsi:noNamespaceSchemaLocation="Yes">β Dallas, γ - 98554</acronym> - </p> - <p xmlns:dmstc="http://www.netzero.com"> - <em>EMP0003</em> - <strong>Roger - Jones</strong> - <code>Department Manager</code> - <sup>100,000</sup> - <var>&ent4;</var> - <acronym title="Yes" class="No" id="_98553" xsi:noNamespaceSchemaLocation="Yes">PO Box 27 Irving, texas 98553</acronym> - </p> - <p xmlns:nm="http://www.altavista.com"> - <em>EMP0004</em> - <strong>Jeny Oconnor</strong> - <code>Personnel Director</code> - <sup>95,000</sup> - <var>Female</var> - <acronym title="Yes" class="Yα" id="_98556" xsi:noNamespaceSchemaLocation="Yes">27 South Road. Dallas, Texas 98556</acronym> - </p> - <p xmlns:emp2="http://www.nist.gov"> - <em>EMP0005</em> - <strong>Robert Myers</strong> - <code>Computer Specialist</code> - <sup>90,000</sup> - <var>male</var> - <acronym title="Yes" class="Yes" xsi:noNamespaceSchemaLocation="Yes">1821 Nordic. Road, Irving Texas 98558</acronym> - </p> -</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/.gitignore b/third_party/WebKit/LayoutTests/external/csswg-test/.gitignore new file mode 100644 index 0000000..20072eb --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/.gitignore
@@ -0,0 +1,14 @@ +dist +dist_last +build-temp +tools/cache +*.xcodeproj +*.DS_Store +*.pyc +*.svn +.directory* +*~ +*.orig +*Thumbs.db +_certs +config.json
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-contents-before-after-002.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-contents-before-after-002.html index 9420b38f..4c5947f 100644 --- a/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-contents-before-after-002.html +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-contents-before-after-002.html
@@ -7,10 +7,12 @@ <style> div::before { display: contents; + border: 100px solid red; content: "P" } div::after { display: contents; + border: 100px solid red; content: "S" } </style>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001-expected.html b/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001-expected.html index f556ca5..9fea986c 100644 --- a/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001-expected.html +++ b/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001-expected.html
@@ -40,11 +40,11 @@ td { - padding: 10px; - font-size: 15px; - background-color: grey; - width: 80px; - height: 80px; + padding: 5px; + font-size: 13px; + background-color: silver; + width: 70px; + height: 70px; }
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html b/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html index 3d6f19c..76f3149 100644 --- a/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html +++ b/third_party/WebKit/LayoutTests/external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html
@@ -55,11 +55,11 @@ td { - padding: 10px; - font-size: 15px; - background-color: grey; - width: 80px; - height: 80px; + padding: 5px; + font-size: 13px; + background-color: silver; + width: 70px; + height: 70px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-lookupNamespaceURI-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-lookupNamespaceURI-expected.txt index 54998b3c..78d3985 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-lookupNamespaceURI-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-lookupNamespaceURI-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 58 tests; 50 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 58 tests; 54 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS DocumentFragment should have null namespace, prefix null PASS DocumentFragment should have null namespace, prefix "" PASS DocumentFragment should have null namespace, prefix "foo" @@ -18,7 +18,7 @@ PASS fooNamespace is not default PASS xmlns namespace is not default PASS Element should have baz namespace, prefix null -FAIL Element should have baz namespace, prefix "" assert_equals: expected (string) "bazURI" but got (object) null +PASS Element should have baz namespace, prefix "" PASS Element does not has namespace with xlmns prefix PASS Element has bar namespace PASS Empty namespace is not default on fooElem, prefix null @@ -26,7 +26,7 @@ PASS bar namespace is not default PASS baz namespace is default PASS Comment should inherit baz namespace -FAIL Comment should inherit baz namespace assert_equals: expected (string) "bazURI" but got (object) null +PASS Comment should inherit baz namespace PASS Comment should inherit namespace URI matching prefix PASS Comment should inherit bar namespace PASS For comment, empty namespace is not default, prefix null @@ -36,7 +36,7 @@ PASS For comment, inherited bar namespace is not default PASS For comment, inherited baz namespace is default PASS Child element should inherit baz namespace -FAIL Child element should have null namespace assert_equals: expected (string) "childNamespace" but got (object) null +PASS Child element should have null namespace PASS Child element should not have XMLNS namespace PASS Child element has namespace URI matching prefix PASS Empty namespace is not default for child, prefix null @@ -47,7 +47,7 @@ PASS baz namespace is default for child PASS childNamespace is default for child PASS Document should have xhtml namespace, prefix null -FAIL Document should have xhtml namespace, prefix "" assert_equals: expected (string) "http://www.w3.org/1999/xhtml" but got (object) null +PASS Document should have xhtml namespace, prefix "" PASS Document has no namespace URI matching prefix PASS Document has bar namespace PASS For document, empty namespace is not default, prefix null
diff --git a/third_party/WebKit/LayoutTests/mojo/data-pipe.html b/third_party/WebKit/LayoutTests/mojo/data-pipe.html new file mode 100644 index 0000000..5298cbd --- /dev/null +++ b/third_party/WebKit/LayoutTests/mojo/data-pipe.html
@@ -0,0 +1,145 @@ +<!DOCTYPE html> +<title>Mojo data pipe tests</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> + +let kElementNumBytes = 1; +let kCapacityNumBytes = 64; + +function createDataPipe() { + return Mojo.createDataPipe({ + elementNumBytes: kElementNumBytes, + capacityNumBytes: kCapacityNumBytes + }); +}; + +test(() => { + let {result, producer, consumer} = createDataPipe(); + assert_equals(result, Mojo.RESULT_OK); + assert_true(producer instanceof MojoHandle); + assert_true(consumer instanceof MojoHandle); +}, "Create data pipe"); + +test(() => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + + let {result, numBytes} = producer.writeData(data); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, data.length); +}, "Write data"); + +test(() => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes + 1); + + let {result, numBytes} = producer.writeData(data, {allOrNone: true}); + assert_equals(result, Mojo.RESULT_OUT_OF_RANGE); + assert_equals(numBytes, 0); +}, "Write data all or none"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + + consumer.watch({readable: true}, test.step_func_done((result) => { + var {result, numBytes} = consumer.queryData(); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, data.length); + })); + producer.writeData(data); +}, "Query data"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + for (let i = 0; i < data.length; ++i) + data[i] = i; + + consumer.watch({readable: true}, test.step_func_done((result) => { + var kDiscardNumBytes = data.length / 2; + + var {result, numBytes} = consumer.discardData(kDiscardNumBytes); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, kDiscardNumBytes); + + var {result, numBytes} = consumer.queryData(); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, kDiscardNumBytes); + + var buffer = new Uint8Array(kDiscardNumBytes); + var {result, numBytes} = consumer.readData(buffer); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, kDiscardNumBytes); + assert_array_equals(buffer, data.slice(kDiscardNumBytes)); + })); + producer.writeData(data); +}, "Discard data"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + + consumer.watch({readable: true}, test.step_func_done((result) => { + var {result, numBytes} = consumer.discardData(data.length + 1, {allOrNone: true}); + assert_equals(result, Mojo.RESULT_OUT_OF_RANGE); + assert_equals(numBytes, 0); + })); + producer.writeData(data); +}, "Discard data all or none"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + for (let i = 0; i < data.length; ++i) + data[i] = i; + + consumer.watch({readable: true}, test.step_func_done((result) => { + var buffer = new Uint8Array(data.length); + var {result, numBytes} = consumer.readData(buffer); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, data.length); + assert_array_equals(buffer, data); + + var {result, numBytes} = consumer.queryData(); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, 0); + })); + producer.writeData(data); +}, "Read data"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + + consumer.watch({readable: true}, test.step_func_done((result) => { + var buffer = new Uint8Array(data.length + 1); + var {result, numBytes} = consumer.readData(buffer, {allOrNone: true}); + assert_equals(result, Mojo.RESULT_OUT_OF_RANGE); + assert_equals(numBytes, 0); + })); + producer.writeData(data); +}, "Read data all or none"); + +async_test((test) => { + let {producer, consumer} = createDataPipe(); + let data = new Uint8Array(kCapacityNumBytes); + for (let i = 0; i < data.length; ++i) + data[i] = i; + + consumer.watch({readable: true}, test.step_func_done((result) => { + var buffer = new Uint8Array(data.length); + var {result, numBytes} = consumer.readData(buffer, {peek: true}); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, data.length); + assert_array_equals(buffer, data); + + var {result, numBytes} = consumer.queryData(); + assert_equals(result, Mojo.RESULT_OK); + assert_equals(numBytes, data.length); + })); + producer.writeData(data); +}, "Peek data"); + +</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/border-radius-clip-content-edge-expected.png index 73ff947..0882ca3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/border-radius-clip-content-edge-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png index d78ce9a..db34fd1 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png index d78ce9a..db34fd1 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png index eb1f211f4..c0b4daa 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/replaced/border-radius-clip-content-edge-expected.png new file mode 100644 index 0000000..4ceb5a9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png new file mode 100644 index 0000000..b8678f06 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png new file mode 100644 index 0000000..b8678f06 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png new file mode 100644 index 0000000..00d8803 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/replaced/border-radius-clip-content-edge-expected.png new file mode 100644 index 0000000..4ceb5a9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png new file mode 100644 index 0000000..b8678f06 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png new file mode 100644 index 0000000..b8678f06 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png new file mode 100644 index 0000000..00d8803 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/border-radius-clip-content-edge-expected.png new file mode 100644 index 0000000..4ceb5a9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png index 8d6656ab..334880d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png index 8d6656ab..334880d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png index 95b3dd1..13a5668 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 31fb26a..dd72837 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4105,6 +4105,7 @@ method item method namedItem interface Mojo + static method createDataPipe static method createMessagePipe static method createSharedBuffer attribute @@toStringTag @@ -4131,10 +4132,14 @@ attribute @@toStringTag method close method constructor + method discardData method duplicateBufferHandle method mapBuffer + method queryData + method readData method readMessage method watch + method writeData method writeMessage interface MojoWatcher attribute @@toStringTag
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn index 8856cdc..f40694d3 100644 --- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn +++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -129,20 +129,34 @@ "$blink_core_output_dir/imagebitmap/ImageBitmapOptions.h", "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.cpp", "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.h", + "$blink_core_output_dir/mojo/MojoCreateDataPipeOptions.cpp", + "$blink_core_output_dir/mojo/MojoCreateDataPipeOptions.h", + "$blink_core_output_dir/mojo/MojoCreateDataPipeResult.cpp", + "$blink_core_output_dir/mojo/MojoCreateDataPipeResult.h", "$blink_core_output_dir/mojo/MojoCreateMessagePipeResult.cpp", "$blink_core_output_dir/mojo/MojoCreateMessagePipeResult.h", "$blink_core_output_dir/mojo/MojoCreateSharedBufferResult.cpp", "$blink_core_output_dir/mojo/MojoCreateSharedBufferResult.h", + "$blink_core_output_dir/mojo/MojoDiscardDataOptions.cpp", + "$blink_core_output_dir/mojo/MojoDiscardDataOptions.h", "$blink_core_output_dir/mojo/MojoDuplicateBufferHandleOptions.cpp", "$blink_core_output_dir/mojo/MojoDuplicateBufferHandleOptions.h", "$blink_core_output_dir/mojo/MojoHandleSignals.cpp", "$blink_core_output_dir/mojo/MojoHandleSignals.h", "$blink_core_output_dir/mojo/MojoMapBufferResult.cpp", "$blink_core_output_dir/mojo/MojoMapBufferResult.h", + "$blink_core_output_dir/mojo/MojoReadDataOptions.cpp", + "$blink_core_output_dir/mojo/MojoReadDataOptions.h", + "$blink_core_output_dir/mojo/MojoReadDataResult.cpp", + "$blink_core_output_dir/mojo/MojoReadDataResult.h", "$blink_core_output_dir/mojo/MojoReadMessageFlags.cpp", "$blink_core_output_dir/mojo/MojoReadMessageFlags.h", "$blink_core_output_dir/mojo/MojoReadMessageResult.cpp", "$blink_core_output_dir/mojo/MojoReadMessageResult.h", + "$blink_core_output_dir/mojo/MojoWriteDataOptions.cpp", + "$blink_core_output_dir/mojo/MojoWriteDataOptions.h", + "$blink_core_output_dir/mojo/MojoWriteDataResult.cpp", + "$blink_core_output_dir/mojo/MojoWriteDataResult.h", "$blink_core_output_dir/offscreencanvas/ImageEncodeOptions.cpp", "$blink_core_output_dir/offscreencanvas/ImageEncodeOptions.h", "$blink_core_output_dir/page/scrolling/ScrollStateInit.cpp",
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index f473980..d64f10b88 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -565,13 +565,20 @@ "html/track/TrackEventInit.idl", "imagebitmap/ImageBitmapOptions.idl", "input/InputDeviceCapabilitiesInit.idl", + "mojo/MojoCreateDataPipeOptions.idl", + "mojo/MojoCreateDataPipeResult.idl", "mojo/MojoCreateMessagePipeResult.idl", "mojo/MojoCreateSharedBufferResult.idl", + "mojo/MojoDiscardDataOptions.idl", "mojo/MojoDuplicateBufferHandleOptions.idl", "mojo/MojoHandleSignals.idl", "mojo/MojoMapBufferResult.idl", + "mojo/MojoReadDataOptions.idl", + "mojo/MojoReadDataResult.idl", "mojo/MojoReadMessageFlags.idl", "mojo/MojoReadMessageResult.idl", + "mojo/MojoWriteDataOptions.idl", + "mojo/MojoWriteDataResult.idl", "offscreencanvas/ImageEncodeOptions.idl", "page/scrolling/ScrollStateInit.idl", "timing/PerformanceObserverInit.idl",
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index b8c3eb49..706d0b7 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1240,20 +1240,34 @@ return context->locateNamespacePrefix(namespaceURI); } -const AtomicString& Node::lookupNamespaceURI(const String& prefix) const { +const AtomicString& Node::lookupNamespaceURI( + const String& specifiedPrefix) const { // Implemented according to - // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo + // https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri - if (!prefix.isNull() && prefix.isEmpty()) - return nullAtom; + // 1. If prefix is the empty string, then set it to null. + String prefix = specifiedPrefix; + if (!specifiedPrefix.isNull() && specifiedPrefix.isEmpty()) + prefix = String(); + // 2. Return the result of running locate a namespace for the context object + // using prefix. + + // https://dom.spec.whatwg.org/#locate-a-namespace switch (getNodeType()) { case kElementNode: { const Element& element = toElement(*this); + // 1. If its namespace is not null and its namespace prefix is prefix, + // then return namespace. if (!element.namespaceURI().isNull() && element.prefix() == prefix) return element.namespaceURI(); + // 2. If it has an attribute whose namespace is the XMLNS namespace, + // namespace prefix is "xmlns", and local name is prefix, or if prefix is + // null and it has an attribute whose namespace is the XMLNS namespace, + // namespace prefix is null, and local name is "xmlns", then return its + // value if it is not the empty string, and null otherwise. AttributeCollection attributes = element.attributes(); for (const Attribute& attr : attributes) { if (attr.prefix() == xmlnsAtom && attr.localName() == prefix) { @@ -1268,6 +1282,9 @@ } } + // 3. If its parent element is null, then return null. + // 4. Return the result of running locate a namespace on its parent + // element using prefix. if (Element* parent = parentElement()) return parent->lookupNamespaceURI(prefix); return nullAtom; @@ -1832,7 +1849,7 @@ oldDocument.frameHost() == newDocument.frameHost()) return; - oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfPage(*this); + oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this); } void Node::didMoveToNewDocument(Document& oldDocument) { @@ -1849,7 +1866,7 @@ oldDocument.markers().removeMarkers(this); if (document().frameHost() && document().frameHost() != oldDocument.frameHost()) { - document().frameHost()->eventHandlerRegistry().didMoveIntoPage(*this); + document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this); } if (const HeapVector<TraceWrapperMember<MutationObserverRegistration>>*
diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp index c70fe99..a9b0fc8 100644 --- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp +++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
@@ -10,6 +10,7 @@ #include "core/frame/LocalFrame.h" #include "core/html/HTMLFrameOwnerElement.h" #include "core/page/ChromeClient.h" +#include "core/page/Page.h" #include "core/page/scrolling/ScrollingCoordinator.h" namespace blink { @@ -29,7 +30,8 @@ } // namespace -EventHandlerRegistry::EventHandlerRegistry(Page& page) : m_page(&page) {} +EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost) + : m_frameHost(&frameHost) {} EventHandlerRegistry::~EventHandlerRegistry() { for (size_t i = 0; i < EventHandlerClassCount; ++i) { @@ -173,7 +175,7 @@ updateEventHandlerInternal(Remove, handlerClass, &target); } -void EventHandlerRegistry::didMoveIntoPage(EventTarget& target) { +void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target) { if (!target.hasEventListeners()) return; @@ -194,7 +196,7 @@ } } -void EventHandlerRegistry::didMoveOutOfPage(EventTarget& target) { +void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target) { didRemoveAllEventHandlers(target); } @@ -211,19 +213,19 @@ bool hasActiveHandlers) { switch (handlerClass) { case ScrollEvent: - m_page->chromeClient().setHasScrollEventHandlers(frame, - hasActiveHandlers); + m_frameHost->page().chromeClient().setHasScrollEventHandlers( + frame, hasActiveHandlers); break; case WheelEventBlocking: case WheelEventPassive: - m_page->chromeClient().setEventListenerProperties( + m_frameHost->page().chromeClient().setEventListenerProperties( frame, WebEventListenerClass::MouseWheel, webEventListenerProperties(hasEventHandlers(WheelEventBlocking), hasEventHandlers(WheelEventPassive))); break; case TouchStartOrMoveEventBlocking: case TouchStartOrMoveEventPassive: - m_page->chromeClient().setEventListenerProperties( + m_frameHost->page().chromeClient().setEventListenerProperties( frame, WebEventListenerClass::TouchStartOrMove, webEventListenerProperties( hasEventHandlers(TouchStartOrMoveEventBlocking), @@ -231,7 +233,7 @@ break; case TouchEndOrCancelEventBlocking: case TouchEndOrCancelEventPassive: - m_page->chromeClient().setEventListenerProperties( + m_frameHost->page().chromeClient().setEventListenerProperties( frame, WebEventListenerClass::TouchEndOrCancel, webEventListenerProperties( hasEventHandlers(TouchEndOrCancelEventBlocking), @@ -249,13 +251,14 @@ void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget( EventHandlerClass handlerClass) { - ScrollingCoordinator* scrollingCoordinator = m_page->scrollingCoordinator(); + ScrollingCoordinator* scrollingCoordinator = + m_frameHost->page().scrollingCoordinator(); if (scrollingCoordinator && handlerClass == TouchStartOrMoveEventBlocking) scrollingCoordinator->touchEventTargetRectsDidChange(); } DEFINE_TRACE(EventHandlerRegistry) { - visitor->trace(m_page); + visitor->trace(m_frameHost); visitor->template registerWeakMembers< EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this); } @@ -316,14 +319,14 @@ if (Node* node = eventTarget.key->toNode()) { // See the comment for |documentDetached| if either of these assertions // fails. - DCHECK(node->document().page()); - DCHECK(node->document().page() == m_page); + DCHECK(node->document().frameHost()); + DCHECK(node->document().frameHost() == m_frameHost); } else if (LocalDOMWindow* window = eventTarget.key->toLocalDOMWindow()) { // If any of these assertions fail, LocalDOMWindow failed to unregister // its handlers properly. DCHECK(window->frame()); - DCHECK(window->frame()->page()); - DCHECK(window->frame()->page() == m_page); + DCHECK(window->frame()->host()); + DCHECK(window->frame()->host() == m_frameHost); } } #endif // DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h index f6a46a05..5802697 100644 --- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h +++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h
@@ -6,8 +6,7 @@ #define EventHandlerRegistry_h #include "core/CoreExport.h" -#include "core/frame/FrameHost.h" // TODO(sashab): Remove this. -#include "core/page/Page.h" +#include "core/frame/FrameHost.h" #include "wtf/HashCountedSet.h" namespace blink { @@ -21,11 +20,11 @@ // Registry for keeping track of event handlers. Note that only handlers on // documents that can be rendered or can receive input (i.e., are attached to a -// Page) are registered here. +// FrameHost) are registered here. class CORE_EXPORT EventHandlerRegistry final : public GarbageCollectedFinalized<EventHandlerRegistry> { public: - explicit EventHandlerRegistry(Page&); + explicit EventHandlerRegistry(FrameHost&); virtual ~EventHandlerRegistry(); // Supported event handler classes. Note that each one may correspond to @@ -45,7 +44,7 @@ EventHandlerClassCount, // Must be the last entry. }; - // Returns true if the Page has event handlers of the specified class. + // Returns true if the FrameHost has event handlers of the specified class. bool hasEventHandlers(EventHandlerClass) const; // Returns a set of EventTargets which have registered handlers of the given @@ -63,11 +62,11 @@ void didRemoveEventHandler(EventTarget&, EventHandlerClass); void didRemoveAllEventHandlers(EventTarget&); - void didMoveIntoPage(EventTarget&); - void didMoveOutOfPage(EventTarget&); + void didMoveIntoFrameHost(EventTarget&); + void didMoveOutOfFrameHost(EventTarget&); - // Either |documentDetached| or |didMove{Into,OutOf,Between}Pages| must - // be called whenever the Page that is associated with a registered event + // Either |documentDetached| or |didMove{Into,OutOf,Between}FrameHosts| must + // be called whenever the FrameHost that is associated with a registered event // target changes. This ensures the registry does not end up with stale // references to handlers that are no longer related to it. void documentDetached(Document&); @@ -121,7 +120,7 @@ void checkConsistency(EventHandlerClass) const; - Member<Page> m_page; + Member<FrameHost> m_frameHost; EventTargetSet m_targets[EventHandlerClassCount]; };
diff --git a/third_party/WebKit/Source/core/frame/FrameHost.cpp b/third_party/WebKit/Source/core/frame/FrameHost.cpp index 0af55d1..85c722c 100644 --- a/third_party/WebKit/Source/core/frame/FrameHost.cpp +++ b/third_party/WebKit/Source/core/frame/FrameHost.cpp
@@ -52,7 +52,7 @@ m_overscrollController( OverscrollController::create(*m_visualViewport, m_page->chromeClient())), - m_eventHandlerRegistry(new EventHandlerRegistry(page)), + m_eventHandlerRegistry(new EventHandlerRegistry(*this)), m_consoleMessageStorage(new ConsoleMessageStorage()), m_globalRootScrollerController( TopDocumentRootScrollerController::create(*this)),
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp index 7e624fe3..a169c3f 100644 --- a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
@@ -100,10 +100,6 @@ HTMLElement::attachLayoutTree(optionContext); } -void HTMLOptionElement::detachLayoutTree(const AttachContext& context) { - HTMLElement::detachLayoutTree(context); -} - bool HTMLOptionElement::supportsFocus() const { HTMLSelectElement* select = ownerSelectElement(); if (select && select->usesMenuList())
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.h b/third_party/WebKit/Source/core/html/HTMLOptionElement.h index 435ffb95..18e3036 100644 --- a/third_party/WebKit/Source/core/html/HTMLOptionElement.h +++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.h
@@ -98,7 +98,6 @@ bool matchesDefaultPseudoClass() const override; bool matchesEnabledPseudoClass() const override; void attachLayoutTree(const AttachContext& = AttachContext()) override; - void detachLayoutTree(const AttachContext& = AttachContext()) override; void parseAttribute(const AttributeModificationParams&) override; InsertionNotificationRequest insertedInto(ContainerNode*) override; void removedFrom(ContainerNode*) override;
diff --git a/third_party/WebKit/Source/core/inspector/DOMEditor.cpp b/third_party/WebKit/Source/core/inspector/DOMEditor.cpp index 7a9a3f3a..6a9258c 100644 --- a/third_party/WebKit/Source/core/inspector/DOMEditor.cpp +++ b/third_party/WebKit/Source/core/inspector/DOMEditor.cpp
@@ -43,6 +43,8 @@ namespace blink { +using protocol::Response; + class DOMEditor::RemoveChildAction final : public InspectorHistory::Action { WTF_MAKE_NONCOPYABLE(RemoveChildAction);
diff --git a/third_party/WebKit/Source/core/inspector/DOMEditor.h b/third_party/WebKit/Source/core/inspector/DOMEditor.h index 28cb1dc..93555f2 100644 --- a/third_party/WebKit/Source/core/inspector/DOMEditor.h +++ b/third_party/WebKit/Source/core/inspector/DOMEditor.h
@@ -43,7 +43,6 @@ class InspectorHistory; class Node; class Text; -using protocol::Response; class DOMEditor final : public GarbageCollected<DOMEditor> { WTF_MAKE_NONCOPYABLE(DOMEditor); @@ -71,12 +70,16 @@ ExceptionState&); bool setNodeValue(Node* parentNode, const String& value, ExceptionState&); - Response insertBefore(ContainerNode* parentNode, Node*, Node* anchorNode); - Response removeChild(ContainerNode* parentNode, Node*); - Response setAttribute(Element*, const String& name, const String& value); - Response removeAttribute(Element*, const String& name); - Response setOuterHTML(Node*, const String& html, Node** newNode); - Response replaceWholeText(Text*, const String& text); + protocol::Response insertBefore(ContainerNode* parentNode, + Node*, + Node* anchorNode); + protocol::Response removeChild(ContainerNode* parentNode, Node*); + protocol::Response setAttribute(Element*, + const String& name, + const String& value); + protocol::Response removeAttribute(Element*, const String& name); + protocol::Response setOuterHTML(Node*, const String& html, Node** newNode); + protocol::Response replaceWholeText(Text*, const String& text); private: class DOMAction;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp index b99a5db..1dc5cab 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -37,6 +37,8 @@ namespace blink { +using protocol::Response; + InspectorAnimationAgent::InspectorAnimationAgent( InspectedFrames* inspectedFrames, InspectorCSSAgent* cssAgent,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.h b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.h index 3273f5530..1c76ca9 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.h
@@ -34,21 +34,24 @@ void didCommitLoadForLocalFrame(LocalFrame*) override; // Protocol method implementations - Response enable() override; - Response disable() override; - Response getPlaybackRate(double* playbackRate) override; - Response setPlaybackRate(double) override; - Response getCurrentTime(const String& id, double* currentTime) override; - Response setPaused(std::unique_ptr<protocol::Array<String>> animations, - bool paused) override; - Response setTiming(const String& animationId, - double duration, - double delay) override; - Response seekAnimations(std::unique_ptr<protocol::Array<String>> animations, - double currentTime) override; - Response releaseAnimations( + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response getPlaybackRate(double* playbackRate) override; + protocol::Response setPlaybackRate(double) override; + protocol::Response getCurrentTime(const String& id, + double* currentTime) override; + protocol::Response setPaused( + std::unique_ptr<protocol::Array<String>> animations, + bool paused) override; + protocol::Response setTiming(const String& animationId, + double duration, + double delay) override; + protocol::Response seekAnimations( + std::unique_ptr<protocol::Array<String>> animations, + double currentTime) override; + protocol::Response releaseAnimations( std::unique_ptr<protocol::Array<String>> animations) override; - Response resolveAnimation( + protocol::Response resolveAnimation( const String& animationId, std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>*) override; @@ -61,7 +64,8 @@ void didClearDocumentOfWindowObject(LocalFrame*); // Methods for other agents to use. - Response assertAnimation(const String& id, blink::Animation*& result); + protocol::Response assertAnimation(const String& id, + blink::Animation*& result); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.cpp index 3045fae..7eabf47f 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.cpp
@@ -36,6 +36,8 @@ namespace blink { +using protocol::Response; + namespace ApplicationCacheAgentState { static const char applicationCacheAgentEnabled[] = "applicationCacheAgentEnabled";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.h b/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.h index 7d4f9b33..6155d49 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorApplicationCacheAgent.h
@@ -51,21 +51,21 @@ // InspectorBaseAgent void restore() override; - Response disable() override; + protocol::Response disable() override; // InspectorInstrumentation API void updateApplicationCacheStatus(LocalFrame*); void networkStateChanged(LocalFrame*, bool online); // ApplicationCache API for frontend - Response getFramesWithManifests( + protocol::Response getFramesWithManifests( std::unique_ptr< protocol::Array<protocol::ApplicationCache::FrameWithManifest>>* frameIds) override; - Response enable() override; - Response getManifestForFrame(const String& frameId, - String* manifestURL) override; - Response getApplicationCacheForFrame( + protocol::Response enable() override; + protocol::Response getManifestForFrame(const String& frameId, + String* manifestURL) override; + protocol::Response getApplicationCacheForFrame( const String& frameId, std::unique_ptr<protocol::ApplicationCache::ApplicationCache>*) override; @@ -83,7 +83,8 @@ buildObjectForApplicationCacheResource( const ApplicationCacheHost::ResourceInfo&); - Response assertFrameWithDocumentLoader(String frameId, DocumentLoader*&); + protocol::Response assertFrameWithDocumentLoader(String frameId, + DocumentLoader*&); Member<InspectedFrames> m_inspectedFrames; };
diff --git a/third_party/WebKit/Source/core/inspector/InspectorBaseAgent.h b/third_party/WebKit/Source/core/inspector/InspectorBaseAgent.h index 718706f5..2ad507f 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorBaseAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorBaseAgent.h
@@ -42,9 +42,6 @@ class LocalFrame; -using protocol::Maybe; -using protocol::Response; - class CORE_EXPORT InspectorAgent : public GarbageCollectedFinalized<InspectorAgent> { public: @@ -85,7 +82,7 @@ } } - Response disable() override { return Response::OK(); } + protocol::Response disable() override { return protocol::Response::OK(); } void dispose() override { disable();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp index eeec1a0..f8c3cef8 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -92,6 +92,8 @@ namespace blink { +using protocol::Response; + namespace { int s_frontendOperationCounter = 0;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h index cdf3962a..bb4f5aa 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
@@ -125,74 +125,80 @@ void setUsageTrackerStatus(bool enabled); void enable(std::unique_ptr<EnableCallback>) override; - Response disable() override; - Response getMatchedStylesForNode( + protocol::Response disable() override; + protocol::Response getMatchedStylesForNode( int nodeId, - Maybe<protocol::CSS::CSSStyle>* inlineStyle, - Maybe<protocol::CSS::CSSStyle>* attributesStyle, - Maybe<protocol::Array<protocol::CSS::RuleMatch>>* matchedCSSRules, - Maybe<protocol::Array<protocol::CSS::PseudoElementMatches>>*, - Maybe<protocol::Array<protocol::CSS::InheritedStyleEntry>>*, - Maybe<protocol::Array<protocol::CSS::CSSKeyframesRule>>*) override; - Response getInlineStylesForNode( + protocol::Maybe<protocol::CSS::CSSStyle>* inlineStyle, + protocol::Maybe<protocol::CSS::CSSStyle>* attributesStyle, + protocol::Maybe<protocol::Array<protocol::CSS::RuleMatch>>* + matchedCSSRules, + protocol::Maybe<protocol::Array<protocol::CSS::PseudoElementMatches>>*, + protocol::Maybe<protocol::Array<protocol::CSS::InheritedStyleEntry>>*, + protocol::Maybe<protocol::Array<protocol::CSS::CSSKeyframesRule>>*) + override; + protocol::Response getInlineStylesForNode( int nodeId, - Maybe<protocol::CSS::CSSStyle>* inlineStyle, - Maybe<protocol::CSS::CSSStyle>* attributesStyle) override; - Response getComputedStyleForNode( + protocol::Maybe<protocol::CSS::CSSStyle>* inlineStyle, + protocol::Maybe<protocol::CSS::CSSStyle>* attributesStyle) override; + protocol::Response getComputedStyleForNode( int nodeId, std::unique_ptr< protocol::Array<protocol::CSS::CSSComputedStyleProperty>>*) override; - Response getPlatformFontsForNode( + protocol::Response getPlatformFontsForNode( int nodeId, std::unique_ptr<protocol::Array<protocol::CSS::PlatformFontUsage>>* fonts) override; - Response collectClassNames( + protocol::Response collectClassNames( const String& styleSheetId, std::unique_ptr<protocol::Array<String>>* classNames) override; - Response getStyleSheetText(const String& styleSheetId, String* text) override; - Response setStyleSheetText(const String& styleSheetId, - const String& text, - Maybe<String>* sourceMapURL) override; - Response setRuleSelector( + protocol::Response getStyleSheetText(const String& styleSheetId, + String* text) override; + protocol::Response setStyleSheetText( + const String& styleSheetId, + const String& text, + protocol::Maybe<String>* sourceMapURL) override; + protocol::Response setRuleSelector( const String& styleSheetId, std::unique_ptr<protocol::CSS::SourceRange>, const String& selector, std::unique_ptr<protocol::CSS::SelectorList>*) override; - Response setKeyframeKey( + protocol::Response setKeyframeKey( const String& styleSheetId, std::unique_ptr<protocol::CSS::SourceRange>, const String& keyText, std::unique_ptr<protocol::CSS::Value>* outKeyText) override; - Response setStyleTexts( + protocol::Response setStyleTexts( std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>> edits, std::unique_ptr<protocol::Array<protocol::CSS::CSSStyle>>* styles) override; - Response setMediaText(const String& styleSheetId, - std::unique_ptr<protocol::CSS::SourceRange>, - const String& text, - std::unique_ptr<protocol::CSS::CSSMedia>*) override; - Response createStyleSheet(const String& frameId, - String* styleSheetId) override; - Response addRule(const String& styleSheetId, - const String& ruleText, - std::unique_ptr<protocol::CSS::SourceRange>, - std::unique_ptr<protocol::CSS::CSSRule>*) override; - Response forcePseudoState( + protocol::Response setMediaText( + const String& styleSheetId, + std::unique_ptr<protocol::CSS::SourceRange>, + const String& text, + std::unique_ptr<protocol::CSS::CSSMedia>*) override; + protocol::Response createStyleSheet(const String& frameId, + String* styleSheetId) override; + protocol::Response addRule(const String& styleSheetId, + const String& ruleText, + std::unique_ptr<protocol::CSS::SourceRange>, + std::unique_ptr<protocol::CSS::CSSRule>*) override; + protocol::Response forcePseudoState( int nodeId, std::unique_ptr<protocol::Array<String>> forcedPseudoClasses) override; - Response getMediaQueries( + protocol::Response getMediaQueries( std::unique_ptr<protocol::Array<protocol::CSS::CSSMedia>>*) override; - Response setEffectivePropertyValueForNode(int nodeId, - const String& propertyName, - const String& value) override; - Response getBackgroundColors( + protocol::Response setEffectivePropertyValueForNode( int nodeId, - Maybe<protocol::Array<String>>* backgroundColors) override; + const String& propertyName, + const String& value) override; + protocol::Response getBackgroundColors( + int nodeId, + protocol::Maybe<protocol::Array<String>>* backgroundColors) override; - Response startRuleUsageTracking() override; + protocol::Response startRuleUsageTracking() override; - Response stopRuleUsageTracking( + protocol::Response stopRuleUsageTracking( std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) override; @@ -211,7 +217,7 @@ CSSStyleDeclaration* findEffectiveDeclaration( CSSPropertyID, const HeapVector<Member<CSSStyleDeclaration>>& styles); - Response getLayoutTreeAndStyles( + protocol::Response getLayoutTreeAndStyles( std::unique_ptr<protocol::Array<String>> styleWhitelist, std::unique_ptr<protocol::Array<protocol::CSS::LayoutTreeNode>>* layoutTreeNodes, @@ -254,11 +260,11 @@ void updateActiveStyleSheets(Document*); void setActiveStyleSheets(Document*, const HeapVector<Member<CSSStyleSheet>>&); - Response setStyleText(InspectorStyleSheetBase*, - const SourceRange&, - const String&, - CSSStyleDeclaration*&); - Response multipleStyleTextsActions( + protocol::Response setStyleText(InspectorStyleSheetBase*, + const SourceRange&, + const String&, + CSSStyleDeclaration*&); + protocol::Response multipleStyleTextsActions( std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>>, HeapVector<Member<StyleSheetAction>>* actions); @@ -274,8 +280,10 @@ InspectorStyleSheet* inspectorStyleSheetForRule(CSSStyleRule*); InspectorStyleSheet* viaInspectorStyleSheet(Document*); - Response assertInspectorStyleSheetForId(const String&, InspectorStyleSheet*&); - Response assertStyleSheetForId(const String&, InspectorStyleSheetBase*&); + protocol::Response assertInspectorStyleSheetForId(const String&, + InspectorStyleSheet*&); + protocol::Response assertStyleSheetForId(const String&, + InspectorStyleSheetBase*&); String detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument); std::unique_ptr<protocol::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp index 2dac689..dfeeadc2 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -84,6 +84,8 @@ namespace blink { using namespace HTMLNames; +using protocol::Maybe; +using protocol::Response; namespace DOMAgentState { static const char domAgentEnabled[] = "domAgentEnabled";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h index 0b0212806..f5849ac2 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -96,7 +96,7 @@ std::unique_ptr<InspectorHighlightConfig>) {} }; - static Response toResponse(ExceptionState&); + static protocol::Response toResponse(ExceptionState&); static bool getPseudoElementType(PseudoId, String*); static ShadowRoot* userAgentShadowRoot(Node*); @@ -113,105 +113,116 @@ void reset(); // Methods called from the frontend for DOM nodes inspection. - Response enable() override; - Response disable() override; - Response getDocument(Maybe<int> depth, - Maybe<bool> traverseFrames, - std::unique_ptr<protocol::DOM::Node>* root) override; - Response getFlattenedDocument( - Maybe<int> depth, - Maybe<bool> pierce, + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response getDocument( + protocol::Maybe<int> depth, + protocol::Maybe<bool> traverseFrames, + std::unique_ptr<protocol::DOM::Node>* root) override; + protocol::Response getFlattenedDocument( + protocol::Maybe<int> depth, + protocol::Maybe<bool> pierce, std::unique_ptr<protocol::Array<protocol::DOM::Node>>* nodes) override; - Response collectClassNamesFromSubtree( + protocol::Response collectClassNamesFromSubtree( int nodeId, std::unique_ptr<protocol::Array<String>>* classNames) override; - Response requestChildNodes(int nodeId, - Maybe<int> depth, - Maybe<bool> traverseFrames) override; - Response querySelector(int nodeId, - const String& selector, - int* outNodeId) override; - Response querySelectorAll( + protocol::Response requestChildNodes( + int nodeId, + protocol::Maybe<int> depth, + protocol::Maybe<bool> traverseFrames) override; + protocol::Response querySelector(int nodeId, + const String& selector, + int* outNodeId) override; + protocol::Response querySelectorAll( int nodeId, const String& selector, std::unique_ptr<protocol::Array<int>>* nodeIds) override; - Response setNodeName(int nodeId, const String& name, int* outNodeId) override; - Response setNodeValue(int nodeId, const String& value) override; - Response removeNode(int nodeId) override; - Response setAttributeValue(int nodeId, - const String& name, - const String& value) override; - Response setAttributesAsText(int nodeId, - const String& text, - Maybe<String> name) override; - Response removeAttribute(int nodeId, const String& name) override; - Response getOuterHTML(int nodeId, String* outerHTML) override; - Response setOuterHTML(int nodeId, const String& outerHTML) override; - Response performSearch(const String& query, - Maybe<bool> includeUserAgentShadowDOM, - String* searchId, - int* resultCount) override; - Response getSearchResults( + protocol::Response setNodeName(int nodeId, + const String& name, + int* outNodeId) override; + protocol::Response setNodeValue(int nodeId, const String& value) override; + protocol::Response removeNode(int nodeId) override; + protocol::Response setAttributeValue(int nodeId, + const String& name, + const String& value) override; + protocol::Response setAttributesAsText(int nodeId, + const String& text, + protocol::Maybe<String> name) override; + protocol::Response removeAttribute(int nodeId, const String& name) override; + protocol::Response getOuterHTML(int nodeId, String* outerHTML) override; + protocol::Response setOuterHTML(int nodeId, const String& outerHTML) override; + protocol::Response performSearch( + const String& query, + protocol::Maybe<bool> includeUserAgentShadowDOM, + String* searchId, + int* resultCount) override; + protocol::Response getSearchResults( const String& searchId, int fromIndex, int toIndex, std::unique_ptr<protocol::Array<int>>* nodeIds) override; - Response discardSearchResults(const String& searchId) override; - Response requestNode(const String& objectId, int* outNodeId) override; - Response setInspectMode(const String& mode, - Maybe<protocol::DOM::HighlightConfig>) override; - Response highlightRect(int x, - int y, - int width, - int height, - Maybe<protocol::DOM::RGBA> color, - Maybe<protocol::DOM::RGBA> outlineColor) override; - Response highlightQuad(std::unique_ptr<protocol::Array<double>> quad, - Maybe<protocol::DOM::RGBA> color, - Maybe<protocol::DOM::RGBA> outlineColor) override; - Response highlightNode(std::unique_ptr<protocol::DOM::HighlightConfig>, - Maybe<int> nodeId, - Maybe<int> backendNodeId, - Maybe<String> objectId) override; - Response hideHighlight() override; - Response highlightFrame( + protocol::Response discardSearchResults(const String& searchId) override; + protocol::Response requestNode(const String& objectId, + int* outNodeId) override; + protocol::Response setInspectMode( + const String& mode, + protocol::Maybe<protocol::DOM::HighlightConfig>) override; + protocol::Response highlightRect( + int x, + int y, + int width, + int height, + protocol::Maybe<protocol::DOM::RGBA> color, + protocol::Maybe<protocol::DOM::RGBA> outlineColor) override; + protocol::Response highlightQuad( + std::unique_ptr<protocol::Array<double>> quad, + protocol::Maybe<protocol::DOM::RGBA> color, + protocol::Maybe<protocol::DOM::RGBA> outlineColor) override; + protocol::Response highlightNode( + std::unique_ptr<protocol::DOM::HighlightConfig>, + protocol::Maybe<int> nodeId, + protocol::Maybe<int> backendNodeId, + protocol::Maybe<String> objectId) override; + protocol::Response hideHighlight() override; + protocol::Response highlightFrame( const String& frameId, - Maybe<protocol::DOM::RGBA> contentColor, - Maybe<protocol::DOM::RGBA> contentOutlineColor) override; - Response pushNodeByPathToFrontend(const String& path, - int* outNodeId) override; - Response pushNodesByBackendIdsToFrontend( + protocol::Maybe<protocol::DOM::RGBA> contentColor, + protocol::Maybe<protocol::DOM::RGBA> contentOutlineColor) override; + protocol::Response pushNodeByPathToFrontend(const String& path, + int* outNodeId) override; + protocol::Response pushNodesByBackendIdsToFrontend( std::unique_ptr<protocol::Array<int>> backendNodeIds, std::unique_ptr<protocol::Array<int>>* nodeIds) override; - Response setInspectedNode(int nodeId) override; - Response resolveNode( + protocol::Response setInspectedNode(int nodeId) override; + protocol::Response resolveNode( int nodeId, - Maybe<String> objectGroup, + protocol::Maybe<String> objectGroup, std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>*) override; - Response getAttributes( + protocol::Response getAttributes( int nodeId, std::unique_ptr<protocol::Array<String>>* attributes) override; - Response copyTo(int nodeId, - int targetNodeId, - Maybe<int> insertBeforeNodeId, - int* outNodeId) override; - Response moveTo(int nodeId, - int targetNodeId, - Maybe<int> insertBeforeNodeId, - int* outNodeId) override; - Response undo() override; - Response redo() override; - Response markUndoableState() override; - Response focus(int nodeId) override; - Response setFileInputFiles( + protocol::Response copyTo(int nodeId, + int targetNodeId, + protocol::Maybe<int> insertBeforeNodeId, + int* outNodeId) override; + protocol::Response moveTo(int nodeId, + int targetNodeId, + protocol::Maybe<int> insertBeforeNodeId, + int* outNodeId) override; + protocol::Response undo() override; + protocol::Response redo() override; + protocol::Response markUndoableState() override; + protocol::Response focus(int nodeId) override; + protocol::Response setFileInputFiles( int nodeId, std::unique_ptr<protocol::Array<String>> files) override; - Response getBoxModel(int nodeId, - std::unique_ptr<protocol::DOM::BoxModel>*) override; - Response getNodeForLocation(int x, int y, int* outNodeId) override; - Response getRelayoutBoundary(int nodeId, int* outNodeId) override; - Response getHighlightObjectForTest( + protocol::Response getBoxModel( + int nodeId, + std::unique_ptr<protocol::DOM::BoxModel>*) override; + protocol::Response getNodeForLocation(int x, int y, int* outNodeId) override; + protocol::Response getRelayoutBoundary(int nodeId, int* outNodeId) override; + protocol::Response getHighlightObjectForTest( int nodeId, std::unique_ptr<protocol::DictionaryValue>* highlight) override; @@ -271,18 +282,19 @@ Function<bool(Node*)>*, HeapVector<Member<Node>>* result); - Response assertNode(int nodeId, Node*&); - Response assertElement(int nodeId, Element*&); + protocol::Response assertNode(int nodeId, Node*&); + protocol::Response assertElement(int nodeId, Element*&); Document* document() const { return m_document.get(); } private: void setDocument(Document*); void innerEnable(); - Response setSearchingForNode(SearchMode, - Maybe<protocol::DOM::HighlightConfig>); - Response highlightConfigFromInspectorObject( - Maybe<protocol::DOM::HighlightConfig> highlightInspectorObject, + protocol::Response setSearchingForNode( + SearchMode, + protocol::Maybe<protocol::DOM::HighlightConfig>); + protocol::Response highlightConfigFromInspectorObject( + protocol::Maybe<protocol::DOM::HighlightConfig> highlightInspectorObject, std::unique_ptr<InspectorHighlightConfig>*); // Node-related methods. @@ -290,9 +302,11 @@ int bind(Node*, NodeToIdMap*); void unbind(Node*, NodeToIdMap*); - Response assertEditableNode(int nodeId, Node*&); - Response assertEditableChildNode(Element* parentElement, int nodeId, Node*&); - Response assertEditableElement(int nodeId, Element*&); + protocol::Response assertEditableNode(int nodeId, Node*&); + protocol::Response assertEditableChildNode(Element* parentElement, + int nodeId, + Node*&); + protocol::Response assertEditableElement(int nodeId, Element*&); int pushNodePathToFrontend(Node*, NodeToIdMap* nodeMap); void pushChildNodesToFrontend(int nodeId, @@ -324,15 +338,15 @@ buildDistributedNodesForSlot(HTMLSlotElement*); Node* nodeForPath(const String& path); - Response nodeForRemoteId(const String& id, Node*&); + protocol::Response nodeForRemoteId(const String& id, Node*&); void discardFrontendBindings(); void innerHighlightQuad(std::unique_ptr<FloatQuad>, - Maybe<protocol::DOM::RGBA> color, - Maybe<protocol::DOM::RGBA> outlineColor); + protocol::Maybe<protocol::DOM::RGBA> color, + protocol::Maybe<protocol::DOM::RGBA> outlineColor); - Response pushDocumentUponHandlelessOperation(); + protocol::Response pushDocumentUponHandlelessOperation(); InspectorRevalidateDOMTask* revalidateTask();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp index 0725821..b588658 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -62,6 +62,9 @@ namespace blink { +using protocol::Maybe; +using protocol::Response; + static const char webglErrorFiredEventName[] = "webglErrorFired"; static const char webglWarningFiredEventName[] = "webglWarningFired"; static const char webglErrorNameProperty[] = "webglErrorName";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h index 608ef920..31e08db 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
@@ -72,20 +72,25 @@ DECLARE_VIRTUAL_TRACE(); // DOMDebugger API for frontend - Response setDOMBreakpoint(int nodeId, const String& type) override; - Response removeDOMBreakpoint(int nodeId, const String& type) override; - Response setEventListenerBreakpoint(const String& eventName, - Maybe<String> targetName) override; - Response removeEventListenerBreakpoint(const String& eventName, - Maybe<String> targetName) override; - Response setInstrumentationBreakpoint(const String& eventName) override; - Response removeInstrumentationBreakpoint(const String& eventName) override; - Response setXHRBreakpoint(const String& url) override; - Response removeXHRBreakpoint(const String& url) override; - Response getEventListeners( + protocol::Response setDOMBreakpoint(int nodeId, const String& type) override; + protocol::Response removeDOMBreakpoint(int nodeId, + const String& type) override; + protocol::Response setEventListenerBreakpoint( + const String& eventName, + protocol::Maybe<String> targetName) override; + protocol::Response removeEventListenerBreakpoint( + const String& eventName, + protocol::Maybe<String> targetName) override; + protocol::Response setInstrumentationBreakpoint( + const String& eventName) override; + protocol::Response removeInstrumentationBreakpoint( + const String& eventName) override; + protocol::Response setXHRBreakpoint(const String& url) override; + protocol::Response removeXHRBreakpoint(const String& url) override; + protocol::Response getEventListeners( const String& objectId, - Maybe<int> depth, - Maybe<bool> pierce, + protocol::Maybe<int> depth, + protocol::Maybe<bool> pierce, std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>* listeners) override; @@ -108,7 +113,7 @@ void did(const probe::UserCallback&); void breakableLocation(const char* name); - Response disable() override; + protocol::Response disable() override; void restore() override; void didCommitLoadForLocalFrame(LocalFrame*) override; @@ -135,8 +140,10 @@ void breakProgramOnDOMEvent(Node* target, int breakpointType, bool insertion); void updateSubtreeBreakpoints(Node*, uint32_t rootMask, bool set); bool hasBreakpoint(Node*, int type); - Response setBreakpoint(const String& eventName, const String& targetName); - Response removeBreakpoint(const String& eventName, const String& targetName); + protocol::Response setBreakpoint(const String& eventName, + const String& targetName); + protocol::Response removeBreakpoint(const String& eventName, + const String& targetName); void didAddBreakpoint(); void didRemoveBreakpoint();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp index 9d3964c..c8f814b 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp
@@ -139,6 +139,8 @@ namespace blink { +using protocol::Response; + InspectorInputAgent::InspectorInputAgent(InspectedFrames* inspectedFrames) : m_inspectedFrames(inspectedFrames) {}
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.h b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.h index 3917428..0c830da 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.h
@@ -53,11 +53,11 @@ DECLARE_VIRTUAL_TRACE(); // Methods called from the frontend for simulating input. - Response dispatchTouchEvent( + protocol::Response dispatchTouchEvent( const String& type, std::unique_ptr<protocol::Array<protocol::Input::TouchPoint>> touchPoints, - Maybe<int> modifiers, - Maybe<double> timestamp) override; + protocol::Maybe<int> modifiers, + protocol::Maybe<double> timestamp) override; private: explicit InspectorInputAgent(InspectedFrames*);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp index 1f0b3e9..292c16c 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -60,6 +60,8 @@ namespace blink { using protocol::Array; +using protocol::Maybe; +using protocol::Response; unsigned InspectorLayerTreeAgent::s_lastSnapshotId; inline String idForLayer(const GraphicsLayer* graphicsLayer) {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.h b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.h index a1d7406..c853444e 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.h
@@ -70,29 +70,30 @@ void didPaint(const GraphicsLayer*, GraphicsContext&, const LayoutRect&); // Called from the front-end. - Response enable() override; - Response disable() override; - Response compositingReasons( + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response compositingReasons( const String& layerId, std::unique_ptr<protocol::Array<String>>* compositingReasons) override; - Response makeSnapshot(const String& layerId, String* snapshotId) override; - Response loadSnapshot( + protocol::Response makeSnapshot(const String& layerId, + String* snapshotId) override; + protocol::Response loadSnapshot( std::unique_ptr<protocol::Array<protocol::LayerTree::PictureTile>> tiles, String* snapshotId) override; - Response releaseSnapshot(const String& snapshotId) override; - Response profileSnapshot( + protocol::Response releaseSnapshot(const String& snapshotId) override; + protocol::Response profileSnapshot( const String& snapshotId, - Maybe<int> minRepeatCount, - Maybe<double> minDuration, - Maybe<protocol::DOM::Rect> clipRect, + protocol::Maybe<int> minRepeatCount, + protocol::Maybe<double> minDuration, + protocol::Maybe<protocol::DOM::Rect> clipRect, std::unique_ptr<protocol::Array<protocol::Array<double>>>* timings) override; - Response replaySnapshot(const String& snapshotId, - Maybe<int> fromStep, - Maybe<int> toStep, - Maybe<double> scale, - String* dataURL) override; - Response snapshotCommandLog( + protocol::Response replaySnapshot(const String& snapshotId, + protocol::Maybe<int> fromStep, + protocol::Maybe<int> toStep, + protocol::Maybe<double> scale, + String* dataURL) override; + protocol::Response snapshotCommandLog( const String& snapshotId, std::unique_ptr<protocol::Array<protocol::DictionaryValue>>* commandLog) override; @@ -108,8 +109,9 @@ GraphicsLayer* rootGraphicsLayer(); PaintLayerCompositor* paintLayerCompositor(); - Response layerById(const String& layerId, GraphicsLayer*&); - Response snapshotById(const String& snapshotId, const PictureSnapshot*&); + protocol::Response layerById(const String& layerId, GraphicsLayer*&); + protocol::Response snapshotById(const String& snapshotId, + const PictureSnapshot*&); typedef HashMap<int, int> LayerIdToNodeIdMap; void buildLayerIdToNodeIdMap(PaintLayer*, LayerIdToNodeIdMap&);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp index 46a024b4..f60ea0b 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.cpp
@@ -12,6 +12,8 @@ namespace blink { +using protocol::Response; + namespace LogAgentState { static const char logEnabled[] = "logEnabled"; static const char logViolations[] = "logViolations";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h index 12a08f2..840f014 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorLogAgent.h
@@ -32,13 +32,13 @@ void consoleMessageAdded(ConsoleMessage*); // Protocol methods. - Response enable() override; - Response disable() override; - Response clear() override; - Response startViolationsReport( + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response clear() override; + protocol::Response startViolationsReport( std::unique_ptr<protocol::Array<protocol::Log::ViolationSetting>>) override; - Response stopViolationsReport() override; + protocol::Response stopViolationsReport() override; private: // PerformanceMonitor::Client implementation.
diff --git a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp index 4b9d755..babea04 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp
@@ -34,6 +34,8 @@ namespace blink { +using protocol::Response; + InspectorMemoryAgent::~InspectorMemoryAgent() {} Response InspectorMemoryAgent::getDOMCounters(int* documents,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h index a22a9728..80234448d 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h
@@ -45,9 +45,9 @@ static InspectorMemoryAgent* create() { return new InspectorMemoryAgent(); } ~InspectorMemoryAgent() override; - Response getDOMCounters(int* documents, - int* nodes, - int* jsEventListeners) override; + protocol::Response getDOMCounters(int* documents, + int* nodes, + int* jsEventListeners) override; private: InspectorMemoryAgent();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp index 8fd423c..5c8857a 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -84,6 +84,7 @@ using GetResponseBodyCallback = protocol::Network::Backend::GetResponseBodyCallback; +using protocol::Response; namespace NetworkAgentState { static const char networkAgentEnabled[] = "networkAgentEnabled";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h index 71f498e..c05aa1c3 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
@@ -192,30 +192,31 @@ void didReceiveWebSocketFrameError(unsigned long identifier, const String&); // Called from frontend - Response enable(Maybe<int> totalBufferSize, - Maybe<int> resourceBufferSize) override; - Response disable() override; - Response setUserAgentOverride(const String&) override; - Response setExtraHTTPHeaders( + protocol::Response enable(Maybe<int> totalBufferSize, + Maybe<int> resourceBufferSize) override; + protocol::Response disable() override; + protocol::Response setUserAgentOverride(const String&) override; + protocol::Response setExtraHTTPHeaders( std::unique_ptr<protocol::Network::Headers>) override; void getResponseBody(const String& requestId, std::unique_ptr<GetResponseBodyCallback>) override; - Response addBlockedURL(const String& url) override; - Response removeBlockedURL(const String& url) override; - Response replayXHR(const String& requestId) override; - Response setMonitoringXHREnabled(bool) override; - Response canClearBrowserCache(bool* result) override; - Response canClearBrowserCookies(bool* result) override; - Response emulateNetworkConditions(bool offline, - double latency, - double downloadThroughput, - double uploadThroughput, - Maybe<String> connectionType) override; - Response setCacheDisabled(bool) override; - Response setBypassServiceWorker(bool) override; - Response setDataSizeLimitsForTest(int maxTotalSize, - int maxResourceSize) override; - Response getCertificate( + protocol::Response addBlockedURL(const String& url) override; + protocol::Response removeBlockedURL(const String& url) override; + protocol::Response replayXHR(const String& requestId) override; + protocol::Response setMonitoringXHREnabled(bool) override; + protocol::Response canClearBrowserCache(bool* result) override; + protocol::Response canClearBrowserCookies(bool* result) override; + protocol::Response emulateNetworkConditions( + bool offline, + double latency, + double downloadThroughput, + double uploadThroughput, + Maybe<String> connectionType) override; + protocol::Response setCacheDisabled(bool) override; + protocol::Response setBypassServiceWorker(bool) override; + protocol::Response setDataSizeLimitsForTest(int maxTotalSize, + int maxResourceSize) override; + protocol::Response getCertificate( const String& origin, std::unique_ptr<protocol::Array<String>>* certificate) override;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index 7e8ff69..d23a4ed 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -73,6 +73,8 @@ namespace blink { +using protocol::Response; + namespace PageAgentState { static const char pageAgentEnabled[] = "pageAgentEnabled"; static const char pageAgentScriptsToEvaluateOnLoad[] =
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h index 9a02f3f..dd76d0a4 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
@@ -108,19 +108,20 @@ static String cachedResourceTypeJson(const Resource&); // Page API for frontend - Response enable() override; - Response disable() override; - Response addScriptToEvaluateOnLoad(const String& scriptSource, - String* identifier) override; - Response removeScriptToEvaluateOnLoad(const String& identifier) override; - Response setAutoAttachToCreatedPages(bool) override; - Response reload(Maybe<bool> bypassCache, - Maybe<String> scriptToEvaluateOnLoad) override; - Response navigate(const String& url, - Maybe<String> referrer, - String* frameId) override; - Response stopLoading() override; - Response getResourceTree( + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response addScriptToEvaluateOnLoad(const String& scriptSource, + String* identifier) override; + protocol::Response removeScriptToEvaluateOnLoad( + const String& identifier) override; + protocol::Response setAutoAttachToCreatedPages(bool) override; + protocol::Response reload(Maybe<bool> bypassCache, + Maybe<String> scriptToEvaluateOnLoad) override; + protocol::Response navigate(const String& url, + Maybe<String> referrer, + String* frameId) override; + protocol::Response stopLoading() override; + protocol::Response getResourceTree( std::unique_ptr<protocol::Page::FrameResourceTree>* frameTree) override; void getResourceContent(const String& frameId, const String& url, @@ -131,19 +132,20 @@ Maybe<bool> caseSensitive, Maybe<bool> isRegex, std::unique_ptr<SearchInResourceCallback>) override; - Response setDocumentContent(const String& frameId, - const String& html) override; - Response startScreencast(Maybe<String> format, - Maybe<int> quality, - Maybe<int> maxWidth, - Maybe<int> maxHeight, - Maybe<int> everyNthFrame) override; - Response stopScreencast() override; - Response configureOverlay(Maybe<bool> suspended, - Maybe<String> message) override; - Response getLayoutMetrics(std::unique_ptr<protocol::Page::LayoutViewport>*, - std::unique_ptr<protocol::Page::VisualViewport>*, - std::unique_ptr<protocol::DOM::Rect>*) override; + protocol::Response setDocumentContent(const String& frameId, + const String& html) override; + protocol::Response startScreencast(Maybe<String> format, + Maybe<int> quality, + Maybe<int> maxWidth, + Maybe<int> maxHeight, + Maybe<int> everyNthFrame) override; + protocol::Response stopScreencast() override; + protocol::Response configureOverlay(Maybe<bool> suspended, + Maybe<String> message) override; + protocol::Response getLayoutMetrics( + std::unique_ptr<protocol::Page::LayoutViewport>*, + std::unique_ptr<protocol::Page::VisualViewport>*, + std::unique_ptr<protocol::DOM::Rect>*) override; // InspectorInstrumentation API void didClearDocumentOfWindowObject(LocalFrame*);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp index c71a2e5..eafc3d5 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp
@@ -15,6 +15,9 @@ namespace blink { +using protocol::Maybe; +using protocol::Response; + namespace TracingAgentState { const char sessionId[] = "sessionId"; }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h index 77a8b11d..578f58e 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h
@@ -43,18 +43,18 @@ // Base agent methods. void restore() override; - Response disable() override; + protocol::Response disable() override; // InspectorInstrumentation methods void frameStartedLoading(LocalFrame*, FrameLoadType); void frameStoppedLoading(LocalFrame*); // Protocol method implementations. - void start(Maybe<String> categories, - Maybe<String> options, - Maybe<double> bufferUsageReportingInterval, - Maybe<String> transferMode, - Maybe<protocol::Tracing::TraceConfig>, + void start(protocol::Maybe<String> categories, + protocol::Maybe<String> options, + protocol::Maybe<double> bufferUsageReportingInterval, + protocol::Maybe<String> transferMode, + protocol::Maybe<protocol::Tracing::TraceConfig>, std::unique_ptr<StartCallback>) override; void end(std::unique_ptr<EndCallback>) override;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp index 3595d89..ec4dc34 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp
@@ -38,6 +38,8 @@ namespace blink { +using protocol::Response; + namespace WorkerAgentState { static const char autoAttach[] = "autoAttach"; static const char waitForDebuggerOnStart[] = "waitForDebuggerOnStart";
diff --git a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h index 1033503..9666fbe 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h
@@ -52,7 +52,7 @@ ~InspectorWorkerAgent() override; DECLARE_VIRTUAL_TRACE(); - Response disable() override; + protocol::Response disable() override; void restore() override; void didCommitLoadForLocalFrame(LocalFrame*) override; @@ -62,9 +62,10 @@ void workerTerminated(WorkerInspectorProxy*); // Called from Dispatcher - Response setAutoAttach(bool autoAttach, bool waitForDebuggerOnStart) override; - Response sendMessageToTarget(const String& targetId, - const String& message) override; + protocol::Response setAutoAttach(bool autoAttach, + bool waitForDebuggerOnStart) override; + protocol::Response sendMessageToTarget(const String& targetId, + const String& message) override; void setTracingSessionId(const String&);
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.cpp b/third_party/WebKit/Source/core/mojo/Mojo.cpp index f06dc11..5e5d4f2 100644 --- a/third_party/WebKit/Source/core/mojo/Mojo.cpp +++ b/third_party/WebKit/Source/core/mojo/Mojo.cpp
@@ -4,6 +4,8 @@ #include "core/mojo/Mojo.h" +#include "core/mojo/MojoCreateDataPipeOptions.h" +#include "core/mojo/MojoCreateDataPipeResult.h" #include "core/mojo/MojoCreateMessagePipeResult.h" #include "core/mojo/MojoCreateSharedBufferResult.h" #include "core/mojo/MojoHandle.h" @@ -29,6 +31,27 @@ } // static +void Mojo::createDataPipe(const MojoCreateDataPipeOptions& optionsDict, + MojoCreateDataPipeResult& resultDict) { + ::MojoCreateDataPipeOptions options = {0}; + options.struct_size = sizeof(options); + options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; + options.element_num_bytes = optionsDict.elementNumBytes(); + options.capacity_num_bytes = optionsDict.capacityNumBytes(); + + mojo::ScopedDataPipeProducerHandle producer; + mojo::ScopedDataPipeConsumerHandle consumer; + MojoResult result = mojo::CreateDataPipe(&options, &producer, &consumer); + resultDict.setResult(result); + if (result == MOJO_RESULT_OK) { + resultDict.setProducer( + MojoHandle::create(mojo::ScopedHandle::From(std::move(producer)))); + resultDict.setConsumer( + MojoHandle::create(mojo::ScopedHandle::From(std::move(consumer)))); + } +} + +// static void Mojo::createSharedBuffer(unsigned numBytes, MojoCreateSharedBufferResult& resultDict) { MojoCreateSharedBufferOptions* options = nullptr;
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.h b/third_party/WebKit/Source/core/mojo/Mojo.h index 1d26763..c78e1bd 100644 --- a/third_party/WebKit/Source/core/mojo/Mojo.h +++ b/third_party/WebKit/Source/core/mojo/Mojo.h
@@ -10,6 +10,8 @@ namespace blink { +class MojoCreateDataPipeOptions; +class MojoCreateDataPipeResult; class MojoCreateMessagePipeResult; class MojoCreateSharedBufferResult; @@ -42,6 +44,8 @@ static const MojoResult kResultShouldWait = MOJO_RESULT_SHOULD_WAIT; static void createMessagePipe(MojoCreateMessagePipeResult&); + static void createDataPipe(const MojoCreateDataPipeOptions&, + MojoCreateDataPipeResult&); static void createSharedBuffer(unsigned numBytes, MojoCreateSharedBufferResult&);
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.idl b/third_party/WebKit/Source/core/mojo/Mojo.idl index 4a48194..92421f4 100644 --- a/third_party/WebKit/Source/core/mojo/Mojo.idl +++ b/third_party/WebKit/Source/core/mojo/Mojo.idl
@@ -29,5 +29,6 @@ const MojoResult RESULT_SHOULD_WAIT = 17; static MojoCreateMessagePipeResult createMessagePipe(); + static MojoCreateDataPipeResult createDataPipe(MojoCreateDataPipeOptions options); static MojoCreateSharedBufferResult createSharedBuffer(unsigned long numBytes); };
diff --git a/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeOptions.idl b/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeOptions.idl new file mode 100644 index 0000000..0fba87ae --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeOptions.idl
@@ -0,0 +1,8 @@ +// Copyright 2017 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. + +dictionary MojoCreateDataPipeOptions { + unsigned long elementNumBytes; + unsigned long capacityNumBytes; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeResult.idl b/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeResult.idl new file mode 100644 index 0000000..50667678 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoCreateDataPipeResult.idl
@@ -0,0 +1,9 @@ +// Copyright 2017 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. + +dictionary MojoCreateDataPipeResult { + required MojoResult result; + MojoHandle producer; + MojoHandle consumer; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoDiscardDataOptions.idl b/third_party/WebKit/Source/core/mojo/MojoDiscardDataOptions.idl new file mode 100644 index 0000000..87a62f8 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoDiscardDataOptions.idl
@@ -0,0 +1,7 @@ +// Copyright 2017 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. + +dictionary MojoDiscardDataOptions { + boolean allOrNone = false; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.cpp b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp index b48b61f..9cf46fe 100644 --- a/third_party/WebKit/Source/core/mojo/MojoHandle.cpp +++ b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
@@ -9,11 +9,16 @@ #include "core/dom/DOMArrayBuffer.h" #include "core/dom/DOMArrayBufferView.h" #include "core/mojo/MojoCreateSharedBufferResult.h" +#include "core/mojo/MojoDiscardDataOptions.h" #include "core/mojo/MojoDuplicateBufferHandleOptions.h" #include "core/mojo/MojoMapBufferResult.h" +#include "core/mojo/MojoReadDataOptions.h" +#include "core/mojo/MojoReadDataResult.h" #include "core/mojo/MojoReadMessageFlags.h" #include "core/mojo/MojoReadMessageResult.h" #include "core/mojo/MojoWatcher.h" +#include "core/mojo/MojoWriteDataOptions.h" +#include "core/mojo/MojoWriteDataResult.h" // Mojo messages typically do not contain many handles. In fact most // messages do not contain any handle. An inline capacity of 4 should avoid @@ -97,6 +102,79 @@ resultDict.setHandles(handles); } +void MojoHandle::writeData(const ArrayBufferOrArrayBufferView& buffer, + const MojoWriteDataOptions& optionsDict, + MojoWriteDataResult& resultDict) { + MojoWriteDataFlags flags = MOJO_WRITE_DATA_FLAG_NONE; + if (optionsDict.allOrNone()) + flags |= MOJO_WRITE_DATA_FLAG_ALL_OR_NONE; + + const void* elements = nullptr; + uint32_t numBytes = 0; + if (buffer.isArrayBuffer()) { + DOMArrayBuffer* array = buffer.getAsArrayBuffer(); + elements = array->data(); + numBytes = array->byteLength(); + } else { + DOMArrayBufferView* view = buffer.getAsArrayBufferView(); + elements = view->baseAddress(); + numBytes = view->byteLength(); + } + + MojoResult result = + MojoWriteData(m_handle->value(), elements, &numBytes, flags); + resultDict.setResult(result); + resultDict.setNumBytes(result == MOJO_RESULT_OK ? numBytes : 0); +} + +void MojoHandle::queryData(MojoReadDataResult& resultDict) { + uint32_t numBytes = 0; + MojoResult result = MojoReadData(m_handle->value(), nullptr, &numBytes, + MOJO_READ_DATA_FLAG_QUERY); + resultDict.setResult(result); + resultDict.setNumBytes(numBytes); +} + +void MojoHandle::discardData(unsigned numBytes, + const MojoDiscardDataOptions& optionsDict, + MojoReadDataResult& resultDict) { + MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_DISCARD; + if (optionsDict.allOrNone()) + flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE; + + MojoResult result = + MojoReadData(m_handle->value(), nullptr, &numBytes, flags); + resultDict.setResult(result); + resultDict.setNumBytes(result == MOJO_RESULT_OK ? numBytes : 0); +} + +void MojoHandle::readData(ArrayBufferOrArrayBufferView& buffer, + const MojoReadDataOptions& optionsDict, + MojoReadDataResult& resultDict) { + MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_NONE; + if (optionsDict.allOrNone()) + flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE; + if (optionsDict.peek()) + flags |= MOJO_READ_DATA_FLAG_PEEK; + + void* elements = nullptr; + unsigned numBytes = 0; + if (buffer.isArrayBuffer()) { + DOMArrayBuffer* array = buffer.getAsArrayBuffer(); + elements = array->data(); + numBytes = array->byteLength(); + } else { + DOMArrayBufferView* view = buffer.getAsArrayBufferView(); + elements = view->baseAddress(); + numBytes = view->byteLength(); + } + + MojoResult result = + MojoReadData(m_handle->value(), elements, &numBytes, flags); + resultDict.setResult(result); + resultDict.setNumBytes(result == MOJO_RESULT_OK ? numBytes : 0); +} + void MojoHandle::mapBuffer(unsigned offset, unsigned numBytes, MojoMapBufferResult& resultDict) {
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.h b/third_party/WebKit/Source/core/mojo/MojoHandle.h index 61e4048c..6bf880a 100644 --- a/third_party/WebKit/Source/core/mojo/MojoHandle.h +++ b/third_party/WebKit/Source/core/mojo/MojoHandle.h
@@ -12,13 +12,18 @@ class ArrayBufferOrArrayBufferView; class MojoCreateSharedBufferResult; +class MojoDiscardDataOptions; class MojoDuplicateBufferHandleOptions; class MojoHandleSignals; class MojoMapBufferResult; +class MojoReadDataOptions; +class MojoReadDataResult; class MojoReadMessageFlags; class MojoReadMessageResult; class MojoWatchCallback; class MojoWatcher; +class MojoWriteDataOptions; +class MojoWriteDataResult; class ScriptState; class MojoHandle final : public GarbageCollectedFinalized<MojoHandle>, @@ -38,6 +43,18 @@ const HeapVector<Member<MojoHandle>>&); void readMessage(const MojoReadMessageFlags&, MojoReadMessageResult&); + // DataPipe handle. + void writeData(const ArrayBufferOrArrayBufferView&, + const MojoWriteDataOptions&, + MojoWriteDataResult&); + void queryData(MojoReadDataResult&); + void discardData(unsigned numBytes, + const MojoDiscardDataOptions&, + MojoReadDataResult&); + void readData(ArrayBufferOrArrayBufferView&, + const MojoReadDataOptions&, + MojoReadDataResult&); + // SharedBuffer handle. void mapBuffer(unsigned offset, unsigned numBytes, MojoMapBufferResult&); void duplicateBufferHandle(const MojoDuplicateBufferHandleOptions&,
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.idl b/third_party/WebKit/Source/core/mojo/MojoHandle.idl index 78a49ed0..50f5466 100644 --- a/third_party/WebKit/Source/core/mojo/MojoHandle.idl +++ b/third_party/WebKit/Source/core/mojo/MojoHandle.idl
@@ -10,12 +10,19 @@ void close(); [CallWith=ScriptState] MojoWatcher watch(MojoHandleSignals signals, MojoWatchCallback callback); - // TODO(alokp): Create MessagePipeHandle, a subclass of MojoHandle + // TODO(alokp): Create MojoMessagePipeHandle, a subclass of MojoHandle // and move the following member functions. MojoResult writeMessage(BufferSource buffer, sequence<MojoHandle> handles); MojoReadMessageResult readMessage(optional MojoReadMessageFlags flags); - // TODO(alokp): Create SharedBufferHandle, a subclass of MojoHandle + // TODO(alokp): Create MojoDataPipeProducerHandle and MojoDataPipeConsumerHandle, + // subclasses of MojoHandle and move the following member functions. + MojoWriteDataResult writeData(BufferSource buffer, optional MojoWriteDataOptions options); + MojoReadDataResult queryData(); + MojoReadDataResult discardData(unsigned long numBytes, optional MojoDiscardDataOptions options); + MojoReadDataResult readData(BufferSource buffer, optional MojoReadDataOptions options); + + // TODO(alokp): Create MojoSharedBufferHandle, a subclass of MojoHandle // and move the following member functions. MojoMapBufferResult mapBuffer(unsigned long offset, unsigned long numBytes); MojoCreateSharedBufferResult duplicateBufferHandle(optional MojoDuplicateBufferHandleOptions options);
diff --git a/third_party/WebKit/Source/core/mojo/MojoReadDataOptions.idl b/third_party/WebKit/Source/core/mojo/MojoReadDataOptions.idl new file mode 100644 index 0000000..b0f027d --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoReadDataOptions.idl
@@ -0,0 +1,8 @@ +// Copyright 2017 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. + +dictionary MojoReadDataOptions { + boolean allOrNone = false; + boolean peek = false; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoReadDataResult.idl b/third_party/WebKit/Source/core/mojo/MojoReadDataResult.idl new file mode 100644 index 0000000..e3150c5 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoReadDataResult.idl
@@ -0,0 +1,8 @@ +// Copyright 2017 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. + +dictionary MojoReadDataResult { + required MojoResult result; + required unsigned long numBytes; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoWriteDataOptions.idl b/third_party/WebKit/Source/core/mojo/MojoWriteDataOptions.idl new file mode 100644 index 0000000..67fa570 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoWriteDataOptions.idl
@@ -0,0 +1,7 @@ +// Copyright 2017 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. + +dictionary MojoWriteDataOptions { + boolean allOrNone = false; +};
diff --git a/third_party/WebKit/Source/core/mojo/MojoWriteDataResult.idl b/third_party/WebKit/Source/core/mojo/MojoWriteDataResult.idl new file mode 100644 index 0000000..89916a1 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/MojoWriteDataResult.idl
@@ -0,0 +1,8 @@ +// Copyright 2017 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. + +dictionary MojoWriteDataResult { + required MojoResult result; + required unsigned long numBytes; +};
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditsPanel.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditsPanel.js index beb6fd8..390d1a2 100644 --- a/third_party/WebKit/Source/devtools/front_end/audits/AuditsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditsPanel.js
@@ -48,6 +48,7 @@ this._auditResultsTreeElement.selectable = false; this._auditResultsTreeElement.listItemElement.classList.add('audits-sidebar-results'); this._auditResultsTreeElement.expand(); + this._auditResultsTreeElement.setCollapsible(false); this._sidebarTree.appendChild(this._auditResultsTreeElement); this._constructCategories();
diff --git a/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js b/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js index 5076c466..3c11c51 100644 --- a/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js +++ b/third_party/WebKit/Source/devtools/front_end/cookie_table/CookiesTable.js
@@ -135,9 +135,13 @@ */ _getSelectionCookies() { var node = this._dataGrid.selectedNode; - var neighbor = node && (node.traverseNextNode(true) || node.traversePreviousNode(true)); + var nextNeighbor = node && node.traverseNextNode(true); + var previousNeighbor = node && node.traversePreviousNode(true); - return {current: node && node.cookie, neighbor: neighbor && neighbor.cookie}; + return { + current: node && node.cookie, + neighbor: (nextNeighbor && nextNeighbor.cookie) || (previousNeighbor && previousNeighbor.cookie) + }; } /**
diff --git a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp index 7e91b0f..96bd1fbf 100644 --- a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp +++ b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.cpp
@@ -34,6 +34,8 @@ using protocol::Accessibility::AXValue; using protocol::Accessibility::AXWidgetAttributes; using protocol::Accessibility::AXWidgetStates; +using protocol::Maybe; +using protocol::Response; using namespace HTMLNames;
diff --git a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.h b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.h index 3ed5d138..f6d2b8c9 100644 --- a/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.h +++ b/third_party/WebKit/Source/modules/accessibility/InspectorAccessibilityAgent.h
@@ -30,9 +30,9 @@ DECLARE_VIRTUAL_TRACE(); // Protocol methods. - Response getPartialAXTree( + protocol::Response getPartialAXTree( int domNodeId, - Maybe<bool> fetchRelatives, + protocol::Maybe<bool> fetchRelatives, std::unique_ptr<protocol::Array<protocol::Accessibility::AXNode>>*) override;
diff --git a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp index 26949a0..019d4f1 100644 --- a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp +++ b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
@@ -31,6 +31,7 @@ using blink::protocol::Array; using blink::protocol::CacheStorage::Cache; using blink::protocol::CacheStorage::DataEntry; +using blink::protocol::Response; typedef blink::protocol::CacheStorage::Backend::DeleteCacheCallback DeleteCacheCallback;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp index 0902ff7..03f7365 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp
@@ -12,6 +12,8 @@ namespace blink { +using protocol::Response; + namespace DeviceOrientationInspectorAgentState { static const char alpha[] = "alpha"; static const char beta[] = "beta";
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h index 79c1aa62..e962ef1 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h
@@ -24,10 +24,12 @@ DECLARE_VIRTUAL_TRACE(); // Protocol methods. - Response setDeviceOrientationOverride(double, double, double) override; - Response clearDeviceOrientationOverride() override; + protocol::Response setDeviceOrientationOverride(double, + double, + double) override; + protocol::Response clearDeviceOrientationOverride() override; - Response disable() override; + protocol::Response disable() override; void restore() override; void didCommitLoadForLocalFrame(LocalFrame*) override;
diff --git a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp index 39ada99a..7bc66a9 100644 --- a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
@@ -68,6 +68,8 @@ using blink::protocol::IndexedDB::KeyRange; using blink::protocol::IndexedDB::ObjectStore; using blink::protocol::IndexedDB::ObjectStoreIndex; +using blink::protocol::Maybe; +using blink::protocol::Response; typedef blink::protocol::IndexedDB::Backend::RequestDatabaseNamesCallback RequestDatabaseNamesCallback;
diff --git a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h index 1a6d1107..27c64e36 100644 --- a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h +++ b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h
@@ -53,8 +53,8 @@ void didCommitLoadForLocalFrame(LocalFrame*) override; // Called from the front-end. - Response enable() override; - Response disable() override; + protocol::Response enable() override; + protocol::Response disable() override; void requestDatabaseNames( const String& securityOrigin, std::unique_ptr<RequestDatabaseNamesCallback>) override; @@ -67,7 +67,7 @@ const String& indexName, int skipCount, int pageSize, - Maybe<protocol::IndexedDB::KeyRange>, + protocol::Maybe<protocol::IndexedDB::KeyRange>, std::unique_ptr<RequestDataCallback>) override; void clearObjectStore(const String& securityOrigin, const String& databaseName,
diff --git a/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.cpp b/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.cpp index 7d6f691..2409aeb 100644 --- a/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.cpp +++ b/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.cpp
@@ -44,6 +44,8 @@ namespace blink { +using protocol::Response; + namespace DOMStorageAgentState { static const char domStorageAgentEnabled[] = "domStorageAgentEnabled"; };
diff --git a/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.h b/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.h index bd87ac6c..28251a9 100644 --- a/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.h +++ b/third_party/WebKit/Source/modules/storage/InspectorDOMStorageAgent.h
@@ -65,24 +65,27 @@ void restore() override; // protocol::Dispatcher::DOMStorageCommandHandler overrides. - Response enable() override; - Response disable() override; - Response clear(std::unique_ptr<protocol::DOMStorage::StorageId>) override; + protocol::Response enable() override; + protocol::Response disable() override; + protocol::Response clear( + std::unique_ptr<protocol::DOMStorage::StorageId>) override; - Response getDOMStorageItems( + protocol::Response getDOMStorageItems( std::unique_ptr<protocol::DOMStorage::StorageId>, std::unique_ptr<protocol::Array<protocol::Array<String>>>* entries) override; - Response setDOMStorageItem(std::unique_ptr<protocol::DOMStorage::StorageId>, - const String& key, - const String& value) override; - Response removeDOMStorageItem( + protocol::Response setDOMStorageItem( + std::unique_ptr<protocol::DOMStorage::StorageId>, + const String& key, + const String& value) override; + protocol::Response removeDOMStorageItem( std::unique_ptr<protocol::DOMStorage::StorageId>, const String& key) override; - Response findStorageArea(std::unique_ptr<protocol::DOMStorage::StorageId>, - LocalFrame*&, - StorageArea*&); + protocol::Response findStorageArea( + std::unique_ptr<protocol::DOMStorage::StorageId>, + LocalFrame*&, + StorageArea*&); std::unique_ptr<protocol::DOMStorage::StorageId> storageId( SecurityOrigin*, bool isLocalStorage);
diff --git a/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp b/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp index 34fa9e9..59caca3 100644 --- a/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp
@@ -54,6 +54,9 @@ namespace blink { +using protocol::Maybe; +using protocol::Response; + namespace DatabaseAgentState { static const char databaseAgentEnabled[] = "databaseAgentEnabled"; };
diff --git a/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h b/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h index 20ee21f..2ca5d66a 100644 --- a/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h +++ b/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h
@@ -54,13 +54,13 @@ ~InspectorDatabaseAgent() override; DECLARE_VIRTUAL_TRACE(); - Response disable() override; + protocol::Response disable() override; void restore() override; void didCommitLoadForLocalFrame(LocalFrame*) override; // Called from the front-end. - Response enable() override; - Response getDatabaseTableNames( + protocol::Response enable() override; + protocol::Response getDatabaseTableNames( const String& databaseId, std::unique_ptr<protocol::Array<String>>* names) override; void executeSQL(const String& databaseId,
diff --git a/third_party/WebKit/Source/web/InspectorEmulationAgent.cpp b/third_party/WebKit/Source/web/InspectorEmulationAgent.cpp index 174661e..116e7238 100644 --- a/third_party/WebKit/Source/web/InspectorEmulationAgent.cpp +++ b/third_party/WebKit/Source/web/InspectorEmulationAgent.cpp
@@ -21,6 +21,9 @@ namespace blink { +using protocol::Maybe; +using protocol::Response; + namespace EmulationAgentState { static const char scriptExecutionDisabled[] = "scriptExecutionDisabled"; static const char touchEventEmulationEnabled[] = "touchEventEmulationEnabled";
diff --git a/third_party/WebKit/Source/web/InspectorEmulationAgent.h b/third_party/WebKit/Source/web/InspectorEmulationAgent.h index b54b486..4b8a577 100644 --- a/third_party/WebKit/Source/web/InspectorEmulationAgent.h +++ b/third_party/WebKit/Source/web/InspectorEmulationAgent.h
@@ -36,22 +36,24 @@ ~InspectorEmulationAgent() override; // protocol::Dispatcher::EmulationCommandHandler implementation. - Response forceViewport(double x, double y, double scale) override; - Response resetViewport() override; - Response resetPageScaleFactor() override; - Response setPageScaleFactor(double) override; - Response setScriptExecutionDisabled(bool value) override; - Response setTouchEmulationEnabled(bool enabled, - Maybe<String> configuration) override; - Response setEmulatedMedia(const String&) override; - Response setCPUThrottlingRate(double) override; - Response setVirtualTimePolicy(const String& policy, - Maybe<int> virtualTimeBudgetMs) override; - Response setDefaultBackgroundColorOverride( - Maybe<protocol::DOM::RGBA>) override; + protocol::Response forceViewport(double x, double y, double scale) override; + protocol::Response resetViewport() override; + protocol::Response resetPageScaleFactor() override; + protocol::Response setPageScaleFactor(double) override; + protocol::Response setScriptExecutionDisabled(bool value) override; + protocol::Response setTouchEmulationEnabled( + bool enabled, + protocol::Maybe<String> configuration) override; + protocol::Response setEmulatedMedia(const String&) override; + protocol::Response setCPUThrottlingRate(double) override; + protocol::Response setVirtualTimePolicy( + const String& policy, + protocol::Maybe<int> virtualTimeBudgetMs) override; + protocol::Response setDefaultBackgroundColorOverride( + protocol::Maybe<protocol::DOM::RGBA>) override; // InspectorBaseAgent overrides. - Response disable() override; + protocol::Response disable() override; void restore() override; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp b/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp index 77c7ee0..8f47d89 100644 --- a/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp +++ b/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp
@@ -13,6 +13,8 @@ namespace blink { +using protocol::Response; + namespace RenderingAgentState { static const char showDebugBorders[] = "showDebugBorders"; static const char showFPSCounter[] = "showFPSCounter";
diff --git a/third_party/WebKit/Source/web/InspectorRenderingAgent.h b/third_party/WebKit/Source/web/InspectorRenderingAgent.h index 7a5b13a64..7e48bf490 100644 --- a/third_party/WebKit/Source/web/InspectorRenderingAgent.h +++ b/third_party/WebKit/Source/web/InspectorRenderingAgent.h
@@ -22,21 +22,21 @@ static InspectorRenderingAgent* create(WebLocalFrameImpl*, InspectorOverlay*); // protocol::Dispatcher::PageCommandHandler implementation. - Response setShowPaintRects(bool) override; - Response setShowDebugBorders(bool) override; - Response setShowFPSCounter(bool) override; - Response setShowScrollBottleneckRects(bool) override; - Response setShowViewportSizeOnResize(bool) override; + protocol::Response setShowPaintRects(bool) override; + protocol::Response setShowDebugBorders(bool) override; + protocol::Response setShowFPSCounter(bool) override; + protocol::Response setShowScrollBottleneckRects(bool) override; + protocol::Response setShowViewportSizeOnResize(bool) override; // InspectorBaseAgent overrides. - Response disable() override; + protocol::Response disable() override; void restore() override; DECLARE_VIRTUAL_TRACE(); private: InspectorRenderingAgent(WebLocalFrameImpl*, InspectorOverlay*); - Response compositingEnabled(); + protocol::Response compositingEnabled(); WebViewImpl* webViewImpl(); Member<WebLocalFrameImpl> m_webLocalFrameImpl;
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index df484b9..474fd13 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -181,7 +181,10 @@ sources = [ "include/protocol/gaming-input-unstable-v1-client-protocol.h", "include/protocol/gaming-input-unstable-v1-server-protocol.h", - "protocol/gaming-input-protocol.c", + "include/protocol/gaming-input-unstable-v2-client-protocol.h", + "include/protocol/gaming-input-unstable-v2-server-protocol.h", + "protocol/gaming-input-protocol-v1.c", + "protocol/gaming-input-protocol-v2.c", ] deps = [
diff --git a/third_party/wayland-protocols/README.chromium b/third_party/wayland-protocols/README.chromium index 48968e7..035d45b8 100644 --- a/third_party/wayland-protocols/README.chromium +++ b/third_party/wayland-protocols/README.chromium
@@ -43,9 +43,12 @@ wayland-scanner code < unstable/vsync-feedback/vsync-feedback-unstable-v1.xml > protocol/vsync-feedback-protocol.c wayland-scanner server-header < unstable/vsync-feedback/vsync-feedback-unstable-v1.xml > include/protocol/vsync-feedback-unstable-v1-server-protocol.h wayland-scanner client-header < unstable/vsync-feedback/vsync-feedback-unstable-v1.xml > include/protocol/vsync-feedback-unstable-v1-client-protocol.h - wayland-scanner code < unstable/gaming-input/gaming-input-unstable-v1.xml > protocol/gaming-input-protocol.c + wayland-scanner code < unstable/gaming-input/gaming-input-unstable-v1.xml > protocol/gaming-input-protocol-v1.c wayland-scanner server-header < unstable/gaming-input/gaming-input-unstable-v1.xml > include/protocol/gaming-input-unstable-v1-server-protocol.h wayland-scanner client-header < unstable/gaming-input/gaming-input-unstable-v1.xml > include/protocol/gaming-input-unstable-v1-client-protocol.h + wayland-scanner code < unstable/gaming-input/gaming-input-unstable-v2.xml > protocol/gaming-input-protocol-v2.c + wayland-scanner server-header < unstable/gaming-input/gaming-input-unstable-v2.xml > include/protocol/gaming-input-unstable-v2-server-protocol.h + wayland-scanner client-header < unstable/gaming-input/gaming-input-unstable-v2.xml > include/protocol/gaming-input-unstable-v2-client-protocol.h wayland-scanner code < unstable/stylus/stylus-unstable-v1.xml > protocol/stylus-protocol-v1.c wayland-scanner server-header < unstable/stylus/stylus-unstable-v1.xml > include/protocol/stylus-unstable-v1-server-protocol.h wayland-scanner client-header < unstable/stylus/stylus-unstable-v1.xml > include/protocol/stylus-unstable-v1-client-protocol.h
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h index 59aff16..d5eac5e 100644 --- a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.11.0 */ +/* Generated by wayland-scanner 1.12.90 */ #ifndef GAMING_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H #define GAMING_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H @@ -85,7 +85,7 @@ * @page page_iface_zcr_gamepad_v1 zcr_gamepad_v1 * @section page_iface_zcr_gamepad_v1_desc Description * - * The zwp_gamepad_v1 interface represents one or more gamepad input devices, + * The zcr_gamepad_v1 interface represents one or more gamepad input devices, * which are reported as a normalized 'Standard Gamepad' as it is specified * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping * @section page_iface_zcr_gamepad_v1_api API @@ -94,18 +94,18 @@ /** * @defgroup iface_zcr_gamepad_v1 The zcr_gamepad_v1 interface * - * The zwp_gamepad_v1 interface represents one or more gamepad input devices, + * The zcr_gamepad_v1 interface represents one or more gamepad input devices, * which are reported as a normalized 'Standard Gamepad' as it is specified * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping */ extern const struct wl_interface zcr_gamepad_v1_interface; -#define ZCR_GAMING_INPUT_V1_GET_GAMEPAD 0 +#define ZCR_GAMING_INPUT_V1_GET_GAMEPAD 0 /** * @ingroup iface_zcr_gaming_input_v1 */ -#define ZCR_GAMING_INPUT_V1_GET_GAMEPAD_SINCE_VERSION 1 +#define ZCR_GAMING_INPUT_V1_GET_GAMEPAD_SINCE_VERSION 1 /** @ingroup iface_zcr_gaming_input_v1 */ static inline void @@ -137,7 +137,7 @@ /** * @ingroup iface_zcr_gaming_input_v1 * - * Create gamepad object. See zwp_gamepad_v1 interface for details. + * Create gamepad object. See zcr_gamepad_v1 interface for details. */ static inline struct zcr_gamepad_v1 * zcr_gaming_input_v1_get_gamepad(struct zcr_gaming_input_v1 *zcr_gaming_input_v1, struct wl_seat *seat) @@ -258,7 +258,7 @@ }; /** - * @ingroup zcr_gamepad_v1_iface + * @ingroup iface_zcr_gamepad_v1 */ static inline int zcr_gamepad_v1_add_listener(struct zcr_gamepad_v1 *zcr_gamepad_v1, @@ -268,12 +268,29 @@ (void (**)(void)) listener, data); } -#define ZCR_GAMEPAD_V1_DESTROY 0 +#define ZCR_GAMEPAD_V1_DESTROY 0 /** * @ingroup iface_zcr_gamepad_v1 */ -#define ZCR_GAMEPAD_V1_DESTROY_SINCE_VERSION 1 +#define ZCR_GAMEPAD_V1_STATE_CHANGE_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v1 + */ +#define ZCR_GAMEPAD_V1_AXIS_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v1 + */ +#define ZCR_GAMEPAD_V1_BUTTON_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v1 + */ +#define ZCR_GAMEPAD_V1_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gamepad_v1 + */ +#define ZCR_GAMEPAD_V1_DESTROY_SINCE_VERSION 1 /** @ingroup iface_zcr_gamepad_v1 */ static inline void
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h index 01e70a4..fb68f969 100644 --- a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.11.0 */ +/* Generated by wayland-scanner 1.12.90 */ #ifndef GAMING_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H #define GAMING_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H @@ -88,7 +88,7 @@ * @page page_iface_zcr_gamepad_v1 zcr_gamepad_v1 * @section page_iface_zcr_gamepad_v1_desc Description * - * The zwp_gamepad_v1 interface represents one or more gamepad input devices, + * The zcr_gamepad_v1 interface represents one or more gamepad input devices, * which are reported as a normalized 'Standard Gamepad' as it is specified * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping * @section page_iface_zcr_gamepad_v1_api API @@ -97,7 +97,7 @@ /** * @defgroup iface_zcr_gamepad_v1 The zcr_gamepad_v1 interface * - * The zwp_gamepad_v1 interface represents one or more gamepad input devices, + * The zcr_gamepad_v1 interface represents one or more gamepad input devices, * which are reported as a normalized 'Standard Gamepad' as it is specified * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping */ @@ -108,18 +108,22 @@ * @struct zcr_gaming_input_v1_interface */ struct zcr_gaming_input_v1_interface { - /** - * get gamepad device assigned to seat - * - * Create gamepad object. See zwp_gamepad_v1 interface for - * details. - */ - void (*get_gamepad)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *seat); + /** + * get gamepad device assigned to seat + * + * Create gamepad object. See zcr_gamepad_v1 interface for + * details. + */ + void (*get_gamepad)(struct wl_client* client, + struct wl_resource* resource, + uint32_t id, + struct wl_resource* seat); }; +/** + * @ingroup iface_zcr_gaming_input_v1 + */ +#define ZCR_GAMING_INPUT_V1_GET_GAMEPAD_SINCE_VERSION 1 #ifndef ZCR_GAMEPAD_V1_GAMEPAD_STATE_ENUM #define ZCR_GAMEPAD_V1_GAMEPAD_STATE_ENUM @@ -174,27 +178,32 @@ struct wl_resource *resource); }; -#define ZCR_GAMEPAD_V1_STATE_CHANGE 0 -#define ZCR_GAMEPAD_V1_AXIS 1 -#define ZCR_GAMEPAD_V1_BUTTON 2 -#define ZCR_GAMEPAD_V1_FRAME 3 +#define ZCR_GAMEPAD_V1_STATE_CHANGE 0 +#define ZCR_GAMEPAD_V1_AXIS 1 +#define ZCR_GAMEPAD_V1_BUTTON 2 +#define ZCR_GAMEPAD_V1_FRAME 3 /** * @ingroup iface_zcr_gamepad_v1 */ -#define ZCR_GAMEPAD_V1_STATE_CHANGE_SINCE_VERSION 1 +#define ZCR_GAMEPAD_V1_STATE_CHANGE_SINCE_VERSION 1 /** * @ingroup iface_zcr_gamepad_v1 */ -#define ZCR_GAMEPAD_V1_AXIS_SINCE_VERSION 1 +#define ZCR_GAMEPAD_V1_AXIS_SINCE_VERSION 1 /** * @ingroup iface_zcr_gamepad_v1 */ -#define ZCR_GAMEPAD_V1_BUTTON_SINCE_VERSION 1 +#define ZCR_GAMEPAD_V1_BUTTON_SINCE_VERSION 1 /** * @ingroup iface_zcr_gamepad_v1 */ -#define ZCR_GAMEPAD_V1_FRAME_SINCE_VERSION 1 +#define ZCR_GAMEPAD_V1_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gamepad_v1 + */ +#define ZCR_GAMEPAD_V1_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zcr_gamepad_v1
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-client-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-client-protocol.h new file mode 100644 index 0000000..8a7f0946 --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-client-protocol.h
@@ -0,0 +1,413 @@ +/* Generated by wayland-scanner 1.12.90 */ + +#ifndef GAMING_INPUT_UNSTABLE_V2_CLIENT_PROTOCOL_H +#define GAMING_INPUT_UNSTABLE_V2_CLIENT_PROTOCOL_H + +#include <stddef.h> +#include <stdint.h> +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_gaming_input_unstable_v2 The gaming_input_unstable_v2 protocol + * @section page_ifaces_gaming_input_unstable_v2 Interfaces + * - @subpage page_iface_zcr_gaming_input_v2 - extends wl_seat with gaming input + * devices - @subpage page_iface_zcr_gaming_seat_v2 - controller object for all + * gaming devices of a seat - @subpage page_iface_zcr_gamepad_v2 - gamepad input + * device + * @section page_copyright_gaming_input_unstable_v2 Copyright + * <pre> + * + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * </pre> + */ +struct wl_seat; +struct zcr_gamepad_v2; +struct zcr_gaming_input_v2; +struct zcr_gaming_seat_v2; + +/** + * @page page_iface_zcr_gaming_input_v2 zcr_gaming_input_v2 + * @section page_iface_zcr_gaming_input_v2_desc Description + * + * A global interface to provide gaming input devices for a given seat. + * + * Currently only gamepad devices are supported. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding uinterface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and uinterface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zcr_gaming_input_v2_api API + * See @ref iface_zcr_gaming_input_v2. + */ +/** + * @defgroup iface_zcr_gaming_input_v2 The zcr_gaming_input_v2 interface + * + * A global interface to provide gaming input devices for a given seat. + * + * Currently only gamepad devices are supported. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding uinterface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and uinterface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zcr_gaming_input_v2_interface; +/** + * @page page_iface_zcr_gaming_seat_v2 zcr_gaming_seat_v2 + * @section page_iface_zcr_gaming_seat_v2_desc Description + * + * An object that provides access to all the gaming devices of a seat. + * When a gamepad is connected, the compositor will send gamepad_added event. + * @section page_iface_zcr_gaming_seat_v2_api API + * See @ref iface_zcr_gaming_seat_v2. + */ +/** + * @defgroup iface_zcr_gaming_seat_v2 The zcr_gaming_seat_v2 interface + * + * An object that provides access to all the gaming devices of a seat. + * When a gamepad is connected, the compositor will send gamepad_added event. + */ +extern const struct wl_interface zcr_gaming_seat_v2_interface; +/** + * @page page_iface_zcr_gamepad_v2 zcr_gamepad_v2 + * @section page_iface_zcr_gamepad_v2_desc Description + * + * The zcr_gamepad_v2 interface represents one or more gamepad input devices, + * which are reported as a normalized 'Standard Gamepad' as it is specified + * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + * @section page_iface_zcr_gamepad_v2_api API + * See @ref iface_zcr_gamepad_v2. + */ +/** + * @defgroup iface_zcr_gamepad_v2 The zcr_gamepad_v2 interface + * + * The zcr_gamepad_v2 interface represents one or more gamepad input devices, + * which are reported as a normalized 'Standard Gamepad' as it is specified + * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + */ +extern const struct wl_interface zcr_gamepad_v2_interface; + +#define ZCR_GAMING_INPUT_V2_GET_GAMING_SEAT 0 +#define ZCR_GAMING_INPUT_V2_DESTROY 1 + +/** + * @ingroup iface_zcr_gaming_input_v2 + */ +#define ZCR_GAMING_INPUT_V2_GET_GAMING_SEAT_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gaming_input_v2 + */ +#define ZCR_GAMING_INPUT_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zcr_gaming_input_v2 */ +static inline void zcr_gaming_input_v2_set_user_data( + struct zcr_gaming_input_v2* zcr_gaming_input_v2, + void* user_data) { + wl_proxy_set_user_data((struct wl_proxy*)zcr_gaming_input_v2, user_data); +} + +/** @ingroup iface_zcr_gaming_input_v2 */ +static inline void* zcr_gaming_input_v2_get_user_data( + struct zcr_gaming_input_v2* zcr_gaming_input_v2) { + return wl_proxy_get_user_data((struct wl_proxy*)zcr_gaming_input_v2); +} + +static inline uint32_t zcr_gaming_input_v2_get_version( + struct zcr_gaming_input_v2* zcr_gaming_input_v2) { + return wl_proxy_get_version((struct wl_proxy*)zcr_gaming_input_v2); +} + +/** + * @ingroup iface_zcr_gaming_input_v2 + * + * Get a gaming seat object for a given seat. Gaming seat provides access + * to gaming devices + */ +static inline struct zcr_gaming_seat_v2* zcr_gaming_input_v2_get_gaming_seat( + struct zcr_gaming_input_v2* zcr_gaming_input_v2, + struct wl_seat* seat) { + struct wl_proxy* gaming_seat; + + gaming_seat = + wl_proxy_marshal_constructor((struct wl_proxy*)zcr_gaming_input_v2, + ZCR_GAMING_INPUT_V2_GET_GAMING_SEAT, + &zcr_gaming_seat_v2_interface, NULL, seat); + + return (struct zcr_gaming_seat_v2*)gaming_seat; +} + +/** + * @ingroup iface_zcr_gaming_input_v2 + * + * Destroy gaming_input object. Objects created from this object are + * unaffected and should be destroyed separately. + */ +static inline void zcr_gaming_input_v2_destroy( + struct zcr_gaming_input_v2* zcr_gaming_input_v2) { + wl_proxy_marshal((struct wl_proxy*)zcr_gaming_input_v2, + ZCR_GAMING_INPUT_V2_DESTROY); + + wl_proxy_destroy((struct wl_proxy*)zcr_gaming_input_v2); +} + +/** + * @ingroup iface_zcr_gaming_seat_v2 + * @struct zcr_gaming_seat_v2_listener + */ +struct zcr_gaming_seat_v2_listener { + /** + * gamepad added event + * + * Notification that there is gamepad connected at this seat. + * @param gamepad new connected gamepad + */ + void (*gamepad_added)(void* data, + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2, + struct zcr_gamepad_v2* gamepad); +}; + +/** + * @ingroup iface_zcr_gaming_seat_v2 + */ +static inline int zcr_gaming_seat_v2_add_listener( + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2, + const struct zcr_gaming_seat_v2_listener* listener, + void* data) { + return wl_proxy_add_listener((struct wl_proxy*)zcr_gaming_seat_v2, + (void (**)(void))listener, data); +} + +#define ZCR_GAMING_SEAT_V2_DESTROY 0 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + */ +#define ZCR_GAMING_SEAT_V2_GAMEPAD_ADDED_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + */ +#define ZCR_GAMING_SEAT_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zcr_gaming_seat_v2 */ +static inline void zcr_gaming_seat_v2_set_user_data( + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2, + void* user_data) { + wl_proxy_set_user_data((struct wl_proxy*)zcr_gaming_seat_v2, user_data); +} + +/** @ingroup iface_zcr_gaming_seat_v2 */ +static inline void* zcr_gaming_seat_v2_get_user_data( + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2) { + return wl_proxy_get_user_data((struct wl_proxy*)zcr_gaming_seat_v2); +} + +static inline uint32_t zcr_gaming_seat_v2_get_version( + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2) { + return wl_proxy_get_version((struct wl_proxy*)zcr_gaming_seat_v2); +} + +/** + * @ingroup iface_zcr_gaming_seat_v2 + * + * Destroy gaming_seat object. Objects created from this object are + * unaffected and should be destroyed separately. + */ +static inline void zcr_gaming_seat_v2_destroy( + struct zcr_gaming_seat_v2* zcr_gaming_seat_v2) { + wl_proxy_marshal((struct wl_proxy*)zcr_gaming_seat_v2, + ZCR_GAMING_SEAT_V2_DESTROY); + + wl_proxy_destroy((struct wl_proxy*)zcr_gaming_seat_v2); +} + +#ifndef ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM +#define ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM +/** + * @ingroup iface_zcr_gamepad_v2 + * physical button state + * + * Describes the physical state of a button that produced the button + * event. + */ +enum zcr_gamepad_v2_button_state { + /** + * the button is not pressed + */ + ZCR_GAMEPAD_V2_BUTTON_STATE_RELEASED = 0, + /** + * the button is pressed + */ + ZCR_GAMEPAD_V2_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM */ + +/** + * @ingroup iface_zcr_gamepad_v2 + * @struct zcr_gamepad_v2_listener + */ +struct zcr_gamepad_v2_listener { + /** + * gamepad removed + * + * Removed event is send when the gamepad is disconnected. The + * client should expect no more event and call destroy. + * + * This event cannot be used as destructor as requests (e.g. + * vibration) might be added to this interface. + */ + void (*removed)(void* data, struct zcr_gamepad_v2* zcr_gamepad_v2); + /** + * axis change event + * + * Notification of axis change. + * + * The axis id specifies which axis has changed as defined by the + * W3C 'Standard Gamepad'. + * + * The value is calibrated and normalized to the -1 to 1 range. + * @param time timestamp with millisecond granularity + * @param axis axis that produced this event + * @param value new value of axis + */ + void (*axis)(void* data, + struct zcr_gamepad_v2* zcr_gamepad_v2, + uint32_t time, + uint32_t axis, + wl_fixed_t value); + /** + * Gamepad button changed + * + * Notification of button change. + * + * The button id specifies which button has changed as defined by + * the W3C 'Standard Gamepad'. + * + * A button can have a digital and an analog value. The analog + * value is normalized to a 0 to 1 range. If a button does not + * provide an analog value, it will be derived from the digital + * state. + * @param time timestamp with millisecond granularity + * @param button id of button + * @param state digital state of the button + * @param analog analog value of the button + */ + void (*button)(void* data, + struct zcr_gamepad_v2* zcr_gamepad_v2, + uint32_t time, + uint32_t button, + uint32_t state, + wl_fixed_t analog); + /** + * Notifies end of a series of gamepad changes. + * + * Indicates the end of a set of events that logically belong + * together. A client is expected to accumulate the data in all + * events within the frame before proceeding. + * @param time timestamp with millisecond granularity + */ + void (*frame)(void* data, + struct zcr_gamepad_v2* zcr_gamepad_v2, + uint32_t time); +}; + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +static inline int zcr_gamepad_v2_add_listener( + struct zcr_gamepad_v2* zcr_gamepad_v2, + const struct zcr_gamepad_v2_listener* listener, + void* data) { + return wl_proxy_add_listener((struct wl_proxy*)zcr_gamepad_v2, + (void (**)(void))listener, data); +} + +#define ZCR_GAMEPAD_V2_DESTROY 0 + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_REMOVED_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_AXIS_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_BUTTON_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zcr_gamepad_v2 */ +static inline void zcr_gamepad_v2_set_user_data( + struct zcr_gamepad_v2* zcr_gamepad_v2, + void* user_data) { + wl_proxy_set_user_data((struct wl_proxy*)zcr_gamepad_v2, user_data); +} + +/** @ingroup iface_zcr_gamepad_v2 */ +static inline void* zcr_gamepad_v2_get_user_data( + struct zcr_gamepad_v2* zcr_gamepad_v2) { + return wl_proxy_get_user_data((struct wl_proxy*)zcr_gamepad_v2); +} + +static inline uint32_t zcr_gamepad_v2_get_version( + struct zcr_gamepad_v2* zcr_gamepad_v2) { + return wl_proxy_get_version((struct wl_proxy*)zcr_gamepad_v2); +} + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +static inline void zcr_gamepad_v2_destroy( + struct zcr_gamepad_v2* zcr_gamepad_v2) { + wl_proxy_marshal((struct wl_proxy*)zcr_gamepad_v2, ZCR_GAMEPAD_V2_DESTROY); + + wl_proxy_destroy((struct wl_proxy*)zcr_gamepad_v2); +} + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-server-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-server-protocol.h new file mode 100644 index 0000000..4a770d7e --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v2-server-protocol.h
@@ -0,0 +1,314 @@ +/* Generated by wayland-scanner 1.12.90 */ + +#ifndef GAMING_INPUT_UNSTABLE_V2_SERVER_PROTOCOL_H +#define GAMING_INPUT_UNSTABLE_V2_SERVER_PROTOCOL_H + +#include <stddef.h> +#include <stdint.h> +#include "wayland-server.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wl_client; +struct wl_resource; + +/** + * @page page_gaming_input_unstable_v2 The gaming_input_unstable_v2 protocol + * @section page_ifaces_gaming_input_unstable_v2 Interfaces + * - @subpage page_iface_zcr_gaming_input_v2 - extends wl_seat with gaming input + * devices - @subpage page_iface_zcr_gaming_seat_v2 - controller object for all + * gaming devices of a seat - @subpage page_iface_zcr_gamepad_v2 - gamepad input + * device + * @section page_copyright_gaming_input_unstable_v2 Copyright + * <pre> + * + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * </pre> + */ +struct wl_seat; +struct zcr_gamepad_v2; +struct zcr_gaming_input_v2; +struct zcr_gaming_seat_v2; + +/** + * @page page_iface_zcr_gaming_input_v2 zcr_gaming_input_v2 + * @section page_iface_zcr_gaming_input_v2_desc Description + * + * A global interface to provide gaming input devices for a given seat. + * + * Currently only gamepad devices are supported. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding uinterface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and uinterface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zcr_gaming_input_v2_api API + * See @ref iface_zcr_gaming_input_v2. + */ +/** + * @defgroup iface_zcr_gaming_input_v2 The zcr_gaming_input_v2 interface + * + * A global interface to provide gaming input devices for a given seat. + * + * Currently only gamepad devices are supported. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding uinterface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and uinterface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zcr_gaming_input_v2_interface; +/** + * @page page_iface_zcr_gaming_seat_v2 zcr_gaming_seat_v2 + * @section page_iface_zcr_gaming_seat_v2_desc Description + * + * An object that provides access to all the gaming devices of a seat. + * When a gamepad is connected, the compositor will send gamepad_added event. + * @section page_iface_zcr_gaming_seat_v2_api API + * See @ref iface_zcr_gaming_seat_v2. + */ +/** + * @defgroup iface_zcr_gaming_seat_v2 The zcr_gaming_seat_v2 interface + * + * An object that provides access to all the gaming devices of a seat. + * When a gamepad is connected, the compositor will send gamepad_added event. + */ +extern const struct wl_interface zcr_gaming_seat_v2_interface; +/** + * @page page_iface_zcr_gamepad_v2 zcr_gamepad_v2 + * @section page_iface_zcr_gamepad_v2_desc Description + * + * The zcr_gamepad_v2 interface represents one or more gamepad input devices, + * which are reported as a normalized 'Standard Gamepad' as it is specified + * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + * @section page_iface_zcr_gamepad_v2_api API + * See @ref iface_zcr_gamepad_v2. + */ +/** + * @defgroup iface_zcr_gamepad_v2 The zcr_gamepad_v2 interface + * + * The zcr_gamepad_v2 interface represents one or more gamepad input devices, + * which are reported as a normalized 'Standard Gamepad' as it is specified + * by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + */ +extern const struct wl_interface zcr_gamepad_v2_interface; + +/** + * @ingroup iface_zcr_gaming_input_v2 + * @struct zcr_gaming_input_v2_interface + */ +struct zcr_gaming_input_v2_interface { + /** + * get a gaming seat + * + * Get a gaming seat object for a given seat. Gaming seat + * provides access to gaming devices + */ + void (*get_gaming_seat)(struct wl_client* client, + struct wl_resource* resource, + uint32_t gaming_seat, + struct wl_resource* seat); + /** + * release the memory for the gaming input object + * + * Destroy gaming_input object. Objects created from this object + * are unaffected and should be destroyed separately. + */ + void (*destroy)(struct wl_client* client, struct wl_resource* resource); +}; + +/** + * @ingroup iface_zcr_gaming_input_v2 + */ +#define ZCR_GAMING_INPUT_V2_GET_GAMING_SEAT_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gaming_input_v2 + */ +#define ZCR_GAMING_INPUT_V2_DESTROY_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + * @struct zcr_gaming_seat_v2_interface + */ +struct zcr_gaming_seat_v2_interface { + /** + * release the memory for the gaming seat object + * + * Destroy gaming_seat object. Objects created from this object + * are unaffected and should be destroyed separately. + */ + void (*destroy)(struct wl_client* client, struct wl_resource* resource); +}; + +#define ZCR_GAMING_SEAT_V2_GAMEPAD_ADDED 0 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + */ +#define ZCR_GAMING_SEAT_V2_GAMEPAD_ADDED_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + */ +#define ZCR_GAMING_SEAT_V2_DESTROY_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gaming_seat_v2 + * Sends an gamepad_added event to the client owning the resource. + * @param resource_ The client's resource + * @param gamepad new connected gamepad + */ +static inline void zcr_gaming_seat_v2_send_gamepad_added( + struct wl_resource* resource_, + struct wl_resource* gamepad) { + wl_resource_post_event(resource_, ZCR_GAMING_SEAT_V2_GAMEPAD_ADDED, gamepad); +} + +#ifndef ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM +#define ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM +/** + * @ingroup iface_zcr_gamepad_v2 + * physical button state + * + * Describes the physical state of a button that produced the button + * event. + */ +enum zcr_gamepad_v2_button_state { + /** + * the button is not pressed + */ + ZCR_GAMEPAD_V2_BUTTON_STATE_RELEASED = 0, + /** + * the button is pressed + */ + ZCR_GAMEPAD_V2_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZCR_GAMEPAD_V2_BUTTON_STATE_ENUM */ + +/** + * @ingroup iface_zcr_gamepad_v2 + * @struct zcr_gamepad_v2_interface + */ +struct zcr_gamepad_v2_interface { + /** + * destroy gamepad object + * + * + */ + void (*destroy)(struct wl_client* client, struct wl_resource* resource); +}; + +#define ZCR_GAMEPAD_V2_REMOVED 0 +#define ZCR_GAMEPAD_V2_AXIS 1 +#define ZCR_GAMEPAD_V2_BUTTON 2 +#define ZCR_GAMEPAD_V2_FRAME 3 + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_REMOVED_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_AXIS_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_BUTTON_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gamepad_v2 + */ +#define ZCR_GAMEPAD_V2_DESTROY_SINCE_VERSION 1 + +/** + * @ingroup iface_zcr_gamepad_v2 + * Sends an removed event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void zcr_gamepad_v2_send_removed(struct wl_resource* resource_) { + wl_resource_post_event(resource_, ZCR_GAMEPAD_V2_REMOVED); +} + +/** + * @ingroup iface_zcr_gamepad_v2 + * Sends an axis event to the client owning the resource. + * @param resource_ The client's resource + * @param time timestamp with millisecond granularity + * @param axis axis that produced this event + * @param value new value of axis + */ +static inline void zcr_gamepad_v2_send_axis(struct wl_resource* resource_, + uint32_t time, + uint32_t axis, + wl_fixed_t value) { + wl_resource_post_event(resource_, ZCR_GAMEPAD_V2_AXIS, time, axis, value); +} + +/** + * @ingroup iface_zcr_gamepad_v2 + * Sends an button event to the client owning the resource. + * @param resource_ The client's resource + * @param time timestamp with millisecond granularity + * @param button id of button + * @param state digital state of the button + * @param analog analog value of the button + */ +static inline void zcr_gamepad_v2_send_button(struct wl_resource* resource_, + uint32_t time, + uint32_t button, + uint32_t state, + wl_fixed_t analog) { + wl_resource_post_event(resource_, ZCR_GAMEPAD_V2_BUTTON, time, button, state, + analog); +} + +/** + * @ingroup iface_zcr_gamepad_v2 + * Sends an frame event to the client owning the resource. + * @param resource_ The client's resource + * @param time timestamp with millisecond granularity + */ +static inline void zcr_gamepad_v2_send_frame(struct wl_resource* resource_, + uint32_t time) { + wl_resource_post_event(resource_, ZCR_GAMEPAD_V2_FRAME, time); +} + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/protocol/gaming-input-protocol.c b/third_party/wayland-protocols/protocol/gaming-input-protocol-v1.c similarity index 97% rename from third_party/wayland-protocols/protocol/gaming-input-protocol.c rename to third_party/wayland-protocols/protocol/gaming-input-protocol-v1.c index 13141c7c..1e682f8 100644 --- a/third_party/wayland-protocols/protocol/gaming-input-protocol.c +++ b/third_party/wayland-protocols/protocol/gaming-input-protocol-v1.c
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.11.0 */ +/* Generated by wayland-scanner 1.12.90 */ /* * Copyright 2016 The Chromium Authors.
diff --git a/third_party/wayland-protocols/protocol/gaming-input-protocol-v2.c b/third_party/wayland-protocols/protocol/gaming-input-protocol-v2.c new file mode 100644 index 0000000..f7cf202 --- /dev/null +++ b/third_party/wayland-protocols/protocol/gaming-input-protocol-v2.c
@@ -0,0 +1,85 @@ +/* Generated by wayland-scanner 1.12.90 */ + +/* + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface zcr_gamepad_v2_interface; +extern const struct wl_interface zcr_gaming_seat_v2_interface; + +static const struct wl_interface *types[] = { + NULL, + NULL, + NULL, + NULL, + &zcr_gaming_seat_v2_interface, + &wl_seat_interface, + &zcr_gamepad_v2_interface, +}; + +static const struct wl_message zcr_gaming_input_v2_requests[] = { + { "get_gaming_seat", "no", types + 4 }, + { "destroy", "", types + 0 }, +}; + +WL_EXPORT const struct wl_interface zcr_gaming_input_v2_interface = { + "zcr_gaming_input_v2", 1, + 2, zcr_gaming_input_v2_requests, + 0, NULL, +}; + +static const struct wl_message zcr_gaming_seat_v2_requests[] = { + { "destroy", "", types + 0 }, +}; + +static const struct wl_message zcr_gaming_seat_v2_events[] = { + { "gamepad_added", "n", types + 6 }, +}; + +WL_EXPORT const struct wl_interface zcr_gaming_seat_v2_interface = { + "zcr_gaming_seat_v2", 1, + 1, zcr_gaming_seat_v2_requests, + 1, zcr_gaming_seat_v2_events, +}; + +static const struct wl_message zcr_gamepad_v2_requests[] = { + { "destroy", "", types + 0 }, +}; + +static const struct wl_message zcr_gamepad_v2_events[] = { + { "removed", "", types + 0 }, + { "axis", "uuf", types + 0 }, + { "button", "uuuf", types + 0 }, + { "frame", "u", types + 0 }, +}; + +WL_EXPORT const struct wl_interface zcr_gamepad_v2_interface = { + "zcr_gamepad_v2", 1, + 1, zcr_gamepad_v2_requests, + 4, zcr_gamepad_v2_events, +}; +
diff --git a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml new file mode 100644 index 0000000..9e9f35e --- /dev/null +++ b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml
@@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="gaming_input_unstable_v2"> + + <copyright> + Copyright 2016 The Chromium Authors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + + <interface name="zcr_gaming_input_v2" version="1"> + <description summary="extends wl_seat with gaming input devices"> + A global interface to provide gaming input devices for a given seat. + + Currently only gamepad devices are supported. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding uinterface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and uinterface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + </description> + + <request name="get_gaming_seat"> + <description summary="get a gaming seat"> + Get a gaming seat object for a given seat. Gaming seat provides access + to gaming devices + </description> + <arg name="gaming_seat" type="new_id" interface="zcr_gaming_seat_v2"/> + <arg name="seat" type="object" interface="wl_seat"/> + </request> + + <request name="destroy" type="destructor"> + <description summary="release the memory for the gaming input object"> + Destroy gaming_input object. Objects created from this object are + unaffected and should be destroyed separately. + </description> + </request> + </interface> + + <interface name="zcr_gaming_seat_v2" version="1"> + <description summary="controller object for all gaming devices of a seat"> + An object that provides access to all the gaming devices of a seat. + When a gamepad is connected, the compositor will send gamepad_added event. + </description> + + <request name="destroy" type="destructor"> + <description summary="release the memory for the gaming seat object"> + Destroy gaming_seat object. Objects created from this object are + unaffected and should be destroyed separately. + </description> + </request> + + <event name="gamepad_added"> + <description summary="gamepad added event"> + Notification that there is gamepad connected at this seat. + </description> + <arg name="gamepad" type="new_id" interface="zcr_gamepad_v2" summary="new connected gamepad"/> + </event> + </interface> + + <interface name="zcr_gamepad_v2" version="1"> + <description summary="gamepad input device"> + The zcr_gamepad_v2 interface represents one or more gamepad input devices, + which are reported as a normalized 'Standard Gamepad' as it is specified + by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy gamepad object"/> + </request> + + <event name="removed"> + <description summary="gamepad removed"> + Removed event is send when the gamepad is disconnected. The client should + expect no more event and call destroy. + + This event cannot be used as destructor as requests (e.g. vibration) might + be added to this interface. + </description> + </event> + + <event name="axis"> + <description summary="axis change event"> + Notification of axis change. + + The axis id specifies which axis has changed as defined by the W3C + 'Standard Gamepad'. + + The value is calibrated and normalized to the -1 to 1 range. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="axis" type="uint" summary="axis that produced this event"/> + <arg name="value" type="fixed" summary="new value of axis"/> + </event> + + <enum name="button_state"> + <description summary="physical button state"> + Describes the physical state of a button that produced the button + event. + </description> + <entry name="released" value="0" summary="the button is not pressed"/> + <entry name="pressed" value="1" summary="the button is pressed"/> + </enum> + + <event name="button"> + <description summary="Gamepad button changed"> + Notification of button change. + + The button id specifies which button has changed as defined by the W3C + 'Standard Gamepad'. + + A button can have a digital and an analog value. The analog value is + normalized to a 0 to 1 range. + If a button does not provide an analog value, it will be derived from + the digital state. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="button" type="uint" summary="id of button"/> + <arg name="state" type="uint" enum="button_state" summary="digital state of the button"/> + <arg name="analog" type="fixed" summary="analog value of the button"/> + </event> + + <event name="frame"> + <description summary="Notifies end of a series of gamepad changes."> + Indicates the end of a set of events that logically belong together. + A client is expected to accumulate the data in all events within the + frame before proceeding. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + </event> + </interface> +</protocol>
diff --git a/tools/chrome_proxy/webdriver/compression_regression.py b/tools/chrome_proxy/webdriver/compression_regression.py index f6b1ee6..9f89a220 100644 --- a/tools/chrome_proxy/webdriver/compression_regression.py +++ b/tools/chrome_proxy/webdriver/compression_regression.py
@@ -11,6 +11,7 @@ import common from common import TestDriver from common import IntegrationTest +from common import NotAndroid # The maximum number of data points that will be saved. MAX_DATA_POINTS = 365 @@ -66,6 +67,7 @@ classified as a regression test. """ + @NotAndroid def testCompression(self): """This function is the main test function for regression compression checking and facilitates the test with all of the helper functions'
diff --git a/tools/chrome_proxy/webdriver/data_use.py b/tools/chrome_proxy/webdriver/data_use.py index c241b8c5..b91c760e 100644 --- a/tools/chrome_proxy/webdriver/data_use.py +++ b/tools/chrome_proxy/webdriver/data_use.py
@@ -7,10 +7,13 @@ import common from common import TestDriver from common import IntegrationTest +from common import NotAndroid class DataUseAscription(IntegrationTest): + # This test uses a desktop extension and cannot be run on Android. + @NotAndroid def testDataUseAscription(self): ext_path = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, 'chrome', 'test', 'data',
diff --git a/tools/chrome_proxy/webdriver/smoke.py b/tools/chrome_proxy/webdriver/smoke.py index b54dd7f..1da694c3 100644 --- a/tools/chrome_proxy/webdriver/smoke.py +++ b/tools/chrome_proxy/webdriver/smoke.py
@@ -5,11 +5,14 @@ import common from common import TestDriver from common import IntegrationTest +from common import NotAndroid class Smoke(IntegrationTest): # Ensure Chrome does not use DataSaver in Incognito mode. + # Clank does not honor the --incognito flag. + @NotAndroid def testCheckPageWithIncognito(self): with TestDriver() as t: t.AddChromeArg('--enable-spdy-proxy-auth') @@ -31,5 +34,19 @@ for response in responses: self.assertHasChromeProxyViaHeader(response) + # Ensure pageload metric pingback with DataSaver. + def testPingback(self): + with TestDriver() as t: + t.AddChromeArg('--enable-spdy-proxy-auth') + t.AddChromeArg('--enable-data-reduction-proxy-force-pingback') + t.LoadURL('http://check.googlezip.net/test.html') + t.LoadURL('http://check.googlezip.net/test.html') + t.SleepUntilHistogramHasEntry("DataReductionProxy.Pingback.Succeeded") + # Verify one pingback attempt that was successful. + attempted = t.GetHistogram('DataReductionProxy.Pingback.Attempted') + self.assertEqual(1, attempted['count']) + succeeded = t.GetHistogram('DataReductionProxy.Pingback.Succeeded') + self.assertEqual(1, succeeded['count']) + if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/chrome_proxy/webdriver/video.py b/tools/chrome_proxy/webdriver/video.py index c080b8b..2d59f2b 100644 --- a/tools/chrome_proxy/webdriver/video.py +++ b/tools/chrome_proxy/webdriver/video.py
@@ -18,7 +18,9 @@ t.AddChromeArg('--enable-spdy-proxy-auth') t.LoadURL( 'http://check.googlezip.net/cacheable/video/buck_bunny_tiny.html') - for response in t.GetHTTPResponses(): + responses = t.GetHTTPResponses() + self.assertEquals(2, len(responses)) + for response in responses: self.assertHasChromeProxyViaHeader(response) # Videos fetched via an XHR request should not be proxied. @@ -45,6 +47,7 @@ # Check the compressed video has the same frame count, width, height, and # duration as uncompressed. + @NotAndroid def testVideoMetrics(self): expected = { 'duration': 3.124, @@ -75,10 +78,12 @@ % (metric, expected[metric], actual), places=None, delta=0.001) # Check the frames of a compressed video. + @NotAndroid def testVideoFrames(self): self.instrumentedVideoTest('http://check.googlezip.net/cacheable/video/buck_bunny_640x360_24fps_video.html') # Check the audio volume of a compressed video. + @NotAndroid def testVideoAudio(self): self.instrumentedVideoTest('http://check.googlezip.net/cacheable/video/buck_bunny_640x360_24fps_audio.html')
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 1b54700d..c4b883dd 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -14330,6 +14330,23 @@ <description>Please enter the description of this user action.</description> </action> +<action name="SettingsResetPrompt_Accepted"> + <owner>alito@chromium.org</owner> + <description>The user accepted the settings reset prompt.</description> +</action> + +<action name="SettingsResetPrompt_Declined"> + <owner>alito@chromium.org</owner> + <description>The user declined the settings reset prompt.</description> +</action> + +<action name="SettingsResetPrompt_Shown"> + <owner>alito@chromium.org</owner> + <description> + The settings reset dialog was displayed to the user. + </description> +</action> + <action name="Shelf_AlignmentSetBottom"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 7a57cf1..bdbb9a92 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -388,6 +388,15 @@ </summary> </histogram> +<histogram name="ActivityTracker.Collect.SystemSessionAnalysisStatus" + enum="ActivityTrackerSystemSessionAnalysisStatus"> + <owner>manzagop@chromium.org</owner> + <summary> + Status for the analysis of the system session state. Logged each time a + debug file is collected. + </summary> +</histogram> + <histogram name="ActivityTracker.Collect.TotalTime" units="ms"> <owner>manzagop@chromium.org</owner> <summary> @@ -64151,6 +64160,89 @@ </summary> </histogram> +<histogram name="SettingsResetPrompt.DelayBeforePromptParam" units="seconds"> + <owner>alito@chromium.org</owner> + <summary> + The feature parameter determining the amount of time to wait after startup + before attempting to show the settings reset prompt. Logged once after + startup. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.DialogShown" enum="BooleanShown"> + <owner>alito@chromium.org</owner> + <summary> + Indicates whether the settings reset prompt dialog was shown to the user. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.NumberOfExtensionsDisabled" + units="extensions"> + <owner>alito@chromium.org</owner> + <summary> + The number of extensions that were disabled after the user accepted the + settings reset prompt. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.NumberOfExtensionsToDisable" + units="extensions"> + <owner>alito@chromium.org</owner> + <summary> + The number of extensions that will be disabled if the user accepts the + settings reset prompt. Logged once after startup. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.PromptAccepted" enum="BooleanAccepted"> + <owner>alito@chromium.org</owner> + <summary> + Indicates whether the user accepted the settings reset prompt. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.PromptRequired" enum="BooleanRequired"> + <owner>alito@chromium.org</owner> + <summary> + Indicates whether the settings reset prompt should be shown to the user + based on the state of the user's settings. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.ResetState" + enum="SettingsResetPromptResetState"> + <owner>alito@chromium.org</owner> + <summary> + Indicates whether the settings reset prompt is enabled for the user's + setting, or the reason for it being disabled. Logged once after startup. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.SettingsReset" + enum="SettingsResetPromptSettingsReset"> + <owner>alito@chromium.org</owner> + <summary> + Indicates which settings were reset after the user accepted the settings + reset prompt. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.TimeUntilAccepted" units="ms"> + <owner>alito@chromium.org</owner> + <summary> + The time between the settings reset prompt dialog being shown and the user + accepting the prompt. + </summary> +</histogram> + +<histogram name="SettingsResetPrompt.TimeUntilDeclined" units="ms"> + <owner>alito@chromium.org</owner> + <summary> + The time between the settings reset prompt dialog being shown and the user + declining the prompt. + </summary> +</histogram> + <histogram name="Setup.Install.ApplyArchivePatchTime" units="ms"> <owner>grt@chromium.org</owner> <summary> @@ -80145,6 +80237,14 @@ <int value="2" label="Get stability file path failed"/> </enum> +<enum name="ActivityTrackerSystemSessionAnalysisStatus" type="int"> + <int value="0" label="Success"/> + <int value="1" label="Missing timestamp"/> + <int value="2" label="Missing analyzer"/> + <int value="3" label="Analysis failed"/> + <int value="4" label="Outside range"/> +</enum> + <enum name="ActivityTrackerWriteDumpStatus" type="int"> <int value="0" label="Sucess"/> <int value="1" label="Failed"/> @@ -82679,6 +82779,11 @@ <int value="1" label="Requested"/> </enum> +<enum name="BooleanRequired" type="int"> + <int value="0" label="Not required"/> + <int value="1" label="Required"/> +</enum> + <enum name="BooleanReset" type="int"> <int value="0" label="Not reset"/> <int value="1" label="Reset"/> @@ -108544,6 +108649,21 @@ <int value="9" label="Bad time_between_prompts_seconds param"/> </enum> +<enum name="SettingsResetPromptResetState" type="int"> + <int value="1" label="Reset required"/> + <int value="2" label="Domain not matched, no reset required"/> + <int value="3" label="Already prompted for setting, no reset required"/> + <int value="4" label="Recently prompted, no reset required"/> + <int value="5" label="Other setting requires reset, no reset required"/> + <int value="6" label="Policy detected, no reset required"/> +</enum> + +<enum name="SettingsResetPromptSettingsReset" type="int"> + <int value="1" label="Homepage"/> + <int value="2" label="Default search engine"/> + <int value="3" label="Startup URLs"/> +</enum> + <enum name="SettingsSections" type="int"> <summary> A collection of sections from chrome://settings. Used for metrics about @@ -121483,6 +121603,13 @@ <affected-histogram name="SessionRestore.ForegroundTabFirstPaint3"/> </histogram_suffixes> +<histogram_suffixes name="SettingsResetPromptSettingType"> + <suffix name="DefaultSearch" label="Reset state for default search engine."/> + <suffix name="StartupUrls" label="Reset state for startup URLs."/> + <suffix name="Homepage" label="Reset state for homepage."/> + <affected-histogram name="SettingsResetPrompt.ResetState"/> +</histogram_suffixes> + <histogram_suffixes name="SetupInstallTimes" separator="."> <suffix name="background" label="Background; lowered priority."/> <affected-histogram name="Setup.Install.ApplyArchivePatchTime"/>
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py index 3c0fcc33..e9124438 100644 --- a/tools/perf/benchmarks/system_health.py +++ b/tools/perf/benchmarks/system_health.py
@@ -39,6 +39,7 @@ options.config.chrome_trace_config.category_filter.AddFilterString('rail') options.config.enable_battor_trace = True options.config.enable_chrome_trace = True + options.config.enable_cpu_trace = True options.SetTimelineBasedMetrics([ 'clockSyncLatencyMetric', 'powerMetric',
diff --git a/tools/traffic_annotation/sample_traffic_annotation.cc b/tools/traffic_annotation/sample_traffic_annotation.cc index 45a191c2..f771529 100644 --- a/tools/traffic_annotation/sample_traffic_annotation.cc +++ b/tools/traffic_annotation/sample_traffic_annotation.cc
@@ -8,7 +8,7 @@ // For more description on each field, please refer to: // tools/traffic_annotation/traffic_annotation.proto // and -// out/Debug/gen/components/policy/proto/cloud_policy.proto +// out/Debug/gen/components/policy/proto/chrome_settings.proto // For more information on policies, please refer to: // http://dev.chromium.org/administrators/policy-list-3 @@ -38,10 +38,10 @@ "You can enable or disable this feature via 'Use a web service to " "help resolve spelling errors.' in Chrome's settings under " "Advanced. The feature is disabled by default." - policy { + chrome_policy { SpellCheckServiceEnabled { policy_options {mode: MANDATORY} - value: false + SpellCheckServiceEnabled: false } } })"); @@ -61,10 +61,10 @@ cookies_allowed: false/true cookies_store: "..." setting: "..." - policy { + chrome_policy { [POLICY_NAME] { policy_options {mode: MANDATORY/RECOMMENDED/UNSET} - value: ... + [POLICY_NAME]: ... } } policy_exception_justification = "..."
diff --git a/tools/traffic_annotation/traffic_annotation.proto b/tools/traffic_annotation/traffic_annotation.proto index 8f8d43c..4e6a709 100644 --- a/tools/traffic_annotation/traffic_annotation.proto +++ b/tools/traffic_annotation/traffic_annotation.proto
@@ -5,10 +5,10 @@ syntax = "proto3"; package traffic_annotation; -// cloud_policy_full_runtime.proto is a version of the following proto without -// lite runtime optimization: -// out/Debug/gen/components/policy/proto/cloud_policy.proto -import "cloud_policy_full_runtime.proto"; +// chrome_settings_full_runtime.proto is a version of the following proto +// without lite runtime optimization: +// out/Debug/gen/components/policy/proto/chrome_settings.proto +import "chrome_settings_full_runtime.proto"; // Describes a specific kind of network traffic based on a fine-grained // semantic classification of all network traffic generated by Chrome. @@ -155,8 +155,8 @@ // Example policy configuration that disables this network request. // This would be a text serialized protobuf of any enterprise policy. - // see out/Debug/gen/components/policy/proto/cloud_policy.proto - repeated enterprise_management.CloudPolicySettings policy = 4; + // see out/Debug/gen/components/policy/proto/chrome_settings.proto + repeated enterprise_management.ChromeSettingsProto chrome_policy = 4; // Justification for not having a policy that disables this feature. string policy_exception_justification = 5;
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn index 643971c..3d71046 100644 --- a/ui/display/BUILD.gn +++ b/ui/display/BUILD.gn
@@ -22,6 +22,8 @@ "display_list.h", "display_observer.cc", "display_observer.h", + "display_snapshot_mojo.cc", + "display_snapshot_mojo.h", "display_switches.cc", "display_switches.h", "fake_display_delegate.cc",
diff --git a/ui/display/display_snapshot_mojo.cc b/ui/display/display_snapshot_mojo.cc new file mode 100644 index 0000000..53b1779 --- /dev/null +++ b/ui/display/display_snapshot_mojo.cc
@@ -0,0 +1,64 @@ +// Copyright 2017 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 "ui/display/display_snapshot_mojo.h" + +#include "base/memory/ptr_util.h" +#include "ui/display/types/display_constants.h" + +namespace display { + +DisplaySnapshotMojo::DisplaySnapshotMojo(int64_t display_id, + const gfx::Point& origin, + const gfx::Size& physical_size, + DisplayConnectionType type, + bool is_aspect_preserving_scaling, + bool has_overscan, + bool has_color_correction_matrix, + std::string display_name, + const base::FilePath& sys_path, + int64_t product_id, + DisplayModeList modes, + const std::vector<uint8_t>& edid, + const DisplayMode* current_mode, + const DisplayMode* native_mode, + const gfx::Size& maximum_cursor_size) + : DisplaySnapshot(display_id, + origin, + physical_size, + type, + is_aspect_preserving_scaling, + has_overscan, + has_color_correction_matrix, + display_name, + sys_path, + std::move(modes), + edid, + current_mode, + native_mode) { + product_id_ = product_id; + maximum_cursor_size_ = maximum_cursor_size; +} + +DisplaySnapshotMojo::~DisplaySnapshotMojo() = default; + +std::unique_ptr<DisplaySnapshotMojo> DisplaySnapshotMojo::Clone() const { + DisplayModeList clone_modes; + for (auto& mode : modes()) + clone_modes.push_back(mode->Clone()); + + return base::MakeUnique<DisplaySnapshotMojo>( + display_id(), origin(), physical_size(), type(), + is_aspect_preserving_scaling(), has_overscan(), + has_color_correction_matrix(), display_name(), sys_path(), product_id(), + std::move(clone_modes), edid(), current_mode(), native_mode(), + maximum_cursor_size()); +} + +// TODO(thanhph): Implement ToString() for debugging purposes. +std::string DisplaySnapshotMojo::ToString() const { + return ""; +} + +} // namespace display
diff --git a/ui/display/display_snapshot_mojo.h b/ui/display/display_snapshot_mojo.h new file mode 100644 index 0000000..fb669fe --- /dev/null +++ b/ui/display/display_snapshot_mojo.h
@@ -0,0 +1,46 @@ +// Copyright 2017 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 UI_DISPLAY_DISPLAY_SNAPSHOT_MOJO_H_ +#define UI_DISPLAY_DISPLAY_SNAPSHOT_MOJO_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/display/display_export.h" +#include "ui/display/types/display_snapshot.h" + +namespace display { + +// DisplaySnapshot implementation that can be used with Mojo IPC. +class DISPLAY_EXPORT DisplaySnapshotMojo : public DisplaySnapshot { + public: + DisplaySnapshotMojo(int64_t display_id, + const gfx::Point& origin, + const gfx::Size& physical_size, + DisplayConnectionType type, + bool is_aspect_preserving_scaling, + bool has_overscan, + bool has_color_correction_matrix, + std::string display_name, + const base::FilePath& sys_path, + int64_t product_id, + DisplayModeList modes, + const std::vector<uint8_t>& edid, + const DisplayMode* current_mode, + const DisplayMode* native_mode, + const gfx::Size& maximum_cursor_size); + ~DisplaySnapshotMojo() override; + std::unique_ptr<DisplaySnapshotMojo> Clone() const; + + // DisplaySnapshot: + std::string ToString() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(DisplaySnapshotMojo); +}; + +} // namespace display + +#endif // UI_DISPLAY_DISPLAY_SNAPSHOT_MOJO_H_
diff --git a/ui/display/mojo/BUILD.gn b/ui/display/mojo/BUILD.gn index d39f3431..98cb6e6a 100644 --- a/ui/display/mojo/BUILD.gn +++ b/ui/display/mojo/BUILD.gn
@@ -7,12 +7,15 @@ mojom("interfaces") { sources = [ "display.mojom", + "display_constants.mojom", "display_layout.mojom", "display_mode.mojom", + "display_snapshot_mojo.mojom", "gamma_ramp_rgb_entry.mojom", ] public_deps = [ + "//mojo/common:common_custom_types", "//ui/gfx/geometry/mojo", ] }
diff --git a/ui/display/mojo/display_constants.mojom b/ui/display/mojo/display_constants.mojom new file mode 100644 index 0000000..7ea2469 --- /dev/null +++ b/ui/display/mojo/display_constants.mojom
@@ -0,0 +1,18 @@ +// Copyright 2017 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. + +module display.mojom; + +// Corresponding to display::DisplayConnectionType. +enum DisplayConnectionType { + DISPLAY_CONNECTION_TYPE_NONE = 0, + DISPLAY_CONNECTION_TYPE_UNKNOWN = 1, + DISPLAY_CONNECTION_TYPE_INTERNAL = 2, + DISPLAY_CONNECTION_TYPE_VGA = 4, + DISPLAY_CONNECTION_TYPE_HDMI = 8, + DISPLAY_CONNECTION_TYPE_DVI = 16, + DISPLAY_CONNECTION_TYPE_DISPLAYPORT = 32, + DISPLAY_CONNECTION_TYPE_NETWORK = 64, + DISPLAY_CONNECTION_TYPE_VIRTUAL = 128, +};
diff --git a/ui/display/mojo/display_constants.typemap b/ui/display/mojo/display_constants.typemap new file mode 100644 index 0000000..725ab17 --- /dev/null +++ b/ui/display/mojo/display_constants.typemap
@@ -0,0 +1,15 @@ +# Copyright 2017 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. + +mojom = "//ui/display/mojo/display_constants.mojom" +public_headers = [ "//ui/display/types/display_constants.h" ] +traits_headers = [ "//ui/display/mojo/display_constants_struct_traits.h" ] +sources = [ + "//ui/display/mojo/display_constants_struct_traits.cc", +] +public_deps = [ + "//ui/display", +] +type_mappings = + [ "display.mojom.DisplayConnectionType=display::DisplayConnectionType" ]
diff --git a/ui/display/mojo/display_constants_struct_traits.cc b/ui/display/mojo/display_constants_struct_traits.cc new file mode 100644 index 0000000..fd71086 --- /dev/null +++ b/ui/display/mojo/display_constants_struct_traits.cc
@@ -0,0 +1,99 @@ +// Copyright 2017 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 "ui/display/mojo/display_constants_struct_traits.h" + +namespace mojo { + +display::mojom::DisplayConnectionType EnumTraits< + display::mojom::DisplayConnectionType, + display::DisplayConnectionType>::ToMojom(display::DisplayConnectionType + type) { + switch (type) { + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_NONE; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_UNKNOWN: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_UNKNOWN; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_INTERNAL: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_INTERNAL; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VGA: + return display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VGA; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_HDMI: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_HDMI; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DVI: + return display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DVI; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DISPLAYPORT: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_DISPLAYPORT; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NETWORK: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_NETWORK; + + case display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VIRTUAL: + return display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_VIRTUAL; + } + NOTREACHED(); + return display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE; +} + +bool EnumTraits<display::mojom::DisplayConnectionType, + display::DisplayConnectionType>:: + FromMojom(display::mojom::DisplayConnectionType type, + display::DisplayConnectionType* out) { + switch (type) { + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_UNKNOWN: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_UNKNOWN; + return true; + + case display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_INTERNAL: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_INTERNAL; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VGA: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VGA; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_HDMI: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_HDMI; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DVI: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DVI; + return true; + + case display::mojom::DisplayConnectionType:: + DISPLAY_CONNECTION_TYPE_DISPLAYPORT: + *out = + display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_DISPLAYPORT; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NETWORK: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NETWORK; + return true; + + case display::mojom::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VIRTUAL: + *out = display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_VIRTUAL; + return true; + } + return false; +} + +} // namespace mojo
diff --git a/ui/display/mojo/display_constants_struct_traits.h b/ui/display/mojo/display_constants_struct_traits.h new file mode 100644 index 0000000..bb7c13e --- /dev/null +++ b/ui/display/mojo/display_constants_struct_traits.h
@@ -0,0 +1,24 @@ +// Copyright 2017 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 UI_DISPLAY_MOJO_DISPLAY_CONSTANTS_STRUCT_TRAITS_H_ +#define UI_DISPLAY_MOJO_DISPLAY_CONSTANTS_STRUCT_TRAITS_H_ + +#include "ui/display/mojo/display_constants.mojom.h" +#include "ui/display/types/display_constants.h" + +namespace mojo { + +template <> +struct EnumTraits<display::mojom::DisplayConnectionType, + display::DisplayConnectionType> { + static display::mojom::DisplayConnectionType ToMojom( + display::DisplayConnectionType type); + static bool FromMojom(display::mojom::DisplayConnectionType type, + display::DisplayConnectionType* out); +}; + +}; // namespace mojo + +#endif // UI_DISPLAY_MOJO_DISPLAY_CONSTANTS_STRUCT_TRAITS_H_ \ No newline at end of file
diff --git a/ui/display/mojo/display_mode.typemap b/ui/display/mojo/display_mode.typemap index c37f44507..fc1f37d4 100644 --- a/ui/display/mojo/display_mode.typemap +++ b/ui/display/mojo/display_mode.typemap
@@ -5,6 +5,9 @@ mojom = "//ui/display/mojo/display_mode.mojom" public_headers = [ "//ui/display/types/display_mode.h" ] traits_headers = [ "//ui/display/mojo/display_mode_struct_traits.h" ] +sources = [ + "//ui/display/mojo/display_mode_struct_traits.cc", +] public_deps = [ "//ui/display", ]
diff --git a/ui/display/mojo/display_mode_struct_traits.cc b/ui/display/mojo/display_mode_struct_traits.cc new file mode 100644 index 0000000..2c5d791 --- /dev/null +++ b/ui/display/mojo/display_mode_struct_traits.cc
@@ -0,0 +1,24 @@ +// Copyright 2017 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 "ui/display/mojo/display_mode_struct_traits.h" + +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" + +namespace mojo { + +// static +bool StructTraits<display::mojom::DisplayModeDataView, + std::unique_ptr<display::DisplayMode>>:: + Read(display::mojom::DisplayModeDataView data, + std::unique_ptr<display::DisplayMode>* out) { + gfx::Size size; + if (!data.ReadSize(&size)) + return false; + *out = base::MakeUnique<display::DisplayMode>(size, data.is_interlaced(), + data.refresh_rate()); + return true; +}; + +} // namespace mojo
diff --git a/ui/display/mojo/display_mode_struct_traits.h b/ui/display/mojo/display_mode_struct_traits.h index 8d7d2bc0..2990846d 100644 --- a/ui/display/mojo/display_mode_struct_traits.h +++ b/ui/display/mojo/display_mode_struct_traits.h
@@ -30,14 +30,7 @@ } static bool Read(display::mojom::DisplayModeDataView data, - std::unique_ptr<display::DisplayMode>* out) { - gfx::Size size; - if (!data.ReadSize(&size)) - return false; - *out = base::MakeUnique<display::DisplayMode>(size, data.is_interlaced(), - data.refresh_rate()); - return true; - } + std::unique_ptr<display::DisplayMode>* out); }; } // namespace mojo
diff --git a/ui/display/mojo/display_snapshot_mojo.mojom b/ui/display/mojo/display_snapshot_mojo.mojom new file mode 100644 index 0000000..8b7ce1c5 --- /dev/null +++ b/ui/display/mojo/display_snapshot_mojo.mojom
@@ -0,0 +1,31 @@ +// Copyright 2017 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. + +module display.mojom; + +import "mojo/common/file_path.mojom"; +import "ui/display/mojo/display_constants.mojom"; +import "ui/display/mojo/display_mode.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; + +// Corresponds to display::DisplaySnapshotMojo. +struct DisplaySnapshotMojo { + int64 display_id; + gfx.mojom.Point origin; + gfx.mojom.Size physical_size; + display.mojom.DisplayConnectionType type; + bool is_aspect_preserving_scaling; + bool has_overscan; + bool has_color_correction_matrix; + string display_name; + mojo.common.mojom.FilePath sys_path; + array<display.mojom.DisplayMode> modes; + array<uint8> edid; + uint64 current_mode_index; + bool has_current_mode; + uint64 native_mode_index; + bool has_native_mode; + int64 product_id; + gfx.mojom.Size maximum_cursor_size; +};
diff --git a/ui/display/mojo/display_snapshot_mojo.typemap b/ui/display/mojo/display_snapshot_mojo.typemap new file mode 100644 index 0000000..5a831be --- /dev/null +++ b/ui/display/mojo/display_snapshot_mojo.typemap
@@ -0,0 +1,17 @@ +# Copyright 2017 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. + +mojom = "//ui/display/mojo/display_snapshot_mojo.mojom" +public_headers = [ "//ui/display/display_snapshot_mojo.h" ] +traits_headers = [ "//ui/display/mojo/display_snapshot_mojo_struct_traits.h" ] +sources = [ + "//ui/display/mojo/display_snapshot_mojo_struct_traits.cc", +] +public_deps = [ + "//ui/display", +] +deps = [ + "//ui/gfx/geometry", +] +type_mappings = [ "display.mojom.DisplaySnapshotMojo=std::unique_ptr<display::DisplaySnapshotMojo>[move_only]" ]
diff --git a/ui/display/mojo/display_snapshot_mojo_struct_traits.cc b/ui/display/mojo/display_snapshot_mojo_struct_traits.cc new file mode 100644 index 0000000..0a490e5 --- /dev/null +++ b/ui/display/mojo/display_snapshot_mojo_struct_traits.cc
@@ -0,0 +1,139 @@ +// Copyright 2017 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 "ui/display/mojo/display_snapshot_mojo_struct_traits.h" + +#include "ipc/ipc_message_utils.h" +#include "ui/display/mojo/display_constants_struct_traits.h" +#include "ui/display/mojo/display_mode_struct_traits.h" +#include "ui/display/types/display_constants.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "ui/gfx/geometry/size.h" + +namespace mojo { + +namespace { + +// Returns the index of |mode| in |modes| or not found. +static uint64_t GetModeIndex( + const display::DisplaySnapshot::DisplayModeList& modes, + const display::DisplayMode* mode) { + if (!mode) + return std::numeric_limits<uint64_t>::max(); + + for (size_t i = 0; i < modes.size(); ++i) { + if (modes[i].get()->size() == mode->size() && + modes[i].get()->is_interlaced() == mode->is_interlaced() && + modes[i].get()->refresh_rate() == mode->refresh_rate()) + return i; + } + NOTREACHED(); + return std::numeric_limits<uint64_t>::max(); +} + +} // namespace + +// static +std::vector<std::unique_ptr<display::DisplayMode>> +StructTraits<display::mojom::DisplaySnapshotMojoDataView, + std::unique_ptr<display::DisplaySnapshotMojo>>:: + modes( + const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) { + std::vector<std::unique_ptr<display::DisplayMode>> display_mode_list; + + for (const auto& display_mode : display_snapshot->modes()) + display_mode_list.push_back(display_mode->Clone()); + + return display_mode_list; +} + +// static +uint64_t StructTraits<display::mojom::DisplaySnapshotMojoDataView, + std::unique_ptr<display::DisplaySnapshotMojo>>:: + current_mode_index( + const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) { + return GetModeIndex(display_snapshot->modes(), + display_snapshot->current_mode()); +} + +// static +uint64_t StructTraits<display::mojom::DisplaySnapshotMojoDataView, + std::unique_ptr<display::DisplaySnapshotMojo>>:: + native_mode_index( + const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) { + return GetModeIndex(display_snapshot->modes(), + display_snapshot->native_mode()); +} + +// static +bool StructTraits<display::mojom::DisplaySnapshotMojoDataView, + std::unique_ptr<display::DisplaySnapshotMojo>>:: + Read(display::mojom::DisplaySnapshotMojoDataView data, + std::unique_ptr<display::DisplaySnapshotMojo>* out) { + gfx::Point origin; + if (!data.ReadOrigin(&origin)) + return false; + + gfx::Size physical_size; + if (!data.ReadPhysicalSize(&physical_size)) + return false; + + display::DisplayConnectionType type; + if (!data.ReadType(&type)) + return false; + + std::string display_name; + if (!data.ReadDisplayName(&display_name)) + return false; + + base::FilePath file_path; + if (!data.ReadSysPath(&file_path)) + return false; + + // There is a type mismatch between vectors containing unique_ptr<T> vs + // unique_ptr<const T>. We deserialize into a vector of unique_ptr<T> + // then create a vector of unique_ptr<const T> after. + std::vector<std::unique_ptr<display::DisplayMode>> non_const_modes; + if (!data.ReadModes(&non_const_modes)) + return false; + display::DisplaySnapshot::DisplayModeList modes; + for (auto& mode : non_const_modes) + modes.push_back(std::move(mode)); + + // Get current_mode pointer from modes array. + const display::DisplayMode* current_mode = nullptr; + if (data.has_current_mode()) { + size_t current_mode_index = data.current_mode_index(); + if (current_mode_index >= modes.size()) + return false; + current_mode = modes[current_mode_index].get(); + } + + // Get native_mode pointer from modes array. + const display::DisplayMode* native_mode = nullptr; + if (data.has_native_mode()) { + size_t native_mode_index = data.native_mode_index(); + if (native_mode_index >= modes.size()) + return false; + native_mode = modes[native_mode_index].get(); + } + + std::vector<uint8_t> edid; + if (!data.ReadEdid(&edid)) + return false; + + gfx::Size maximum_cursor_size; + if (!data.ReadMaximumCursorSize(&maximum_cursor_size)) + return false; + + *out = base::MakeUnique<display::DisplaySnapshotMojo>( + data.display_id(), origin, physical_size, type, + data.is_aspect_preserving_scaling(), data.has_overscan(), + data.has_color_correction_matrix(), display_name, file_path, + data.product_id(), std::move(modes), std::move(edid), current_mode, + native_mode, maximum_cursor_size); + return true; +} + +} // namespace mojo \ No newline at end of file
diff --git a/ui/display/mojo/display_snapshot_mojo_struct_traits.h b/ui/display/mojo/display_snapshot_mojo_struct_traits.h new file mode 100644 index 0000000..bf4f584 --- /dev/null +++ b/ui/display/mojo/display_snapshot_mojo_struct_traits.h
@@ -0,0 +1,102 @@ +// Copyright 2017 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 UI_DISPLAY_MOJO_DISPLAY_SNAPSHOT_MOJO_STRUCT_TRAITS_H_ +#define UI_DISPLAY_MOJO_DISPLAY_SNAPSHOT_MOJO_STRUCT_TRAITS_H_ + +#include "ui/display/display_snapshot_mojo.h" +#include "ui/display/mojo/display_snapshot_mojo.mojom.h" +#include "ui/display/types/display_mode.h" + +namespace mojo { + +template <> +struct StructTraits<display::mojom::DisplaySnapshotMojoDataView, + std::unique_ptr<display::DisplaySnapshotMojo>> { + static int64_t display_id( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->display_id(); + } + + static const gfx::Point& origin( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->origin(); + } + + static const gfx::Size& physical_size( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->physical_size(); + } + + static display::DisplayConnectionType type( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->type(); + } + + static bool is_aspect_preserving_scaling( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->is_aspect_preserving_scaling(); + } + + static bool has_overscan( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->has_overscan(); + } + + static bool has_color_correction_matrix( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->has_color_correction_matrix(); + } + + static std::string display_name( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->display_name(); + } + + static const base::FilePath& sys_path( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->sys_path(); + } + + static std::vector<uint8_t> edid( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->edid(); + } + + static std::vector<std::unique_ptr<display::DisplayMode>> modes( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot); + + static uint64_t current_mode_index( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot); + + static bool has_current_mode( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->current_mode() != nullptr; + } + + static uint64_t native_mode_index( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot); + + static bool has_native_mode( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->native_mode() != nullptr; + } + + static int64_t product_id( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->product_id(); + } + + static const gfx::Size& maximum_cursor_size( + const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) { + return snapshot->maximum_cursor_size(); + } + + static bool Read(display::mojom::DisplaySnapshotMojoDataView data, + std::unique_ptr<display::DisplaySnapshotMojo>* out); +}; + +} // namespace mojo + +#endif // UI_DISPLAY_MOJO_DISPLAY_SNAPSHOT_MOJO_STRUCT_TRAITS_H_
diff --git a/ui/display/mojo/display_struct_traits_test.mojom b/ui/display/mojo/display_struct_traits_test.mojom index 7185abd13..30c92ff 100644 --- a/ui/display/mojo/display_struct_traits_test.mojom +++ b/ui/display/mojo/display_struct_traits_test.mojom
@@ -7,6 +7,7 @@ import "ui/display/mojo/display.mojom"; import "ui/display/mojo/display_layout.mojom"; import "ui/display/mojo/display_mode.mojom"; +import "ui/display/mojo/display_snapshot_mojo.mojom"; import "ui/display/mojo/gamma_ramp_rgb_entry.mojom"; interface DisplayStructTraitsTest { @@ -17,6 +18,10 @@ EchoDisplayMode(DisplayMode in) => (DisplayMode out); [Sync] + EchoDisplaySnapshotMojo(DisplaySnapshotMojo in) => (DisplaySnapshotMojo + out); + + [Sync] EchoDisplayPlacement(DisplayPlacement in) => (DisplayPlacement out); [Sync]
diff --git a/ui/display/mojo/display_struct_traits_unittest.cc b/ui/display/mojo/display_struct_traits_unittest.cc index e2c3979..bc30608 100644 --- a/ui/display/mojo/display_struct_traits_unittest.cc +++ b/ui/display/mojo/display_struct_traits_unittest.cc
@@ -2,12 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + +#include "base/macros.h" #include "base/message_loop/message_loop.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" #include "ui/display/display_layout.h" +#include "ui/display/display_snapshot_mojo.h" #include "ui/display/mojo/display_struct_traits_test.mojom.h" +#include "ui/display/types/display_constants.h" #include "ui/display/types/display_mode.h" #include "ui/display/types/gamma_ramp_rgb_entry.h" #include "ui/gfx/geometry/rect.h" @@ -42,6 +47,12 @@ callback.Run(std::move(in)); } + void EchoDisplaySnapshotMojo( + std::unique_ptr<DisplaySnapshotMojo> in, + const EchoDisplaySnapshotMojoCallback& callback) override { + callback.Run(std::move(in)); + } + void EchoDisplayPlacement( const DisplayPlacement& in, const EchoDisplayPlacementCallback& callback) override { @@ -85,6 +96,49 @@ EXPECT_EQ(input.primary_id, output.primary_id); } +bool CompareModes(const DisplayMode& lhs, const DisplayMode& rhs) { + return lhs.size() == rhs.size() && + lhs.is_interlaced() == rhs.is_interlaced() && + lhs.refresh_rate() == rhs.refresh_rate(); +} + +void CheckDisplaySnapShotMojoEqual(const DisplaySnapshotMojo& input, + const DisplaySnapshotMojo& output) { + // We want to test each component individually to make sure each data member + // was correctly serialized and deserialized. + EXPECT_NE(&input, &output); // Make sure they aren't the same object. + EXPECT_EQ(input.display_id(), output.display_id()); + EXPECT_EQ(input.origin(), output.origin()); + EXPECT_EQ(input.physical_size(), output.physical_size()); + EXPECT_EQ(input.type(), output.type()); + EXPECT_EQ(input.is_aspect_preserving_scaling(), + output.is_aspect_preserving_scaling()); + EXPECT_EQ(input.has_overscan(), output.has_overscan()); + EXPECT_EQ(input.has_color_correction_matrix(), + output.has_color_correction_matrix()); + EXPECT_EQ(input.display_name(), output.display_name()); + EXPECT_EQ(input.sys_path(), output.sys_path()); + EXPECT_EQ(input.product_id(), output.product_id()); + EXPECT_EQ(input.modes().size(), output.modes().size()); + + for (size_t i = 0; i < input.modes().size(); i++) + EXPECT_TRUE(CompareModes(*input.modes()[i], *output.modes()[i])); + + EXPECT_EQ(input.edid(), output.edid()); + + if (!input.current_mode()) + EXPECT_EQ(nullptr, output.current_mode()); + else + EXPECT_TRUE(CompareModes(*input.current_mode(), *output.current_mode())); + + if (!input.native_mode()) + EXPECT_EQ(nullptr, output.native_mode()); + else + EXPECT_TRUE(CompareModes(*input.native_mode(), *output.native_mode())); + + EXPECT_EQ(input.maximum_cursor_size(), output.maximum_cursor_size()); +} + } // namespace TEST_F(DisplayStructTraitsTest, DefaultDisplayValues) { @@ -237,4 +291,156 @@ EXPECT_EQ(input.b, output.b); } -} // namespace display +// One display mode, current and native mode nullptr. +TEST_F(DisplayStructTraitsTest, DisplaySnapshotCurrentAndNativeModesNull) { + // Prepare sample input with random values. + const int64_t display_id = 7; + const gfx::Point origin(1, 2); + const gfx::Size physical_size(5, 9); + const gfx::Size maximum_cursor_size(3, 5); + const DisplayConnectionType type = + display::DISPLAY_CONNECTION_TYPE_DISPLAYPORT; + const bool is_aspect_preserving_scaling = true; + const bool has_overscan = true; + const bool has_color_correction_matrix = true; + const std::string display_name("whatever display_name"); + const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("a/cb"); + const int64_t product_id = 19; + + const DisplayMode display_mode(gfx::Size(13, 11), true, 40.0f); + + display::DisplaySnapshot::DisplayModeList modes; + modes.push_back(display_mode.Clone()); + + const DisplayMode* current_mode = nullptr; + const DisplayMode* native_mode = nullptr; + const std::vector<uint8_t> edid = {1}; + + std::unique_ptr<DisplaySnapshotMojo> input = + base::MakeUnique<DisplaySnapshotMojo>( + display_id, origin, physical_size, type, is_aspect_preserving_scaling, + has_overscan, has_color_correction_matrix, display_name, sys_path, + product_id, std::move(modes), edid, current_mode, native_mode, + maximum_cursor_size); + + std::unique_ptr<DisplaySnapshotMojo> output; + GetTraitsTestProxy()->EchoDisplaySnapshotMojo(input->Clone(), &output); + + CheckDisplaySnapShotMojoEqual(*input, *output); +} + +// One display mode that is the native mode and no current mode. +TEST_F(DisplayStructTraitsTest, DisplaySnapshotCurrentModeNull) { + // Prepare sample input with random values. + const int64_t display_id = 6; + const gfx::Point origin(11, 32); + const gfx::Size physical_size(55, 49); + const gfx::Size maximum_cursor_size(13, 95); + const DisplayConnectionType type = display::DISPLAY_CONNECTION_TYPE_VGA; + const bool is_aspect_preserving_scaling = true; + const bool has_overscan = true; + const bool has_color_correction_matrix = true; + const std::string display_name("whatever display_name"); + const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("z/b"); + const int64_t product_id = 9; + + const DisplayMode display_mode(gfx::Size(13, 11), true, 50.0f); + + display::DisplaySnapshot::DisplayModeList modes; + modes.push_back(display_mode.Clone()); + + const DisplayMode* current_mode = nullptr; + const DisplayMode* native_mode = modes[0].get(); + const std::vector<uint8_t> edid = {1}; + + std::unique_ptr<DisplaySnapshotMojo> input = + base::MakeUnique<DisplaySnapshotMojo>( + display_id, origin, physical_size, type, is_aspect_preserving_scaling, + has_overscan, has_color_correction_matrix, display_name, sys_path, + product_id, std::move(modes), edid, current_mode, native_mode, + maximum_cursor_size); + + std::unique_ptr<DisplaySnapshotMojo> output; + GetTraitsTestProxy()->EchoDisplaySnapshotMojo(input->Clone(), &output); + + CheckDisplaySnapShotMojoEqual(*input, *output); +} + +// Multiple display modes, both native and current mode set. +TEST_F(DisplayStructTraitsTest, DisplaySnapshotExternal) { + // Prepare sample input from external display. + const int64_t display_id = 9834293210466051; + const gfx::Point origin(0, 1760); + const gfx::Size physical_size(520, 320); + const gfx::Size maximum_cursor_size(4, 5); + const DisplayConnectionType type = display::DISPLAY_CONNECTION_TYPE_HDMI; + const bool is_aspect_preserving_scaling = false; + const bool has_overscan = false; + const bool has_color_correction_matrix = false; + const std::string display_name("HP Z24i"); + const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("a/cb"); + const int64_t product_id = 139; + + const DisplayMode display_mode(gfx::Size(1024, 768), false, 60.0f); + const DisplayMode display_current_mode(gfx::Size(1440, 900), false, 59.89f); + const DisplayMode display_native_mode(gfx::Size(1920, 1200), false, 59.89f); + + display::DisplaySnapshot::DisplayModeList modes; + modes.push_back(display_mode.Clone()); + modes.push_back(display_current_mode.Clone()); + modes.push_back(display_native_mode.Clone()); + + const DisplayMode* current_mode = modes[1].get(); + const DisplayMode* native_mode = modes[2].get(); + const std::vector<uint8_t> edid = {2, 3, 4, 5}; + + std::unique_ptr<DisplaySnapshotMojo> input = + base::MakeUnique<DisplaySnapshotMojo>( + display_id, origin, physical_size, type, is_aspect_preserving_scaling, + has_overscan, has_color_correction_matrix, display_name, sys_path, + product_id, std::move(modes), edid, current_mode, native_mode, + maximum_cursor_size); + + std::unique_ptr<DisplaySnapshotMojo> output; + GetTraitsTestProxy()->EchoDisplaySnapshotMojo(input->Clone(), &output); + + CheckDisplaySnapShotMojoEqual(*input, *output); +} + +TEST_F(DisplayStructTraitsTest, DisplaySnapshotInternal) { + // Prepare sample input from Pixel's internal display. + const int64_t display_id = 13761487533244416; + const gfx::Point origin(0, 0); + const gfx::Size physical_size(270, 180); + const gfx::Size maximum_cursor_size(64, 64); + const DisplayConnectionType type = display::DISPLAY_CONNECTION_TYPE_INTERNAL; + const bool is_aspect_preserving_scaling = true; + const bool has_overscan = false; + const bool has_color_correction_matrix = false; + const std::string display_name(""); + const base::FilePath sys_path; + const int64_t product_id = 139; + + const DisplayMode display_mode(gfx::Size(2560, 1700), false, 95.96f); + + display::DisplaySnapshot::DisplayModeList modes; + modes.push_back(display_mode.Clone()); + + const DisplayMode* current_mode = modes[0].get(); + const DisplayMode* native_mode = modes[0].get(); + const std::vector<uint8_t> edid = {2, 3}; + + std::unique_ptr<DisplaySnapshotMojo> input = + base::MakeUnique<DisplaySnapshotMojo>( + display_id, origin, physical_size, type, is_aspect_preserving_scaling, + has_overscan, has_color_correction_matrix, display_name, sys_path, + product_id, std::move(modes), edid, current_mode, native_mode, + maximum_cursor_size); + + std::unique_ptr<DisplaySnapshotMojo> output; + GetTraitsTestProxy()->EchoDisplaySnapshotMojo(input->Clone(), &output); + + CheckDisplaySnapShotMojoEqual(*input, *output); +} + +} // namespace display \ No newline at end of file
diff --git a/ui/display/mojo/typemaps.gni b/ui/display/mojo/typemaps.gni index d2bcd57..268ff25 100644 --- a/ui/display/mojo/typemaps.gni +++ b/ui/display/mojo/typemaps.gni
@@ -4,7 +4,9 @@ typemaps = [ "//ui/display/mojo/display.typemap", + "//ui/display/mojo/display_constants.typemap", "//ui/display/mojo/display_layout.typemap", "//ui/display/mojo/display_mode.typemap", + "//ui/display/mojo/display_snapshot_mojo.typemap", "//ui/display/mojo/gamma_ramp_rgb_entry.typemap", ]
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc index 91d3a23..7d933e14 100644 --- a/ui/views/controls/button/checkbox.cc +++ b/ui/views/controls/button/checkbox.cc
@@ -33,13 +33,13 @@ checked_(false) { SetHorizontalAlignment(gfx::ALIGN_LEFT); SetFocusForPlatform(); + SetFocusPainter(nullptr); if (UseMd()) { set_request_focus_on_press(false); SetInkDropMode(PlatformStyle::kUseRipples ? InkDropMode::ON : InkDropMode::OFF); set_has_ink_drop_action_on_click(true); - SetFocusPainter(nullptr); } else { std::unique_ptr<LabelButtonBorder> button_border(new LabelButtonBorder()); // Inset the trailing side by a couple pixels for the focus border. @@ -104,18 +104,6 @@ return ui::MaterialDesignController::IsSecondaryUiMaterial(); } -void Checkbox::Layout() { - LabelButton::Layout(); - - if (!UseMd()) { - // Construct a focus painter that only surrounds the label area. - gfx::Rect rect = label()->GetMirroredBounds(); - rect.Inset(-2, 3); - SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(gfx::Insets( - rect.y(), rect.x(), height() - rect.bottom(), width() - rect.right()))); - } -} - const char* Checkbox::GetClassName() const { return kViewClassName; }
diff --git a/ui/views/controls/button/checkbox.h b/ui/views/controls/button/checkbox.h index 407c4d39..6b336c6 100644 --- a/ui/views/controls/button/checkbox.h +++ b/ui/views/controls/button/checkbox.h
@@ -41,7 +41,6 @@ static bool UseMd(); // Overridden from LabelButton: - void Layout() override; const char* GetClassName() const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; void OnPaint(gfx::Canvas* canvas) override;
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc index 5ad539f..fbd480f 100644 --- a/ui/views/controls/styled_label.cc +++ b/ui/views/controls/styled_label.cc
@@ -353,16 +353,19 @@ // Calculate the size of the optional focus border, and overlap by that // amount. Otherwise, "<a>link</a>," will render as "link ,". gfx::Insets focus_border_insets(label->GetInsets()); - focus_border_insets += -label->View::GetInsets(); + focus_border_insets -= label->View::GetInsets(); const gfx::Size view_size = label->GetPreferredSize(); + const gfx::Insets insets = GetInsets(); label->SetBoundsRect(gfx::Rect( gfx::Point( - GetInsets().left() + x - focus_border_insets.left(), - GetInsets().top() + line * line_height - focus_border_insets.top()), + insets.left() + x - focus_border_insets.left(), + insets.top() + line * line_height - focus_border_insets.top()), view_size)); x += view_size.width() - focus_border_insets.width(); used_width = std::max(used_width, x); - total_height = std::max(total_height, label->bounds().bottom()); + total_height = + std::max(total_height, label->bounds().bottom() + insets.bottom() - + focus_border_insets.bottom()); if (!dry_run) AddChildView(label.release());
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc index 78b7238e..806a75c 100644 --- a/ui/views/controls/styled_label_unittest.cc +++ b/ui/views/controls/styled_label_unittest.cc
@@ -562,4 +562,21 @@ EXPECT_NE(first_child_after_text_update, first_child_after_layout); } +TEST_F(StyledLabelTest, Border) { + const std::string text("One line"); + InitStyledLabel(text); + Label label(ASCIIToUTF16(text)); + gfx::Size label_preferred_size = label.GetPreferredSize(); + styled()->SetBorder( + CreateEmptyBorder(5 /*top*/, 10 /*left*/, 6 /*bottom*/, 20 /*right*/)); + styled()->SetBounds(0, 0, 1000, 0); + styled()->Layout(); + EXPECT_EQ( + label_preferred_size.height() + 5 /*top border*/ + 6 /*bottom border*/, + styled()->GetPreferredSize().height()); + EXPECT_EQ( + label_preferred_size.width() + 10 /*left border*/ + 20 /*right border*/, + styled()->GetPreferredSize().width()); +} + } // namespace views