diff --git a/AUTHORS b/AUTHORS index 72262c45..7da923c 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -989,6 +989,7 @@ Zhaoze Zhou <zhaoze.zhou@partner.samsung.com> Zheda Chen <zheda.chen@intel.com> Zheng Chuang <zhengchuangscu@gmail.com> +Zhengkun Li <zhengkli@amazon.com> Zhenyu Liang <zhenyu.liang@intel.com> Zhenyu Shan <zhenyu.shan@intel.com> Zhifei Fang <facetothefate@gmail.com>
diff --git a/DEPS b/DEPS index c7adc49..f5cf945d 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '44c8131b779b1a21bae524733663014d3614a5ed', + 'skia_revision': 'f4438d56e989745868ad2fc289894a1553d68ab6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '72287902200674b17fbc4557a6a9fb6c67f0542c', + 'v8_revision': '3f6dd8f7b0462a669f3ed1c52519d19625a42d42', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -145,11 +145,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '094c40dce6015add9e9524364a4e9b0523b7c31e', + 'angle_revision': '2fb6563bf50375dffcc92aab6c7865da4c555df7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'af973b67141eb2f8abf7e5bcf109f829fae0abbc', + 'swiftshader_revision': 'a2749f39f47dd61b6f18972f6471993c6b5c1928', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -196,7 +196,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': '1a088f27008b608cfd9363cc70fbac3f44568f0e', + 'catapult_revision': 'f8e231582d6aa491266c06cfaa7b81cd15aa3dfa', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -248,7 +248,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '6df8a917a4496f1a46e8ae21ffa3d00075380e47', + 'spv_tools_revision': 'e545522146af37cc84f6b16e51ebbed96edd334c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -270,25 +270,26 @@ # and whatever else without interference from each other. 'quiche_revision': '348de99ee1f13e6747da3695387a2c78610f5f62', # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling clang format - # and whatever else without interference from each other. - 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917', - # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling libc++ - # and whatever else without interference from each other. - 'libcxx_revision': 'a50f5035629b7621e92acef968403f71b7d48553', - # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling libc++abi - # and whatever else without interference from each other. - 'libcxxabi_revision': '0d529660e32d77d9111912d73f2c74fc5fa2a858', - # Three lines of non-changing comments so that - # the commit queue can handle CLs rolling libunwind - # and whatever else without interference from each other. - 'libunwind_revision': '69d9b84cca8354117b9fe9705a4430d789ee599b', - # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. 'ios_webkit_revision': '59e9de61b7b36507836fa8b098e8839d7d995b13', + + # + # TODO(crbug.com/941824): These revisions need to be kept in sync + # between //DEPS and //buildtools/DEPS, so if you're updating one, + # update the other. There is a presubmit check that checks that + # you've done so; if you are adding new tools to //buildtools and + # hence new revisions to this list, make sure you update the + # _CheckBuildtoolsRevsAreInSync in PRESUBMIT.py to include the additional + # revisions. + # + # Also, if you change these, make sure you update the svn_revisions in + # //buildtools/deps_revisions.gni. + # + 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917', + 'libcxx_revision': 'a50f5035629b7621e92acef968403f71b7d48553', + 'libcxxabi_revision': '0d529660e32d77d9111912d73f2c74fc5fa2a858', + 'libunwind_revision': '69d9b84cca8354117b9fe9705a4430d789ee599b', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -408,7 +409,7 @@ }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '4ec31ccbe1e03279619915b00ddf30af5422106e', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '0146bd6e1f057160bb80e596c644414e05267e9e', 'condition': 'checkout_ios', }, @@ -760,7 +761,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7a62eb7d2b04fa3418bfd1ab4dbc40be74818e64', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '69d4958ee9b3375a35c8e2f88173187a5b89594b', 'condition': 'checkout_linux', }, @@ -785,7 +786,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '40c19421b4ba13579d1d8cbfecc7cb610eca3269', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1c2fa0fdda124fad7f41d30d19efb901df7e4408', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1018,7 +1019,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '8256c8b297c8b7c7ee4de24edff82ed67d6ef207', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '1533bd84f12e5b24b5c2e41d1729942c7aa218ad', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1', @@ -1127,7 +1128,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '29885798ac66d92369e98bc90a51ee2d2e497ec4', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '8320e6d2b742e5ecde2c60ca535a1d3c8f4c0bdb', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1339,7 +1340,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@eae9be8ac5e0e8fbaae7c5af4a5db0fc0f6d2be8', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b58fe2ab9436b6e35ef3527b8fbf4e7f81c4c98a', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 0508eda..12de957 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -3027,6 +3027,46 @@ return all_problems +def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api): + # TODO(crbug.com/941824): We need to make sure the entries in + # //buildtools/DEPS are kept in sync with the entries in //DEPS + # so that users of //buildtools in other projects get the same tooling + # Chromium gets. If we ever fix the referenced bug and add 'includedeps' + # support to gclient, we can eliminate the duplication and delete + # this presubmit check. + + # Update this regexp if new revisions are added to the files. + rev_regexp = input_api.re.compile( + "'(clang_format|libcxx|libcxxabi|libunwind)_revision':") + + # If a user is changing one revision, they need to change the same + # line in both files. This means that any given change should contain + # exactly the same list of changed lines that match the regexps. The + # replace(' ', '') call allows us to ignore whitespace changes to the + # lines. The 'long_text' parameter to the error will contain the + # list of changed lines in both files, which should make it easy enough + # to spot the error without going overboard in this implementation. + revs_changes = { + 'DEPS': {}, + 'buildtools/DEPS': {}, + } + long_text = '' + + for f in input_api.AffectedFiles( + file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')): + for line_num, line in f.ChangedContents(): + if rev_regexp.search(line): + revs_changes[f.LocalPath()][line.replace(' ', '')] = line + long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line) + + if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']): + return [output_api.PresubmitError( + 'Change buildtools revisions in sync in both //DEPS and ' + '//buildtools/DEPS.', long_text=long_text + '\n')] + else: + return [] + + def _AndroidSpecificOnUploadChecks(input_api, output_api): """Groups upload checks that target android code.""" results = [] @@ -3111,6 +3151,7 @@ input_api.canned_checks.CheckVPythonSpec(input_api, output_api))) results.extend(_CheckTranslationScreenshots(input_api, output_api)) results.extend(_CheckCorrectProductNameInMessages(input_api, output_api)) + results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api)) for f in input_api.AffectedFiles(): path, name = input_api.os_path.split(f.LocalPath())
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index e3c16f6..34456b1 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -2232,5 +2232,49 @@ MockOutputApi()) self.assertEqual(0, len(results)) + +class BuildtoolsRevisionsAreInSyncTest(unittest.TestCase): + # TODO(crbug.com/941824): We need to make sure the entries in + # //buildtools/DEPS are kept in sync with the entries in //DEPS + # so that users of //buildtools in other projects get the same tooling + # Chromium gets. If we ever fix the referenced bug and add 'includedeps' + # support to gclient, we can eliminate the duplication and delete + # these tests for the corresponding presubmit check. + + def _check(self, files): + mock_input_api = MockInputApi() + mock_input_api.files = [] + for fname, contents in files.items(): + mock_input_api.files.append(MockFile(fname, contents.splitlines())) + return PRESUBMIT._CheckBuildtoolsRevisionsAreInSync(mock_input_api, + MockOutputApi()) + + def testOneFileChangedButNotTheOther(self): + results = self._check({ + "DEPS": "'libunwind_revision': 'onerev'", + }) + self.assertNotEqual(results, []) + + def testNeitherFileChanged(self): + results = self._check({ + "OWNERS": "foobar@example.com", + }) + self.assertEqual(results, []) + + def testBothFilesChangedAndMatch(self): + results = self._check({ + "DEPS": "'libunwind_revision': 'onerev'", + "buildtools/DEPS": "'libunwind_revision': 'onerev'", + }) + self.assertEqual(results, []) + + def testBothFilesWereChangedAndDontMatch(self): + results = self._check({ + "DEPS": "'libunwind_revision': 'onerev'", + "buildtools/DEPS": "'libunwind_revision': 'anotherrev'", + }) + self.assertNotEqual(results, []) + + if __name__ == '__main__': unittest.main()
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 8983f5f..156e205c 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -19,6 +19,7 @@ #include "android_webview/browser/aw_contents_io_thread_client.h" #include "android_webview/browser/aw_cookie_access_policy.h" #include "android_webview/browser/aw_devtools_manager_delegate.h" +#include "android_webview/browser/aw_feature_list.h" #include "android_webview/browser/aw_feature_list_creator.h" #include "android_webview/browser/aw_http_auth_handler.h" #include "android_webview/browser/aw_proxying_url_loader_factory.h" @@ -984,6 +985,13 @@ return android_webview::GetUserAgent(); } +content::ContentBrowserClient::WideColorGamutHeuristic +AwContentBrowserClient::GetWideColorGamutHeuristic() const { + if (base::FeatureList::IsEnabled(features::kWebViewWideColorGamutSupport)) + return WideColorGamutHeuristic::kUseWindow; + return WideColorGamutHeuristic::kNone; +} + content::SpeechRecognitionManagerDelegate* AwContentBrowserClient::CreateSpeechRecognitionManagerDelegate() { return new AwSpeechRecognitionManagerDelegate();
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index c2afa81a..1b50460 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h
@@ -229,6 +229,8 @@ bool* bypass_redirect_checks) override; std::string GetProduct() const override; std::string GetUserAgent() const override; + ContentBrowserClient::WideColorGamutHeuristic GetWideColorGamutHeuristic() + const override; AwFeatureListCreator* aw_feature_list_creator() { return aw_feature_list_creator_;
diff --git a/android_webview/browser/aw_feature_list.cc b/android_webview/browser/aw_feature_list.cc index 2c02de3..f05c8f60 100644 --- a/android_webview/browser/aw_feature_list.cc +++ b/android_webview/browser/aw_feature_list.cc
@@ -25,7 +25,6 @@ const base::Feature* kFeaturesExposedToJava[] = { &features::kWebViewConnectionlessSafeBrowsing, &features::kWebViewPageStartedOnCommit, - &features::kWebViewWideColorGamutSupport, }; const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java index fd51311c..d8547ede 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -36,7 +36,6 @@ import org.chromium.content_public.browser.ChildProcessCreationParams; import org.chromium.content_public.browser.ChildProcessLauncherHelper; import org.chromium.policy.CombinedPolicyProvider; -import org.chromium.ui.base.WindowAndroid; import java.io.File; import java.io.FileNotFoundException; @@ -147,10 +146,6 @@ } catch (ProcessInitException e) { throw new RuntimeException("Cannot initialize WebView", e); } - - if (AwFeatureList.isEnabled(AwFeatureList.WEBVIEW_WIDE_COLOR_GAMUT_SUPPORT)) { - WindowAndroid.enableWideColorGamut(); - } }); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java b/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java index eff10b2..829c7a8 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java +++ b/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java
@@ -67,7 +67,6 @@ public static final String WEBVIEW_CONNECTIONLESS_SAFE_BROWSING = "WebViewConnectionlessSafeBrowsing"; public static final String WEBVIEW_PAGE_STARTED_ON_COMMIT = "WebViewPageStartedOnCommit"; - public static final String WEBVIEW_WIDE_COLOR_GAMUT_SUPPORT = "WebViewWideColorGamutSupport"; private static native boolean nativeIsEnabled(String featureName); }
diff --git a/android_webview/tools/run_cts.py b/android_webview/tools/run_cts.py index 5e99f5c..13774de 100755 --- a/android_webview/tools/run_cts.py +++ b/android_webview/tools/run_cts.py
@@ -320,6 +320,21 @@ device.Uninstall(package) +def ForwardArgsToTestRunner(known_args): + """Convert any args that should be forwarded to test_runner.py""" + forwarded_args = [] + if known_args.devices: + # test_runner.py parses --device as nargs instead of append args + forwarded_args.extend(['--device'] + known_args.devices) + if known_args.blacklist_file: + forwarded_args.extend(['--blacklist-file', known_args.blacklist_file]) + + if known_args.verbose: + forwarded_args.extend(['-' + 'v' * known_args.verbose]) + #TODO: Pass quiet to test runner when it becomes supported + return forwarded_args + + def main(): parser = argparse.ArgumentParser() parser.add_argument( @@ -373,13 +388,13 @@ logging_common.InitializeLogging(args) devil_chromium.Initialize() + test_runner_args.extend(ForwardArgsToTestRunner(args)) + devices = script_common.GetDevices(args.devices, args.blacklist_file) device = devices[0] if len(devices) > 1: - logging.warning('Only single device supported, using 1st of %d devices: %s', - len(devices), device.serial) - test_runner_args.extend(['-d', device.serial]) - + logging.warning('Detection of arch and cts-release will use 1st of %d ' + 'devices: %s', len(devices), device.serial) arch = args.arch or DetermineArch(device) cts_release = args.cts_release or DetermineCtsRelease(device)
diff --git a/ash/DEPS b/ash/DEPS index 35ba450..7b40fb2 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -61,12 +61,10 @@ "+chromeos/constants", "+chromeos/dbus/dbus_thread_manager.h", "+chromeos/dbus/fake_power_manager_client.h", - "+chromeos/dbus/fake_session_manager_client.h", "+chromeos/dbus/hammerd", "+chromeos/dbus/power_manager", "+chromeos/dbus/power_manager_client.h", "+chromeos/dbus/power_policy_controller.h", - "+chromeos/dbus/session_manager_client.h", "+chromeos/dbus/shill_device_client.h", "+chromeos/dbus/system_clock", # TODO(jamescook): Eliminate this. http://crbug.com/644355
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 3cc430544..5d04d414 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -28,7 +28,6 @@ #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/session/session_controller.h" -#include "ash/shelf/shelf.h" #include "ash/shell.h" #include "ash/voice_interaction/voice_interaction_controller.h" #include "ash/wallpaper/wallpaper_controller.h" @@ -535,16 +534,6 @@ return model_->state_fullscreen(); } -void AppListControllerImpl::OnWindowDragStarted() { - in_window_dragging_ = true; - UpdateHomeLauncherVisibility(); -} - -void AppListControllerImpl::OnWindowDragEnded() { - in_window_dragging_ = false; - UpdateHomeLauncherVisibility(); -} - void AppListControllerImpl::FlushForTesting() { bindings_.FlushForTesting(); } @@ -617,7 +606,7 @@ } // Show the app list if the tablet mode starts. - ShowHomeLauncher(); + Shell::Get()->home_screen_controller()->Show(); UpdateLauncherContainer(); } @@ -643,16 +632,6 @@ app_list_view->OnScreenKeyboardShown(is_visible); } -void AppListControllerImpl::OnWallpaperPreviewStarted() { - in_wallpaper_preview_ = true; - UpdateHomeLauncherVisibility(); -} - -void AppListControllerImpl::OnWallpaperPreviewEnded() { - in_wallpaper_preview_ = false; - UpdateHomeLauncherVisibility(); -} - void AppListControllerImpl::OnVoiceInteractionSettingsEnabled(bool enabled) { UpdateAssistantVisibility(); } @@ -678,7 +657,7 @@ return; if (should_be_shown) - ShowHomeLauncher(); + Shell::Get()->home_screen_controller()->Show(); } void AppListControllerImpl::OnWindowUntracked(aura::Window* untracked_window) { @@ -732,6 +711,16 @@ : AssistantExitPoint::kLauncherClose); } +void AppListControllerImpl::ShowHomeScreen() { + DCHECK(IsTabletMode()); + + Show(GetDisplayIdToShowAppListOn(), app_list::kTabletMode, base::TimeTicks()); +} + +aura::Window* AppListControllerImpl::GetHomeScreenWindow() { + return presenter_.GetWindow(); +} + void AppListControllerImpl::UpdateYPositionAndOpacityForHomeLauncher( int y_position_in_screen, float opacity, @@ -1157,17 +1146,6 @@ return model_->FindFolderItem(folder_id); } -void AppListControllerImpl::UpdateHomeLauncherVisibility() { - if (!IsTabletMode() || !presenter_.GetWindow()) - return; - - const bool in_overview = Shell::Get()->overview_controller()->IsSelecting(); - if (in_wallpaper_preview_ || in_overview || in_window_dragging_) - presenter_.GetWindow()->Hide(); - else - presenter_.GetWindow()->Show(); -} - void AppListControllerImpl::UpdateAssistantVisibility() { GetSearchModel()->search_box()->SetShowAssistantButton( IsAssistantAllowedAndEnabled()); @@ -1185,17 +1163,6 @@ .id(); } -void AppListControllerImpl::ShowHomeLauncher() { - DCHECK(IsTabletMode()); - - if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - return; - - Show(GetDisplayIdToShowAppListOn(), app_list::kTabletMode, base::TimeTicks()); - UpdateHomeLauncherVisibility(); - Shelf::ForWindow(presenter_.GetWindow())->MaybeUpdateShelfBackground(); -} - void AppListControllerImpl::ResetHomeLauncherIfShown() { if (!IsTabletMode() || !presenter_.IsVisible()) return;
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 26176cb..4395afc2 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -151,12 +151,6 @@ base::TimeTicks event_time_stamp); app_list::AppListViewState GetAppListViewState(); - // Called when a window starts/ends dragging. If we're in tablet mode and home - // launcher is enabled, we should hide the home launcher during dragging a - // window and reshow it when the drag ends. - void OnWindowDragStarted(); - void OnWindowDragEnded(); - // app_list::AppListViewDelegate: app_list::AppListModel* GetModel() override; app_list::SearchModel* GetSearchModel() override; @@ -231,8 +225,6 @@ // WallpaperControllerObserver: void OnWallpaperColorsChanged() override; - void OnWallpaperPreviewStarted() override; - void OnWallpaperPreviewEnded() override; // mojom::VoiceInteractionObserver: void OnVoiceInteractionSettingsEnabled(bool enabled) override; @@ -256,6 +248,8 @@ void OnHomeLauncherAnimationComplete(bool shown, int64_t display_id) override; // HomeScreenDelegate: + void ShowHomeScreen() override; + aura::Window* GetHomeScreenWindow() override; void UpdateYPositionAndOpacityForHomeLauncher( int y_position_in_screen, float opacity, @@ -294,10 +288,6 @@ AppListItemMetadataPtr metadata); app_list::AppListFolderItem* FindFolderItem(const std::string& folder_id); - // Update the visibility of the home launcher based on e.g. if the device is - // in overview mode. - void UpdateHomeLauncherVisibility(); - // Update the visibility of Assistant functionality. void UpdateAssistantVisibility(); @@ -306,15 +296,12 @@ int64_t GetDisplayIdToShowAppListOn(); - // Shows the home launcher in tablet mode. - void ShowHomeLauncher(); - void ResetHomeLauncherIfShown(); // Updates which container the launcher window should be in. void UpdateLauncherContainer(); -// Returns the length of the most recent query. + // Returns the length of the most recent query. int GetLastQueryLength(); base::string16 last_raw_query_; @@ -339,13 +326,6 @@ // overview mode exit animations are finished. bool use_slide_to_exit_overview_ = false; - // Whether the wallpaper is being previewed. The home launcher (if enabled) - // should be hidden during wallpaper preview. - bool in_wallpaper_preview_ = false; - - // Whether we're currently in a window dragging process. - bool in_window_dragging_ = false; - base::ObserverList<AppListControllerObserver> observers_; DISALLOW_COPY_AND_ASSIGN(AppListControllerImpl);
diff --git a/ash/app_list/views/assistant/assistant_main_stage.cc b/ash/app_list/views/assistant/assistant_main_stage.cc index 561f3bc..345f8bb 100644 --- a/ash/app_list/views/assistant/assistant_main_stage.cc +++ b/ash/app_list/views/assistant/assistant_main_stage.cc
@@ -143,10 +143,6 @@ layer()->SetFillsBoundsOpaquely(false); layer()->SetMasksToBounds(true); - // TODO(wutao): finalize the padding. - constexpr int kTopPaddingDip = 3; - SetBorder(views::CreateEmptyBorder(gfx::Insets(kTopPaddingDip, 0, 0, 0))); - // Separators: the progress indicator and the horizontal separator will be the // separator when querying and showing the results, respectively. The height // of the horizontal separator is set to be the same as the progress indicator
diff --git a/ash/app_list/views/assistant/assistant_main_view.cc b/ash/app_list/views/assistant/assistant_main_view.cc index e479f41..d68d097d 100644 --- a/ash/app_list/views/assistant/assistant_main_view.cc +++ b/ash/app_list/views/assistant/assistant_main_view.cc
@@ -10,17 +10,12 @@ #include "ash/app_list/views/assistant/dialog_plate.h" #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_view_delegate.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "ui/chromeos/search_box/search_box_constants.h" #include "ui/views/layout/box_layout.h" namespace app_list { -namespace { - -constexpr int kBottomPaddingDip = 8; - -} // namespace - AssistantMainView::AssistantMainView(ash::AssistantViewDelegate* delegate) : delegate_(delegate) { InitLayout(); @@ -83,7 +78,6 @@ views::BoxLayout::Orientation::kVertical)); layout->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - SetBorder(views::CreateEmptyBorder(gfx::Insets(0, 0, kBottomPaddingDip, 0))); // Dialog plate. dialog_plate_ = new DialogPlate(delegate_);
diff --git a/ash/app_list/views/assistant/dialog_plate.cc b/ash/app_list/views/assistant/dialog_plate.cc index 2fea69f..bd3f651e 100644 --- a/ash/app_list/views/assistant/dialog_plate.cc +++ b/ash/app_list/views/assistant/dialog_plate.cc
@@ -33,11 +33,10 @@ namespace { // Appearance. -// TODO(wutao): need to be finalized. constexpr int kDialogPaddingDip = 16; constexpr int kIconSizeDip = 24; constexpr int kButtonSizeDip = 32; -constexpr int kPreferredHeightDip = 48; +constexpr int kPreferredHeightDip = 56; // Animation. constexpr base::TimeDelta kAnimationFadeInDelay =
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index 1fca956a..733477f 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -176,11 +176,9 @@ void SearchBoxView::UpdateSearchIcon() { const gfx::VectorIcon& google_icon = is_search_box_active() ? kGoogleColorIcon : kGoogleBlackIcon; - const gfx::VectorIcon& icon = - search_model_->search_engine_is_google() && - !app_list_features::IsEmbeddedAssistantUIEnabled() - ? google_icon - : kSearchEngineNotGoogleIcon; + const gfx::VectorIcon& icon = search_model_->search_engine_is_google() + ? google_icon + : kSearchEngineNotGoogleIcon; SetSearchIconImage(gfx::CreateVectorIcon(icon, search_box::kSearchIconSize, search_box_color())); }
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index ffad6f52..306d08d 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -97,7 +97,6 @@ AddChildView(icon_); if (is_play_store_app_search_enabled_ || - app_list_features::IsAppShortcutSearchEnabled() || is_app_reinstall_recommendation_enabled_) { badge_ = new views::ImageView; badge_->set_can_process_events_within_subtree(false);
diff --git a/ash/assistant/ui/main_stage/assistant_opt_in_view.cc b/ash/assistant/ui/main_stage/assistant_opt_in_view.cc index 1f19769..4740793 100644 --- a/ash/assistant/ui/main_stage/assistant_opt_in_view.cc +++ b/ash/assistant/ui/main_stage/assistant_opt_in_view.cc
@@ -9,6 +9,7 @@ #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_view_delegate.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "ash/strings/grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/canvas.h" @@ -123,7 +124,9 @@ views::BoxLayout::Orientation::kHorizontal)); layout_manager->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END); + app_list_features::IsEmbeddedAssistantUIEnabled() + ? views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER + : views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END); layout_manager->set_main_axis_alignment( views::BoxLayout::MainAxisAlignment::MAIN_AXIS_ALIGNMENT_CENTER);
diff --git a/ash/assistant/ui/main_stage/suggestion_container_view.cc b/ash/assistant/ui/main_stage/suggestion_container_view.cc index 5d54828..d57dcc63 100644 --- a/ash/assistant/ui/main_stage/suggestion_container_view.cc +++ b/ash/assistant/ui/main_stage/suggestion_container_view.cc
@@ -12,6 +12,7 @@ #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_view_delegate.h" #include "ash/assistant/util/assistant_util.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "base/bind.h" #include "base/strings/utf_string_conversions.h" #include "ui/views/layout/box_layout.h" @@ -72,7 +73,9 @@ gfx::Insets(0, kPaddingDip), kSpacingDip)); layout_manager_->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END); + app_list_features::IsEmbeddedAssistantUIEnabled() + ? views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER + : views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END); // We center align when showing conversation starters. layout_manager_->set_main_axis_alignment(
diff --git a/ash/assistant/ui/main_stage/ui_element_container_view.cc b/ash/assistant/ui/main_stage/ui_element_container_view.cc index 0dbb0037..7aeab3cb 100644 --- a/ash/assistant/ui/main_stage/ui_element_container_view.cc +++ b/ash/assistant/ui/main_stage/ui_element_container_view.cc
@@ -13,6 +13,7 @@ #include "ash/assistant/ui/main_stage/assistant_card_element_view.h" #include "ash/assistant/ui/main_stage/assistant_text_element_view.h" #include "ash/assistant/util/animation_util.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "base/callback.h" #include "base/time/time.h" #include "ui/aura/window.h" @@ -27,14 +28,17 @@ namespace { // Appearance. -constexpr int kFirstCardMarginTopDip = 40; -constexpr int kPaddingBottomDip = 24; +constexpr int kEmbeddedUiFirstCardMarginTopDip = 8; +constexpr int kEmbeddedUiPaddingBottomDip = 8; +constexpr int kMainUiFirstCardMarginTopDip = 40; +constexpr int kMainUiPaddingBottomDip = 24; // Card element animation. constexpr float kCardElementAnimationFadeOutOpacity = 0.26f; // Text element animation. -constexpr float kTextElementAnimationFadeOutOpacity = 0.f; +constexpr float kEmbeddedUiTextElementAnimationFadeOutOpacity = 0.26f; +constexpr float kMainUiTextElementAnimationFadeOutOpacity = 0.f; // UI element animation. constexpr base::TimeDelta kUiElementAnimationFadeInDelay = @@ -43,6 +47,27 @@ base::TimeDelta::FromMilliseconds(250); constexpr base::TimeDelta kUiElementAnimationFadeOutDuration = base::TimeDelta::FromMilliseconds(167); + +// Helpers --------------------------------------------------------------------- + +int GetFirstCardMarginTopDip() { + return app_list_features::IsEmbeddedAssistantUIEnabled() + ? kEmbeddedUiFirstCardMarginTopDip + : kMainUiFirstCardMarginTopDip; +} + +int GetPaddingBottomDip() { + return app_list_features::IsEmbeddedAssistantUIEnabled() + ? kEmbeddedUiPaddingBottomDip + : kMainUiPaddingBottomDip; +} + +float GetTextElementAnimationFadeOutOpacity() { + return app_list_features::IsEmbeddedAssistantUIEnabled() + ? kEmbeddedUiTextElementAnimationFadeOutOpacity + : kMainUiTextElementAnimationFadeOutOpacity; +} + } // namespace // UiElementContainerView ------------------------------------------------------ @@ -106,7 +131,7 @@ void UiElementContainerView::InitLayout() { content_view()->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, - gfx::Insets(0, kUiElementHorizontalMarginDip, kPaddingBottomDip, + gfx::Insets(0, kUiElementHorizontalMarginDip, GetPaddingBottomDip(), kUiElementHorizontalMarginDip), kSpacingDip)); } @@ -229,12 +254,12 @@ if (is_first_card_) { is_first_card_ = false; - // The first card requires a top margin of |kFirstCardMarginTopDip|, but + // The first card requires a top margin of |GetFirstCardMarginTopDip()|, but // we need to account for child spacing because the first card is not // necessarily the first UI element. const int top_margin_dip = child_count() == 0 - ? kFirstCardMarginTopDip - : kFirstCardMarginTopDip - kSpacingDip; + ? GetFirstCardMarginTopDip() + : GetFirstCardMarginTopDip() - kSpacingDip; // We effectively create a top margin by applying an empty border. card_element_view->SetBorder( @@ -271,7 +296,7 @@ // We cache the view for use during animations and its desired opacity that // we'll animate to while processing the next query response. ui_element_views_.push_back(std::pair<ui::LayerOwner*, float>( - text_element_view, kTextElementAnimationFadeOutOpacity)); + text_element_view, GetTextElementAnimationFadeOutOpacity())); content_view()->AddChildView(text_element_view); }
diff --git a/ash/dbus/DEPS b/ash/dbus/DEPS index 5ea2f34..c4c77ff 100644 --- a/ash/dbus/DEPS +++ b/ash/dbus/DEPS
@@ -1,4 +1,6 @@ include_rules = [ "+chromeos/dbus/services", + # TODO(stevenjb): Eliminate this, https://crbug.com/644350. + "+chromeos/dbus/session_manager_client.h", "+dbus", ]
diff --git a/ash/home_screen/home_screen_controller.cc b/ash/home_screen/home_screen_controller.cc index daab566..2292fad 100644 --- a/ash/home_screen/home_screen_controller.cc +++ b/ash/home_screen/home_screen_controller.cc
@@ -5,17 +5,83 @@ #include "ash/home_screen/home_screen_controller.h" #include "ash/home_screen/home_launcher_gesture_handler.h" +#include "ash/home_screen/home_screen_delegate.h" +#include "ash/session/session_controller.h" +#include "ash/shelf/shelf.h" +#include "ash/shell.h" +#include "ash/wallpaper/wallpaper_controller.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "base/logging.h" +#include "ui/aura/window.h" namespace ash { HomeScreenController::HomeScreenController() : home_launcher_gesture_handler_( - std::make_unique<HomeLauncherGestureHandler>()) {} + std::make_unique<HomeLauncherGestureHandler>()) { + wallpaper_controller_observer_.Add(Shell::Get()->wallpaper_controller()); +} HomeScreenController::~HomeScreenController() = default; +bool HomeScreenController::IsHomeScreenAvailable() { + return Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled(); +} + +void HomeScreenController::Show() { + DCHECK(IsHomeScreenAvailable()); + + if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted()) + return; + + delegate_->ShowHomeScreen(); + UpdateVisibility(); + + aura::Window* window = delegate_->GetHomeScreenWindow(); + if (window) + Shelf::ForWindow(window)->MaybeUpdateShelfBackground(); +} + void HomeScreenController::SetDelegate(HomeScreenDelegate* delegate) { delegate_ = delegate; } +void HomeScreenController::OnWindowDragStarted() { + in_window_dragging_ = true; + UpdateVisibility(); +} + +void HomeScreenController::OnWindowDragEnded() { + in_window_dragging_ = false; + UpdateVisibility(); +} + +void HomeScreenController::OnWallpaperPreviewStarted() { + in_wallpaper_preview_ = true; + UpdateVisibility(); +} + +void HomeScreenController::OnWallpaperPreviewEnded() { + in_wallpaper_preview_ = false; + UpdateVisibility(); +} + +void HomeScreenController::UpdateVisibility() { + if (!IsHomeScreenAvailable()) + return; + + aura::Window* window = delegate_->GetHomeScreenWindow(); + if (!window) + return; + + const bool in_overview = Shell::Get()->overview_controller()->IsSelecting(); + if (in_overview || in_wallpaper_preview_ || in_window_dragging_) + window->Hide(); + else + window->Show(); +} + } // namespace ash
diff --git a/ash/home_screen/home_screen_controller.h b/ash/home_screen/home_screen_controller.h index b9d6ea407..2969e0d 100644 --- a/ash/home_screen/home_screen_controller.h +++ b/ash/home_screen/home_screen_controller.h
@@ -8,24 +8,39 @@ #include <memory> #include "ash/ash_export.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "base/macros.h" +#include "base/scoped_observer.h" namespace ash { class HomeLauncherGestureHandler; class HomeScreenDelegate; +class WallpaperController; // HomeScreenController handles the home launcher (e.g., tablet-mode app list) // and owns the HomeLauncherGestureHandler that transitions the launcher window // and other windows when the launcher is shown, hidden or animated. -class ASH_EXPORT HomeScreenController { +class ASH_EXPORT HomeScreenController : public WallpaperControllerObserver { public: HomeScreenController(); - ~HomeScreenController(); + ~HomeScreenController() override; + + // Returns true if the home screen can be shown (generally corresponds to the + // device being in tablet mode). + bool IsHomeScreenAvailable(); + + // Shows the home screen. + void Show(); // Sets the delegate for home screen animations. void SetDelegate(HomeScreenDelegate* delegate); + // Called when a window starts/ends dragging. If the home screen is shown, we + // should hide it during dragging a window and reshow it when the drag ends. + void OnWindowDragStarted(); + void OnWindowDragEnded(); + HomeLauncherGestureHandler* home_launcher_gesture_handler() { return home_launcher_gesture_handler_.get(); } @@ -33,6 +48,21 @@ HomeScreenDelegate* delegate() { return delegate_; } private: + // WallpaperControllerObserver: + void OnWallpaperPreviewStarted() override; + void OnWallpaperPreviewEnded() override; + + // Updates the visibility of the home screen based on e.g. if the device is + // in overview mode. + void UpdateVisibility(); + + // Whether the wallpaper is being previewed. The home screen should be hidden + // during wallpaper preview. + bool in_wallpaper_preview_ = false; + + // Whether we're currently in a window dragging process. + bool in_window_dragging_ = false; + // Not owned. HomeScreenDelegate* delegate_ = nullptr; @@ -40,6 +70,9 @@ // launcher. std::unique_ptr<HomeLauncherGestureHandler> home_launcher_gesture_handler_; + ScopedObserver<WallpaperController, WallpaperControllerObserver> + wallpaper_controller_observer_{this}; + DISALLOW_COPY_AND_ASSIGN(HomeScreenController); };
diff --git a/ash/home_screen/home_screen_delegate.h b/ash/home_screen/home_screen_delegate.h index 461cae4f..ecb070e7 100644 --- a/ash/home_screen/home_screen_delegate.h +++ b/ash/home_screen/home_screen_delegate.h
@@ -8,6 +8,10 @@ #include "base/callback.h" #include "ui/compositor/scoped_layer_animation_settings.h" +namespace aura { +class Window; +} // namespace aura + namespace ash { // Delegate for implementation-specific home screen behavior. @@ -21,6 +25,14 @@ virtual ~HomeScreenDelegate() = default; + // Shows the home screen view. + virtual void ShowHomeScreen() = 0; + + // Gets the home screen window, if available, or null if the home screen + // window is being hidden for effects (e.g. when dragging windows or + // previewing the wallpaper). + virtual aura::Window* GetHomeScreenWindow() = 0; + // Updates the y position and opacity of the home launcher view. If |callback| // is non-null, it should be called with animation settings. virtual void UpdateYPositionAndOpacityForHomeLauncher(
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc index d7c0c46..308090c 100644 --- a/ash/public/cpp/app_list/app_list_features.cc +++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -13,8 +13,6 @@ const base::Feature kEnableAnswerCard{"EnableAnswerCard", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kEnableAppShortcutSearch{"EnableAppShortcutSearch", - base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kEnableBackgroundBlur{"EnableBackgroundBlur", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kEnablePlayStoreAppSearch{ @@ -45,10 +43,6 @@ !IsEmbeddedAssistantUIEnabled(); } -bool IsAppShortcutSearchEnabled() { - return base::FeatureList::IsEnabled(kEnableAppShortcutSearch); -} - bool IsBackgroundBlurEnabled() { return base::FeatureList::IsEnabled(kEnableBackgroundBlur); }
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h index b7c7d69..f69ec90 100644 --- a/ash/public/cpp/app_list/app_list_features.h +++ b/ash/public/cpp/app_list/app_list_features.h
@@ -21,9 +21,6 @@ // Enables the answer card in the app list. ASH_PUBLIC_EXPORT extern const base::Feature kEnableAnswerCard; -// Enables app shortcuts search. -ASH_PUBLIC_EXPORT extern const base::Feature kEnableAppShortcutSearch; - // Enables background blur for the app list, lock screen, and tab switcher, also // enables the AppsGridView mask layer. In this mode, slower devices may have // choppier app list animations. crbug.com/765292. @@ -61,7 +58,6 @@ ASH_PUBLIC_EXPORT extern const base::Feature kEnableAppGridGhost; bool ASH_PUBLIC_EXPORT IsAnswerCardEnabled(); -bool ASH_PUBLIC_EXPORT IsAppShortcutSearchEnabled(); bool ASH_PUBLIC_EXPORT IsBackgroundBlurEnabled(); bool ASH_PUBLIC_EXPORT IsPlayStoreAppSearchEnabled(); bool ASH_PUBLIC_EXPORT IsAppDataSearchEnabled();
diff --git a/ash/public/interfaces/shell_test_api.test-mojom b/ash/public/interfaces/shell_test_api.test-mojom index ab932ae..3dbd259 100644 --- a/ash/public/interfaces/shell_test_api.test-mojom +++ b/ash/public/interfaces/shell_test_api.test-mojom
@@ -33,8 +33,4 @@ // Set the minimum velocity to cause fling gesture. SetMinFlingVelocity(float velocity); - - // Returns the number of child windows for the given container in the primary - // root window. - GetChildWindowCountInContainer(int32 container_id) => (int32 count); };
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index bdda4de..3d37e025 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -12,6 +12,7 @@ #include "ash/assistant/assistant_controller.h" #include "ash/assistant/assistant_ui_controller.h" #include "ash/assistant/model/assistant_ui_model.h" +#include "ash/home_screen/home_screen_controller.h" #include "ash/public/cpp/shelf_types.h" #include "ash/session/session_controller.h" #include "ash/shelf/assistant_overlay.h" @@ -52,10 +53,8 @@ constexpr uint8_t kVoiceInteractionRunningAlpha = 255; // 100% alpha constexpr uint8_t kVoiceInteractionNotRunningAlpha = 138; // 54% alpha -bool IsTabletMode() { - return Shell::Get() - ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled(); +bool IsHomeScreenAvailable() { + return Shell::Get()->home_screen_controller()->IsHomeScreenAvailable(); } } // namespace @@ -97,9 +96,9 @@ } void AppListButton::OnAppListShown() { - // Do not show a highlight in tablet mode since the "homecher" view is always - // open in the background. - if (!IsTabletMode()) + // Do not show a highlight if the home screen is available, since the home + // screen view is always open in the background. + if (!IsHomeScreenAvailable()) AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr); is_showing_app_list_ = true; shelf_->UpdateAutoHideState(); @@ -120,8 +119,10 @@ assistant_overlay_->EndAnimation(); assistant_animation_delay_timer_->Stop(); } - if (!Shell::Get()->app_list_controller()->IsVisible() || IsTabletMode()) + if (!Shell::Get()->app_list_controller()->IsVisible() || + IsHomeScreenAvailable()) { AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, event); + } Button::OnGestureEvent(event); return; @@ -141,8 +142,10 @@ base::Bind(&AppListButton::StartVoiceInteractionAnimation, base::Unretained(this))); } - if (!Shell::Get()->app_list_controller()->IsVisible() || IsTabletMode()) + if (!Shell::Get()->app_list_controller()->IsVisible() || + IsHomeScreenAvailable()) { AnimateInkDrop(views::InkDropState::ACTION_PENDING, event); + } Button::OnGestureEvent(event); // If assistant overlay animation starts, we need to make sure the event
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc index 1cdbdda8..f1d0ef8 100644 --- a/ash/shell_test_api.cc +++ b/ash/shell_test_api.cc
@@ -131,15 +131,4 @@ ui::GestureConfiguration::GetInstance()->set_min_fling_velocity(velocity); } -void ShellTestApi::GetChildWindowCountInContainer( - int container_id, - GetChildWindowCountInContainerCallback cb) { - auto* container = - ash::Shell::GetPrimaryRootWindow()->GetChildById(container_id); - // Return an negative count to indicate that the container is invalid. - if (!container) - std::move(cb).Run(-1); - std::move(cb).Run(container->children().size()); -} - } // namespace ash
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h index a68e97e..97f815b 100644 --- a/ash/shell_test_api.h +++ b/ash/shell_test_api.h
@@ -63,9 +63,6 @@ void ToggleOverviewMode(ToggleOverviewModeCallback cb) override; void AddRemoveDisplay() override; void SetMinFlingVelocity(float velocity) override; - void GetChildWindowCountInContainer( - int container_id, - GetChildWindowCountInContainerCallback cb) override; private: Shell* shell_; // not owned
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc index 9a796c5..0bcab3b 100644 --- a/ash/system/power/power_button_controller_unittest.cc +++ b/ash/system/power/power_button_controller_unittest.cc
@@ -28,7 +28,6 @@ #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" #include "chromeos/dbus/fake_power_manager_client.h" -#include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/dbus/power_manager/suspend.pb.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/test/display_manager_test_api.h" @@ -402,7 +401,7 @@ PressLockButton(); ReleaseLockButton(); EXPECT_TRUE(lock_state_test_api_->is_animating_lock()); - EXPECT_EQ(1, session_manager_client_->request_lock_screen_call_count()); + EXPECT_TRUE(GetLockedState()); } // Tests press lock/power button before release power/lock button. @@ -417,7 +416,7 @@ ReleaseLockButton(); ReleasePowerButton(); EXPECT_FALSE(lock_state_test_api_->is_animating_lock()); - EXPECT_EQ(0, session_manager_client_->request_lock_screen_call_count()); + EXPECT_FALSE(GetLockedState()); EXPECT_TRUE(power_manager_client()->backlights_forced_off()); // Turn the screen on. @@ -430,7 +429,7 @@ ReleasePowerButton(); ReleaseLockButton(); EXPECT_TRUE(lock_state_test_api_->is_animating_lock()); - EXPECT_EQ(1, session_manager_client_->request_lock_screen_call_count()); + EXPECT_TRUE(GetLockedState()); EXPECT_FALSE(power_manager_client()->backlights_forced_off()); }
diff --git a/ash/system/power/power_button_test_base.cc b/ash/system/power/power_button_test_base.cc index 4a3de7ab..2a78c90 100644 --- a/ash/system/power/power_button_test_base.cc +++ b/ash/system/power/power_button_test_base.cc
@@ -17,9 +17,7 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/test/simple_test_tick_clock.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_power_manager_client.h" -#include "chromeos/dbus/fake_session_manager_client.h" #include "ui/events/event.h" #include "ui/events/test/event_generator.h" @@ -30,12 +28,6 @@ PowerButtonTestBase::~PowerButtonTestBase() = default; void PowerButtonTestBase::SetUp() { - // This also initializes DBusThreadManager. - std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter = - chromeos::DBusThreadManager::GetSetterForTesting(); - session_manager_client_ = new chromeos::FakeSessionManagerClient; - dbus_setter->SetSessionManagerClient( - base::WrapUnique(session_manager_client_)); AshTestBase::SetUp(); lock_state_controller_ = Shell::Get()->lock_state_controller(); @@ -45,7 +37,6 @@ void PowerButtonTestBase::TearDown() { AshTestBase::TearDown(); - chromeos::DBusThreadManager::Shutdown(); } void PowerButtonTestBase::ResetPowerButtonController() {
diff --git a/ash/system/power/power_button_test_base.h b/ash/system/power/power_button_test_base.h index b2a37eb..823b70a 100644 --- a/ash/system/power/power_button_test_base.h +++ b/ash/system/power/power_button_test_base.h
@@ -12,10 +12,6 @@ #include "base/test/simple_test_tick_clock.h" #include "ui/events/keycodes/keyboard_codes_posix.h" -namespace chromeos { -class FakeSessionManagerClient; -} // namespace chromeos - namespace ash { class LockStateController; @@ -84,9 +80,6 @@ // they come too close. void AdvanceClockToAvoidIgnoring(); - // Ownership is passed on to chromeos::DBusThreadManager. - chromeos::FakeSessionManagerClient* session_manager_client_ = nullptr; - PowerButtonController* power_button_controller_ = nullptr; // Not owned. LockStateController* lock_state_controller_ = nullptr; // Not owned. PowerButtonScreenshotController* screenshot_controller_ =
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index 44395df..7120da1 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -30,8 +30,6 @@ #include "base/strings/string_util.h" #include "base/system/sys_info.h" #include "base/timer/timer.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/session_manager_client.h" #include "ui/aura/window_tree_host.h" #include "ui/views/controls/menu/menu_controller.h" #include "ui/wm/core/compound_event_filter.h" @@ -506,9 +504,7 @@ base::RecordAction( base::UserMetricsAction("Accel_LockScreen_LockButton")); } - chromeos::DBusThreadManager::Get() - ->GetSessionManagerClient() - ->RequestLockScreen(); + Shell::Get()->session_controller()->LockScreen(); } lock_fail_timer_.Start(FROM_HERE, kLockFailTimeout, this,
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc index e6620ba..1a78300 100644 --- a/ash/wm/lock_state_controller_unittest.cc +++ b/ash/wm/lock_state_controller_unittest.cc
@@ -26,7 +26,6 @@ #include "base/run_loop.h" #include "base/time/time.h" #include "chromeos/dbus/fake_power_manager_client.h" -#include "chromeos/dbus/fake_session_manager_client.h" #include "ui/display/manager/display_configurator.h" #include "ui/display/manager/fake_display_snapshot.h" #include "ui/display/types/display_constants.h" @@ -316,13 +315,12 @@ test_animator_->CompleteAllAnimations(true); ExpectPreLockAnimationFinished(); - EXPECT_EQ(1, session_manager_client_->request_lock_screen_call_count()); - // Notify that we locked successfully. lock_state_controller_->OnStartingLock(); EXPECT_EQ(0u, test_animator_->GetAnimationCount()); - LockScreen(); + Shell::Get()->session_controller()->FlushMojoForTest(); + EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked()); ExpectPostLockAnimationStarted(); test_animator_->CompleteAllAnimations(true); @@ -443,7 +441,7 @@ PressLockButton(); EXPECT_FALSE(lock_state_test_api_->is_animating_lock()); ReleaseLockButton(); - EXPECT_EQ(0, session_manager_client_->request_lock_screen_call_count()); + EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked()); } // Test the basic operation of the lock button (guest). @@ -454,7 +452,7 @@ PressLockButton(); EXPECT_FALSE(lock_state_test_api_->is_animating_lock()); ReleaseLockButton(); - EXPECT_EQ(0, session_manager_client_->request_lock_screen_call_count()); + EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked()); } // Test the basic operation of the lock button. @@ -474,14 +472,16 @@ Advance(SessionStateAnimator::ANIMATION_SPEED_MOVE_WINDOWS); ExpectUnlockedState(); - EXPECT_EQ(0, session_manager_client_->request_lock_screen_call_count()); + EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked()); // Press the button again and let the lock timeout fire. We should request // that the screen be locked. PressLockButton(); ExpectPreLockAnimationStarted(); Advance(SessionStateAnimator::ANIMATION_SPEED_UNDOABLE); - EXPECT_EQ(1, session_manager_client_->request_lock_screen_call_count()); + + Shell::Get()->session_controller()->FlushMojoForTest(); + EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked()); // Pressing the lock button while we have a pending lock request shouldn't do // anything. @@ -491,7 +491,6 @@ ReleaseLockButton(); // Pressing the button also shouldn't do anything after the screen is locked. - LockScreen(); ExpectPostLockAnimationStarted(); PressLockButton(); @@ -518,7 +517,7 @@ EXPECT_LT(0u, test_animator_->GetAnimationCount()); test_animator_->CompleteAllAnimations(true); - EXPECT_EQ(0, session_manager_client_->request_lock_screen_call_count()); + EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked()); } // When we hear that the process is exiting but we haven't had a chance to
diff --git a/ash/wm/overview/caption_container_view.cc b/ash/wm/overview/caption_container_view.cc index 9c67eb8..2c0964a 100644 --- a/ash/wm/overview/caption_container_view.cc +++ b/ash/wm/overview/caption_container_view.cc
@@ -7,8 +7,6 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" #include "ash/wm/overview/overview_constants.h" -#include "ash/wm/overview/overview_item.h" -#include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/rounded_rect_view.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/splitview/split_view_constants.h" @@ -42,11 +40,6 @@ // title. constexpr gfx::Size kIconSize{24, 24}; -// The amount we need to offset the close button so that the icon, which is -// smaller than the actual button is lined up with the right side of the window -// preview. -constexpr int kCloseButtonOffsetDp = 8; - constexpr int kCloseButtonInkDropInsetDp = 2; constexpr SkColor kCloseButtonColor = SK_ColorWHITE; @@ -70,13 +63,20 @@ parent->AddChildView(child); } +gfx::PointF ConvertToScreen(views::View* view, const gfx::Point& location) { + gfx::Point location_copy(location); + views::View::ConvertPointToScreen(view, &location_copy); + return gfx::PointF(location_copy); +} + } // namespace // The close button for the caption container view. It has a custom ink drop. class CaptionContainerView::OverviewCloseButton : public views::ImageButton { public: - explicit OverviewCloseButton(views::ButtonListener* listener) - : views::ImageButton(listener) { + explicit OverviewCloseButton( + CaptionContainerView::EventDelegate* event_delegate) + : views::ImageButton(nullptr), event_delegate_(event_delegate) { SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); SetImage( views::Button::STATE_NORMAL, @@ -91,7 +91,7 @@ ~OverviewCloseButton() override = default; // Resets the listener so that the listener can go out of scope. - void ResetListener() { listener_ = nullptr; } + void ResetEventDelegate() { event_delegate_ = nullptr; } protected: // views::Button: @@ -118,6 +118,10 @@ return std::make_unique<views::CircleInkDropMask>( size(), GetLocalBounds().CenterPoint(), GetInkDropRadius()); } + void NotifyClick(const ui::Event& event) override { + if (event_delegate_) + event_delegate_->HandleCloseButtonClicked(); + } private: int GetInkDropRadius() const { @@ -125,123 +129,25 @@ kCloseButtonInkDropInsetDp; } + CaptionContainerView::EventDelegate* event_delegate_; + DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); }; -// A Button that has a listener and listens to mouse / gesture events on the -// visible part of an overview window. -class CaptionContainerView::ShieldButton : public views::Button { - public: - ShieldButton(views::ButtonListener* listener, const base::string16& name) - : views::Button(listener) { - // The shield button should not be focusable. It's also to avoid - // accessibility error when |name| is empty. - SetFocusBehavior(FocusBehavior::NEVER); - SetAccessibleName(name); - } - ~ShieldButton() override = default; - - // When OverviewItem (which is a ButtonListener) is destroyed, its - // |item_widget_| is allowed to stay around to complete any animations. - // Resetting the listener in all views that are targeted by events is - // necessary to prevent a crash when a user clicks on the fading out widget - // after the OverviewItem has been destroyed. - void ResetListener() { listener_ = nullptr; } - - // views::View: - bool OnMousePressed(const ui::MouseEvent& event) override { - if (listener()) { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - listener()->HandlePressEvent(gfx::PointF(location)); - return true; - } - return views::Button::OnMousePressed(event); - } - - bool OnMouseDragged(const ui::MouseEvent& event) override { - if (listener()) { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - listener()->HandleDragEvent(gfx::PointF(location)); - return true; - } - return views::Button::OnMouseDragged(event); - } - - void OnMouseReleased(const ui::MouseEvent& event) override { - if (listener()) { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - listener()->HandleReleaseEvent(gfx::PointF(location)); - return; - } - views::Button::OnMouseReleased(event); - } - - void OnGestureEvent(ui::GestureEvent* event) override { - if (IsSlidingOutOverviewFromShelf()) { - event->SetHandled(); - return; - } - - if (listener()) { - const gfx::PointF location = - event->details().bounding_box_f().CenterPoint(); - switch (event->type()) { - case ui::ET_GESTURE_TAP_DOWN: - listener()->HandlePressEvent(location); - break; - case ui::ET_GESTURE_SCROLL_UPDATE: - listener()->HandleDragEvent(location); - break; - case ui::ET_SCROLL_FLING_START: - listener()->HandleFlingStartEvent(location, - event->details().velocity_x(), - event->details().velocity_y()); - break; - case ui::ET_GESTURE_SCROLL_END: - listener()->HandleReleaseEvent(location); - break; - case ui::ET_GESTURE_LONG_PRESS: - listener()->HandleLongPressEvent(location); - break; - case ui::ET_GESTURE_TAP: - listener()->ActivateDraggedWindow(); - break; - case ui::ET_GESTURE_END: - listener()->ResetDraggedWindowGesture(); - break; - default: - break; - } - event->SetHandled(); - return; - } - views::Button::OnGestureEvent(event); - } - - OverviewItem* listener() { return static_cast<OverviewItem*>(listener_); } - - protected: - // views::View: - const char* GetClassName() const override { return "ShieldButton"; } - - private: - DISALLOW_COPY_AND_ASSIGN(ShieldButton); -}; - -CaptionContainerView::CaptionContainerView(views::ButtonListener* listener, - aura::Window* window) { - listener_button_ = new ShieldButton(listener, window->GetTitle()); - AddChildView(listener_button_); +CaptionContainerView::CaptionContainerView(EventDelegate* event_delegate, + aura::Window* window) + : Button(nullptr), event_delegate_(event_delegate) { + // This should not be focusable. It's also to avoid accessibility error when + // |window->GetTitle()| is empty. + SetFocusBehavior(FocusBehavior::NEVER); + SetAccessibleName(window->GetTitle()); header_view_ = new views::View(); views::BoxLayout* layout = header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(), kHorizontalLabelPaddingDp)); - AddChildWithLayer(listener_button_, header_view_); + AddChildWithLayer(this, header_view_); // Prefer kAppIconSmallKey (set by the client in Mash), then kAppIconKey and // kWindowIconKey (set for client windows in classic Ash but not Mash). @@ -268,7 +174,7 @@ header_view_->AddChildView(title_label_); layout->SetFlexForView(title_label_, 1); - close_button_ = new OverviewCloseButton(listener); + close_button_ = new OverviewCloseButton(event_delegate); AddChildWithLayer(header_view_, close_button_); } @@ -336,18 +242,14 @@ : SPLITVIEW_ANIMATION_OVERVIEW_ITEM_FADE_OUT); } -void CaptionContainerView::ResetListener() { - listener_button_->ResetListener(); - close_button_->ResetListener(); +void CaptionContainerView::ResetEventDelegate() { + event_delegate_ = nullptr; + close_button_->ResetEventDelegate(); } void CaptionContainerView::SetTitle(const base::string16& title) { title_label_->SetText(title); - listener_button_->SetAccessibleName(title); -} - -views::View* CaptionContainerView::GetListenerButton() { - return listener_button_; + SetAccessibleName(title); } views::ImageButton* CaptionContainerView::GetCloseButton() { @@ -357,7 +259,6 @@ void CaptionContainerView::Layout() { gfx::Rect bounds(GetLocalBounds()); bounds.Inset(kOverviewMargin, kOverviewMargin); - listener_button_->SetBoundsRect(bounds); const int visible_height = close_button_->GetPreferredSize().height(); if (backdrop_view_) { @@ -382,12 +283,10 @@ cannot_snap_container_->SetBoundsRect(cannot_snap_bounds); } - // Position the header at the top. The right side of the header should be - // positioned so that the rightmost of the close icon matches the right side - // of the window preview. - gfx::Rect header_bounds = GetLocalBounds(); - header_bounds.Inset(0, 0, kCloseButtonOffsetDp, 0); - header_bounds.set_height(visible_height); + // Position the header at the top. + const gfx::Rect header_bounds(kOverviewMargin, kOverviewMargin, + GetLocalBounds().width() - kOverviewMargin, + visible_height); header_view_->SetBoundsRect(header_bounds); } @@ -395,6 +294,84 @@ return "CaptionContainerView"; } +bool CaptionContainerView::OnMousePressed(const ui::MouseEvent& event) { + if (!event_delegate_) + return Button::OnMousePressed(event); + event_delegate_->HandlePressEvent(ConvertToScreen(this, event.location())); + return true; +} + +bool CaptionContainerView::OnMouseDragged(const ui::MouseEvent& event) { + if (!event_delegate_) + return Button::OnMouseDragged(event); + event_delegate_->HandleDragEvent(ConvertToScreen(this, event.location())); + return true; +} + +void CaptionContainerView::OnMouseReleased(const ui::MouseEvent& event) { + if (!event_delegate_) { + Button::OnMouseReleased(event); + return; + } + event_delegate_->HandleReleaseEvent(ConvertToScreen(this, event.location())); +} + +void CaptionContainerView::OnGestureEvent(ui::GestureEvent* event) { + if (!event_delegate_) + return; + + if (event_delegate_->ShouldIgnoreGestureEvents()) { + event->SetHandled(); + return; + } + + const gfx::PointF location = event->details().bounding_box_f().CenterPoint(); + switch (event->type()) { + case ui::ET_GESTURE_TAP_DOWN: + event_delegate_->HandlePressEvent(location); + break; + case ui::ET_GESTURE_SCROLL_UPDATE: + event_delegate_->HandleDragEvent(location); + break; + case ui::ET_SCROLL_FLING_START: + event_delegate_->HandleFlingStartEvent(location, + event->details().velocity_x(), + event->details().velocity_y()); + break; + case ui::ET_GESTURE_SCROLL_END: + event_delegate_->HandleReleaseEvent(location); + break; + case ui::ET_GESTURE_LONG_PRESS: + event_delegate_->HandleLongPressEvent(location); + break; + case ui::ET_GESTURE_TAP: + event_delegate_->HandleTapEvent(); + break; + case ui::ET_GESTURE_END: + event_delegate_->HandleGestureEndEvent(); + break; + default: + break; + } + event->SetHandled(); +} + +bool CaptionContainerView::CanAcceptEvent(const ui::Event& event) { + bool accept_events = true; + // Do not process or accept press down events that are on the border. + static ui::EventType press_types[] = {ui::ET_GESTURE_TAP_DOWN, + ui::ET_MOUSE_PRESSED}; + if (event.IsLocatedEvent() && + base::ContainsValue(press_types, event.type())) { + gfx::Rect inset_bounds = GetLocalBounds(); + inset_bounds.Inset(gfx::Insets(kOverviewMargin)); + if (!inset_bounds.Contains(event.AsLocatedEvent()->location())) + accept_events = false; + } + + return accept_events && Button::CanAcceptEvent(event); +} + void CaptionContainerView::AnimateLayerOpacity(ui::Layer* layer, bool visible) { float target_opacity = visible ? 1.f : 0.f; if (layer->GetTargetOpacity() == target_opacity)
diff --git a/ash/wm/overview/caption_container_view.h b/ash/wm/overview/caption_container_view.h index 5b711de1..582e68bd 100644 --- a/ash/wm/overview/caption_container_view.h +++ b/ash/wm/overview/caption_container_view.h
@@ -7,8 +7,7 @@ #include "ash/ash_export.h" #include "base/macros.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/views/view.h" +#include "ui/views/controls/button/button.h" namespace aura { class Window; @@ -19,10 +18,10 @@ } // namespace ui namespace views { -class ButtonListener; class ImageButton; class ImageView; class Label; +class View; } // namespace views namespace ash { @@ -33,7 +32,7 @@ // also draws a header for overview mode which contains a icon, title and close // button. // TODO(sammiequon): Rename this to something which describes it better. -class ASH_EXPORT CaptionContainerView : public views::View { +class ASH_EXPORT CaptionContainerView : public views::Button { public: // The visibility of the header. It may be fully visible or invisible, or // everything but the close button is visible. @@ -43,7 +42,27 @@ kVisible, }; - CaptionContainerView(views::ButtonListener* listener, aura::Window* window); + class EventDelegate { + public: + // TODO: Maybe consolidate into just mouse and gesture events. + virtual void HandlePressEvent(const gfx::PointF& location_in_screen) = 0; + virtual void HandleDragEvent(const gfx::PointF& location_in_screen) = 0; + virtual void HandleReleaseEvent(const gfx::PointF& location_in_screen) = 0; + virtual void HandleFlingStartEvent(const gfx::PointF& location_in_screen, + float velocity_x, + float velocity_y) = 0; + virtual void HandleLongPressEvent( + const gfx::PointF& location_in_screen) = 0; + virtual void HandleTapEvent() = 0; + virtual void HandleGestureEndEvent() = 0; + virtual void HandleCloseButtonClicked() = 0; + virtual bool ShouldIgnoreGestureEvents() = 0; + + protected: + virtual ~EventDelegate() {} + }; + + CaptionContainerView(EventDelegate* event_delegate, aura::Window* window); ~CaptionContainerView() override; // Returns |cannot_snap_container_|. This will create it if it has not been @@ -58,12 +77,11 @@ // Animates |cannot_snap_container_| to its visibility state. void SetCannotSnapLabelVisibility(bool visible); - void ResetListener(); + void ResetEventDelegate(); // Set the title of the view, and also updates the accessiblity name. void SetTitle(const base::string16& title); - views::View* GetListenerButton(); views::ImageButton* GetCloseButton(); views::View* header_view() { return header_view_; } @@ -75,10 +93,14 @@ // views::View: void Layout() override; const char* GetClassName() const override; + bool OnMousePressed(const ui::MouseEvent& event) override; + bool OnMouseDragged(const ui::MouseEvent& event) override; + void OnMouseReleased(const ui::MouseEvent& event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + bool CanAcceptEvent(const ui::Event& event) override; private: class OverviewCloseButton; - class ShieldButton; // Animates |layer| from 0 -> 1 opacity if |visible| and 1 -> 0 opacity // otherwise. The tween type differs for |visible| and if |visible| is true @@ -86,8 +108,8 @@ // opacity matches |visible|. void AnimateLayerOpacity(ui::Layer* layer, bool visible); - // |listener_button_| handles input events and notifies the button listener. - ShieldButton* listener_button_ = nullptr; + // The delegate which all the events get forwarded to. + EventDelegate* event_delegate_; // View which contains the icon, title and close button. views::View* header_view_ = nullptr;
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index 79026bd..b103fa98 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -10,7 +10,6 @@ #include "ash/public/cpp/window_properties.h" #include "ash/scoped_animation_disabler.h" #include "ash/shell.h" -#include "ash/wm/overview/caption_container_view.h" #include "ash/wm/overview/overview_animation_type.h" #include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_controller.h" @@ -106,14 +105,18 @@ overview_session_(overview_session), overview_grid_(overview_grid) { CreateWindowLabel(); - for (auto* window_iter : wm::GetTransientTreeIterator(GetWindow())) + for (auto* window_iter : wm::WindowTransientDescendantIteratorRange( + wm::WindowTransientDescendantIterator(GetWindow()))) { window_iter->AddObserver(this); + } GetWindow()->SetProperty(ash::kIsShowingInOverviewKey, true); } OverviewItem::~OverviewItem() { - for (auto* window_iter : wm::GetTransientTreeIterator(GetWindow())) + for (auto* window_iter : wm::WindowTransientDescendantIteratorRange( + wm::WindowTransientDescendantIterator(GetWindow()))) { window_iter->RemoveObserver(this); + } GetWindow()->ClearProperty(ash::kIsShowingInOverviewKey); } @@ -136,7 +139,7 @@ } void OverviewItem::RestoreWindow(bool reset_transform) { - caption_container_view_->ResetListener(); + caption_container_view_->ResetEventDelegate(); transform_window_.RestoreWindow( reset_transform, overview_session_->enter_exit_overview_type()); } @@ -285,7 +288,7 @@ } void OverviewItem::SendAccessibleSelectionEvent() { - caption_container_view_->GetListenerButton()->NotifyAccessibilityEvent( + caption_container_view_->NotifyAccessibilityEvent( ax::mojom::Event::kSelection, true); } @@ -294,7 +297,7 @@ animating_to_close_ = true; overview_session_->PositionWindows(/*animate=*/true); - caption_container_view_->ResetListener(); + caption_container_view_->ResetEventDelegate(); int translation_y = kSwipeToCloseCloseTranslationDp * (up ? -1 : 1); gfx::Transform transform; @@ -411,61 +414,6 @@ SetBounds(scaled_bounds, animation_type); } -void OverviewItem::HandlePressEvent(const gfx::PointF& location_in_screen) { - // We allow switching finger while dragging, but do not allow dragging two or - // more items. - if (overview_session_->window_drag_controller() && - overview_session_->window_drag_controller()->item()) { - return; - } - - StartDrag(); - overview_session_->InitiateDrag(this, location_in_screen); -} - -void OverviewItem::HandleReleaseEvent(const gfx::PointF& location_in_screen) { - if (!IsDragItem()) - return; - - overview_grid_->SetSelectionWidgetVisibility(true); - overview_session_->CompleteDrag(this, location_in_screen); -} - -void OverviewItem::HandleDragEvent(const gfx::PointF& location_in_screen) { - if (!IsDragItem()) - return; - - overview_session_->Drag(this, location_in_screen); -} - -void OverviewItem::HandleLongPressEvent(const gfx::PointF& location_in_screen) { - if (!ShouldAllowSplitView()) - return; - - overview_session_->StartSplitViewDragMode(location_in_screen); -} - -void OverviewItem::HandleFlingStartEvent(const gfx::PointF& location_in_screen, - float velocity_x, - float velocity_y) { - overview_session_->Fling(this, location_in_screen, velocity_x, velocity_y); -} - -void OverviewItem::ActivateDraggedWindow() { - if (!IsDragItem()) - return; - - overview_session_->ActivateDraggedWindow(); -} - -void OverviewItem::ResetDraggedWindowGesture() { - if (!IsDragItem()) - return; - - OnSelectorItemDragEnded(); - overview_session_->ResetDraggedWindowGesture(); -} - bool OverviewItem::IsDragItem() { return overview_session_->window_drag_controller() && overview_session_->window_drag_controller()->item() == this; @@ -606,29 +554,78 @@ : OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO; } -void OverviewItem::ButtonPressed(views::Button* sender, - const ui::Event& event) { - if (IsSlidingOutOverviewFromShelf()) - return; - - if (sender == caption_container_view_->GetCloseButton()) { - base::RecordAction( - base::UserMetricsAction("WindowSelector_OverviewCloseButton")); - if (Shell::Get() - ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled()) { - base::RecordAction( - base::UserMetricsAction("Tablet_WindowCloseFromOverviewButton")); - } - CloseWindow(); +void OverviewItem::HandlePressEvent(const gfx::PointF& location_in_screen) { + // We allow switching finger while dragging, but do not allow dragging two or + // more items. + if (overview_session_->window_drag_controller() && + overview_session_->window_drag_controller()->item()) { return; } - CHECK_EQ(sender, caption_container_view_->GetListenerButton()); + StartDrag(); + overview_session_->InitiateDrag(this, location_in_screen); +} - // For other cases, the event is handled in OverviewWindowDragController. +void OverviewItem::HandleReleaseEvent(const gfx::PointF& location_in_screen) { + if (!IsDragItem()) + return; + + overview_grid_->SetSelectionWidgetVisibility(true); + overview_session_->CompleteDrag(this, location_in_screen); +} + +void OverviewItem::HandleDragEvent(const gfx::PointF& location_in_screen) { + if (!IsDragItem()) + return; + + overview_session_->Drag(this, location_in_screen); +} + +void OverviewItem::HandleLongPressEvent(const gfx::PointF& location_in_screen) { if (!ShouldAllowSplitView()) - overview_session_->SelectWindow(this); + return; + + overview_session_->StartSplitViewDragMode(location_in_screen); +} + +void OverviewItem::HandleFlingStartEvent(const gfx::PointF& location_in_screen, + float velocity_x, + float velocity_y) { + overview_session_->Fling(this, location_in_screen, velocity_x, velocity_y); +} + +void OverviewItem::HandleTapEvent() { + if (!IsDragItem()) + return; + + overview_session_->ActivateDraggedWindow(); +} + +void OverviewItem::HandleGestureEndEvent() { + if (!IsDragItem()) + return; + + OnSelectorItemDragEnded(); + overview_session_->ResetDraggedWindowGesture(); +} + +void OverviewItem::HandleCloseButtonClicked() { + if (IsSlidingOutOverviewFromShelf()) + return; + + base::RecordAction( + base::UserMetricsAction("WindowSelector_OverviewCloseButton")); + if (Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled()) { + base::RecordAction( + base::UserMetricsAction("Tablet_WindowCloseFromOverviewButton")); + } + CloseWindow(); +} + +bool OverviewItem::ShouldIgnoreGestureEvents() { + return IsSlidingOutOverviewFromShelf(); } void OverviewItem::OnWindowBoundsChanged(aura::Window* window, @@ -719,21 +716,21 @@ } void OverviewItem::CreateWindowLabel() { - views::Widget::InitParams params_label; - params_label.type = views::Widget::InitParams::TYPE_POPUP; - params_label.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params_label.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params_label.visible_on_all_workspaces = true; - params_label.layer_type = ui::LAYER_NOT_DRAWN; - params_label.name = "OverviewModeLabel"; - params_label.activatable = + views::Widget::InitParams params; + params.type = views::Widget::InitParams::TYPE_POPUP; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; + params.visible_on_all_workspaces = true; + params.layer_type = ui::LAYER_NOT_DRAWN; + params.name = "OverviewModeLabel"; + params.activatable = views::Widget::InitParams::Activatable::ACTIVATABLE_DEFAULT; - params_label.accept_events = true; - params_label.parent = transform_window_.window()->parent(); + params.accept_events = true; + params.parent = transform_window_.window()->parent(); item_widget_ = std::make_unique<views::Widget>(); item_widget_->set_focus_on_creation(false); - item_widget_->Init(params_label); + item_widget_->Init(params); aura::Window* widget_window = item_widget_->GetNativeWindow(); widget_window->parent()->StackChildBelow(widget_window, transform_window_.window()); @@ -756,16 +753,9 @@ transform_window_.GetTransformedBounds()); ::wm::TranslateRectFromScreen(root_window_, &transformed_window_bounds); - gfx::Rect label_rect(kHeaderHeightDp, kHeaderHeightDp); - label_rect.set_width(transformed_window_bounds.width()); - // For tabbed windows the initial bounds of the caption are set such that it - // appears to be "growing" up from the window content area. - label_rect.set_y(-label_rect.height()); - aura::Window* widget_window = item_widget_->GetNativeWindow(); ScopedOverviewAnimationSettings animation_settings(animation_type, widget_window); - // Create a start animation observer if this is an enter overview layout // animation. if (animation_type == OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_ON_ENTER) { @@ -775,12 +765,13 @@ std::move(start_observer)); } - // |widget_window| covers both the transformed window and the header - // as well as the gap between the windows to prevent events from reaching - // the window including its sizing borders. - label_rect.set_height(kHeaderHeightDp + transformed_window_bounds.height()); + // |widget_window| is sized to the same bounds as the original window plus + // some space for the header and a little padding. + gfx::Rect label_rect(0, -kHeaderHeightDp, transformed_window_bounds.width(), + kHeaderHeightDp + transformed_window_bounds.height()); label_rect.Inset(-kOverviewMargin, -kOverviewMargin); widget_window->SetBounds(label_rect); + gfx::Transform label_transform; label_transform.Translate(gfx::ToRoundedInt(transformed_window_bounds.x()), gfx::ToRoundedInt(transformed_window_bounds.y()));
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h index f16f768..5a5bd73 100644 --- a/ash/wm/overview/overview_item.h +++ b/ash/wm/overview/overview_item.h
@@ -8,6 +8,7 @@ #include <memory> #include "ash/ash_export.h" +#include "ash/wm/overview/caption_container_view.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/scoped_overview_transform_window.h" #include "base/macros.h" @@ -26,12 +27,10 @@ } // namespace views namespace ash { - -class CaptionContainerView; class OverviewGrid; // This class represents an item in overview mode. -class ASH_EXPORT OverviewItem : public views::ButtonListener, +class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate, public aura::WindowObserver, public ui::ImplicitAnimationObserver { public: @@ -156,17 +155,6 @@ // If the window item represents a minimized window, update its content view. void UpdateItemContentViewForMinimizedWindow(); - // Handle the mouse/gesture event and facilitate dragging the item. - void HandlePressEvent(const gfx::PointF& location_in_screen); - void HandleReleaseEvent(const gfx::PointF& location_in_screen); - void HandleDragEvent(const gfx::PointF& location_in_screen); - void HandleLongPressEvent(const gfx::PointF& location_in_screen); - void HandleFlingStartEvent(const gfx::PointF& location_in_screen, - float velocity_x, - float velocity_y); - void ActivateDraggedWindow(); - void ResetDraggedWindowGesture(); - // Checks if this item is current being dragged. bool IsDragItem(); @@ -194,8 +182,18 @@ OverviewAnimationType GetExitOverviewAnimationType(); OverviewAnimationType GetExitTransformAnimationType(); - // views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // CaptionContainerView::EventDelegate: + void HandlePressEvent(const gfx::PointF& location_in_screen) override; + void HandleReleaseEvent(const gfx::PointF& location_in_screen) override; + void HandleDragEvent(const gfx::PointF& location_in_screen) override; + void HandleLongPressEvent(const gfx::PointF& location_in_screen) override; + void HandleFlingStartEvent(const gfx::PointF& location_in_screen, + float velocity_x, + float velocity_y) override; + void HandleTapEvent() override; + void HandleGestureEndEvent() override; + void HandleCloseButtonClicked() override; + bool ShouldIgnoreGestureEvents() override; // aura::WindowObserver: void OnWindowBoundsChanged(aura::Window* window,
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc index b51b1f9b..4cac448 100644 --- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
@@ -6,7 +6,7 @@ #include <vector> -#include "ash/app_list/app_list_controller_impl.h" +#include "ash/home_screen/home_screen_controller.h" #include "ash/root_window_controller.h" #include "ash/scoped_animation_disabler.h" #include "ash/shell.h" @@ -145,9 +145,7 @@ } // Hide the home launcher if it's enabled during dragging. - // TODO(xdai): Move the hide/show home launcher logic to a general place in - // TabletModeWindowDragDelegate. - Shell::Get()->app_list_controller()->OnWindowDragStarted(); + Shell::Get()->home_screen_controller()->OnWindowDragStarted(); // Blurs the wallpaper background. RootWindowController::ForWindow(root_window) @@ -188,7 +186,7 @@ DCHECK(!Shell::Get()->overview_controller()->IsSelecting()); // May reshow the home launcher after dragging. - Shell::Get()->app_list_controller()->OnWindowDragEnded(); + Shell::Get()->home_screen_controller()->OnWindowDragEnded(); // Clears the background wallpaper blur. RootWindowController::ForWindow(dragged_window_->GetRootWindow())
diff --git a/base/BUILD.gn b/base/BUILD.gn index a2b1e0a..6379ad9 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2808,6 +2808,7 @@ "debug/elf_reader_unittest.cc", "files/dir_reader_posix_unittest.cc", "files/file_descriptor_watcher_posix_unittest.cc", + "fuchsia/file_utils_unittest.cc", "fuchsia/filtered_service_directory_unittest.cc", "fuchsia/service_directory_test_base.cc", "fuchsia/service_directory_test_base.h",
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java index a993647..10d1142 100644 --- a/base/android/java/src/org/chromium/base/LocaleUtils.java +++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -195,8 +195,8 @@ } /** - * @return a comma separated language tags string that represents a default locale. - * Each language tag is well-formed IETF BCP 47 language tag with language and country + * @return a language tag string that represents the default locale. + * The language tag is well-formed IETF BCP 47 language tag with language and country * code. */ @CalledByNative
diff --git a/base/containers/any_internal_unittest.cc b/base/containers/any_internal_unittest.cc index dacd2ff8..2b237f7 100644 --- a/base/containers/any_internal_unittest.cc +++ b/base/containers/any_internal_unittest.cc
@@ -4,13 +4,18 @@ #include "base/containers/any_internal.h" -#include <string> - #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace internal { +namespace { +struct OutOfLineStruct { + void* one; + void* two; +}; +} // namespace + TEST(AnyInternalTest, InlineOrOutlineStorage) { static_assert(AnyInternal::InlineStorageHelper<int>::kUseInlineStorage, "int should be stored inline"); @@ -20,8 +25,8 @@ AnyInternal::InlineStorageHelper<std::unique_ptr<int>>::kUseInlineStorage, "std::unique_ptr<int> should be stored inline"); static_assert( - !AnyInternal::InlineStorageHelper<std::string>::kUseInlineStorage, - "std::string should be stored out of line"); + !AnyInternal::InlineStorageHelper<OutOfLineStruct>::kUseInlineStorage, + "A struct with two pointers should be stored out of line"); } } // namespace internal
diff --git a/base/fuchsia/file_utils.cc b/base/fuchsia/file_utils.cc index bb012b8..07e957a 100644 --- a/base/fuchsia/file_utils.cc +++ b/base/fuchsia/file_utils.cc
@@ -4,10 +4,17 @@ #include "base/fuchsia/file_utils.h" +#include <fcntl.h> #include <lib/fdio/fd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> -#include "base/files/file.h" +#include <utility> + +#include "base/files/scoped_file.h" #include "base/fuchsia/fuchsia_logging.h" +#include "base/macros.h" namespace base { namespace fuchsia { @@ -16,26 +23,25 @@ const char kServiceDirectoryPath[] = "/svc"; const char kPackageRootDirectoryPath[] = "/pkg"; -zx::handle GetHandleFromFile(File file) { - zx::handle handle; - zx_status_t status = - fdio_fd_transfer(file.GetPlatformFile(), handle.reset_and_get_address()); - if (status != ZX_ERR_UNAVAILABLE) - ignore_result(file.TakePlatformFile()); - if (status == ZX_OK) - return handle; - ZX_DLOG(ERROR, status) << "fdio_fd_transfer"; - return zx::handle(); -} +fidl::InterfaceHandle<::fuchsia::io::Directory> OpenDirectory( + const base::FilePath& path) { + ScopedFD fd(open(path.value().c_str(), O_DIRECTORY | O_RDONLY)); + if (!fd.is_valid()) { + DPLOG(ERROR) << "Failed to open " << path; + return fidl::InterfaceHandle<::fuchsia::io::Directory>(); + } -base::File GetFileFromHandle(zx::handle handle) { - base::ScopedFD fd; + zx::channel channel; zx_status_t status = - fdio_fd_create(handle.release(), base::ScopedFD::Receiver(fd).get()); - if (status == ZX_OK) - return base::File(fd.release()); - ZX_LOG(WARNING, status) << "fdio_fd_create"; - return base::File(); + fdio_fd_transfer(fd.get(), channel.reset_and_get_address()); + if (status != ZX_ERR_UNAVAILABLE) + ignore_result(fd.release()); + if (status != ZX_OK) { + ZX_DLOG(ERROR, status) << "fdio_fd_transfer"; + return fidl::InterfaceHandle<::fuchsia::io::Directory>(); + } + + return fidl::InterfaceHandle<::fuchsia::io::Directory>(std::move(channel)); } } // namespace fuchsia
diff --git a/base/fuchsia/file_utils.h b/base/fuchsia/file_utils.h index 1b249929..b1df755 100644 --- a/base/fuchsia/file_utils.h +++ b/base/fuchsia/file_utils.h
@@ -5,14 +5,12 @@ #ifndef BASE_FUCHSIA_FILE_UTILS_H_ #define BASE_FUCHSIA_FILE_UTILS_H_ -#include <lib/zx/handle.h> +#include <fuchsia/io/cpp/fidl.h> #include "base/base_export.h" +#include "base/files/file_path.h" namespace base { - -class File; - namespace fuchsia { // Persisted data directory, i.e. /data . Returned as DIR_APP_DATA from @@ -25,14 +23,10 @@ // Package root directory, i.e. /pkg . BASE_EXPORT extern const char kPackageRootDirectoryPath[]; -// Gets a Zircon handle from a file or directory |path| in the process' -// namespace. -BASE_EXPORT zx::handle GetHandleFromFile(base::File file); - -// Makes a File object from a Zircon handle. -// Returns an empty File if |handle| is invalid or not a valid PA_FDIO_REMOTE -// descriptor. -BASE_EXPORT base::File GetFileFromHandle(zx::handle handle); +// Returns fuchsia.io.Directory for the specified |path| or null InterfaceHandle +// if the path doesn't exist or it's not a directory. +BASE_EXPORT fidl::InterfaceHandle<::fuchsia::io::Directory> OpenDirectory( + const base::FilePath& path); } // namespace fuchsia } // namespace base
diff --git a/base/fuchsia/file_utils_unittest.cc b/base/fuchsia/file_utils_unittest.cc new file mode 100644 index 0000000..11bb1a2 --- /dev/null +++ b/base/fuchsia/file_utils_unittest.cc
@@ -0,0 +1,44 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/fuchsia/file_utils.h" + +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace fuchsia { + +class OpenDirectoryTest : public testing::Test { + protected: + void SetUp() override { + EXPECT_TRUE(temp_dir.CreateUniqueTempDirUnderPath( + base::FilePath(kPersistedDataDirectoryPath))); + } + + ScopedTempDir temp_dir; +}; + +TEST_F(OpenDirectoryTest, Open) { + auto dir = OpenDirectory(temp_dir.GetPath()); + ASSERT_TRUE(dir); +} + +// OpenDirectory() should fail when opening a directory that doesn't exist. +TEST_F(OpenDirectoryTest, OpenNonExistent) { + auto dir = OpenDirectory(temp_dir.GetPath().AppendASCII("non_existent")); + ASSERT_FALSE(dir); +} + +// OpenDirectory() should open only directories. +TEST_F(OpenDirectoryTest, OpenFile) { + auto file_path = temp_dir.GetPath().AppendASCII("test_file"); + ASSERT_TRUE(WriteFile(file_path, "foo", 3)); + auto dir = OpenDirectory(file_path); + ASSERT_FALSE(dir); +} + +} // namespace fuchsia +} // namespace base \ No newline at end of file
diff --git a/base/fuchsia/service_directory_client.cc b/base/fuchsia/service_directory_client.cc index c3b1a47..3dc964f 100644 --- a/base/fuchsia/service_directory_client.cc +++ b/base/fuchsia/service_directory_client.cc
@@ -17,19 +17,11 @@ namespace { -fidl::InterfaceHandle<::fuchsia::io::Directory> ConnectToServiceRoot() { - fidl::InterfaceHandle<::fuchsia::io::Directory> directory; - zx_status_t result = fdio_service_connect( - kServiceDirectoryPath, directory.NewRequest().TakeChannel().release()); - ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc"; - return directory; -} - // Singleton container for the process-global ServiceDirectoryClient instance. std::unique_ptr<ServiceDirectoryClient>* ProcessServiceDirectoryClient() { static base::NoDestructor<std::unique_ptr<ServiceDirectoryClient>> - service_directory_client_ptr( - std::make_unique<ServiceDirectoryClient>(ConnectToServiceRoot())); + service_directory_client_ptr(std::make_unique<ServiceDirectoryClient>( + OpenDirectory(base::FilePath(kServiceDirectoryPath)))); return service_directory_client_ptr.get(); }
diff --git a/base/process/launch_fuchsia.cc b/base/process/launch_fuchsia.cc index 53c99f2b..3e840cdf 100644 --- a/base/process/launch_fuchsia.cc +++ b/base/process/launch_fuchsia.cc
@@ -180,14 +180,15 @@ } for (const auto& path_to_clone : options.paths_to_clone) { - zx::handle handle = fuchsia::GetHandleFromFile( - base::File(base::FilePath(path_to_clone), - base::File::FLAG_OPEN | base::File::FLAG_READ)); - if (!handle) { + fidl::InterfaceHandle<::fuchsia::io::Directory> directory = + base::fuchsia::OpenDirectory(path_to_clone); + if (!directory) { LOG(WARNING) << "Could not open handle for path: " << path_to_clone; return base::Process(); } + zx::handle handle = directory.TakeChannel(); + spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry( path_to_clone.value().c_str(), handle.get())); transferred_handles.push_back(std::move(handle));
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc index c694196..b08292b 100644 --- a/base/process/process_util_unittest.cc +++ b/base/process/process_util_unittest.cc
@@ -264,13 +264,14 @@ // Attach the tempdir to "data", but also try to duplicate the existing "data" // directory. - options.paths_to_clone.push_back(base::FilePath("/data")); + options.paths_to_clone.push_back( + base::FilePath(base::fuchsia::kPersistedDataDirectoryPath)); options.paths_to_clone.push_back(base::FilePath("/tmp")); options.paths_to_transfer.push_back( - {FilePath("/data"), - fuchsia::GetHandleFromFile( - base::File(base::FilePath(tmpdir_with_staged.GetPath()), - base::File::FLAG_OPEN | base::File::FLAG_READ)) + {FilePath(base::fuchsia::kPersistedDataDirectoryPath), + base::fuchsia::OpenDirectory( + base::FilePath(tmpdir_with_staged.GetPath())) + .TakeChannel() .release()}); // Verify from that "/data/staged" exists from the child process' perspective. @@ -307,14 +308,14 @@ staged_file.Close(); // Mount the tempdir to "/foo". - zx::handle tmp_handle = fuchsia::GetHandleFromFile( - base::File(base::FilePath(new_tmpdir.GetPath()), - base::File::FLAG_OPEN | base::File::FLAG_READ)); - ASSERT_TRUE(tmp_handle.is_valid()); + zx::channel tmp_channel = + base::fuchsia::OpenDirectory(new_tmpdir.GetPath()).TakeChannel(); + + ASSERT_TRUE(tmp_channel.is_valid()); LaunchOptions options; options.paths_to_clone.push_back(base::FilePath("/tmp")); options.paths_to_transfer.push_back( - {base::FilePath("/foo"), tmp_handle.release()}); + {base::FilePath("/foo"), tmp_channel.release()}); options.spawn_flags = FDIO_SPAWN_CLONE_STDIO; // Verify from that "/foo/staged" exists from the child process' perspective.
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 5d45100b..1dbafee 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -352,16 +352,16 @@ empty_queues_to_reload_.RunActiveCallbacks(); } -void SequenceManagerImpl::WakeUpReadyDelayedQueues(LazyNow* lazy_now) { +void SequenceManagerImpl::MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"), - "SequenceManagerImpl::WakeUpReadyDelayedQueues"); + "SequenceManagerImpl::MoveReadyDelayedTasksToWorkQueues"); for (TimeDomain* time_domain : main_thread_only().time_domains) { if (time_domain == main_thread_only().real_time_domain.get()) { - time_domain->WakeUpReadyDelayedQueues(lazy_now); + time_domain->MoveReadyDelayedTasksToWorkQueues(lazy_now); } else { LazyNow time_domain_lazy_now = time_domain->CreateLazyNow(); - time_domain->WakeUpReadyDelayedQueues(&time_domain_lazy_now); + time_domain->MoveReadyDelayedTasksToWorkQueues(&time_domain_lazy_now); } } } @@ -426,7 +426,7 @@ ReloadEmptyWorkQueues(); LazyNow lazy_now(controller_->GetClock()); - WakeUpReadyDelayedQueues(&lazy_now); + MoveReadyDelayedTasksToWorkQueues(&lazy_now); // If we sampled now, check if it's time to reclaim memory next time we go // idle. @@ -506,8 +506,9 @@ return TimeDelta(); // Otherwise we need to find the shortest delay, if any. NB we don't need to - // call WakeUpReadyDelayedQueues because it's assumed DelayTillNextTask will - // return TimeDelta>() if the delayed task is due to run now. + // call MoveReadyDelayedTasksToWorkQueues because it's assumed + // DelayTillNextTask will return TimeDelta>() if the delayed task is due to + // run now. TimeDelta delay_till_next_task = TimeDelta::Max(); for (TimeDomain* time_domain : main_thread_only().time_domains) { Optional<TimeDelta> delay = time_domain->DelayTillNextTask(lazy_now);
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index 4ca8d599..7718efc 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -311,7 +311,7 @@ // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and // reloads any empty work queues. - void WakeUpReadyDelayedQueues(LazyNow* lazy_now); + void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now); void NotifyWillProcessTask(ExecutingTask* task, LazyNow* time_before_task); void NotifyDidProcessTask(ExecutingTask* task, LazyNow* time_after_task);
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index 8ca4c366..b0985f6 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -755,13 +755,14 @@ // Move the task into the |delayed_work_queue|. LazyNow lazy_now(mock_tick_clock()); - sequence_manager()->WakeUpReadyDelayedQueues(&lazy_now); + sequence_manager()->MoveReadyDelayedTasksToWorkQueues(&lazy_now); + sequence_manager()->ScheduleWork(); EXPECT_FALSE(queue->GetTaskQueueImpl()->delayed_work_queue()->Empty()); EXPECT_TRUE(queue->HasTaskToRunImmediately()); // Run the task, making the queue empty. RunLoop().RunUntilIdle(); - EXPECT_FALSE(queue->HasTaskToRunImmediately()); + EXPECT_TRUE(queue->GetTaskQueueImpl()->delayed_work_queue()->Empty()); } TEST_P(SequenceManagerTest, DelayedTaskPosting) { @@ -1770,15 +1771,16 @@ // Move time forwards until just before the delayed task should run. AdvanceMockTickClock(TimeDelta::FromMilliseconds(10)); LazyNow lazy_now_1(mock_tick_clock()); - sequence_manager()->WakeUpReadyDelayedQueues(&lazy_now_1); + sequence_manager()->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1); EXPECT_FALSE(queue->HasTaskToRunImmediately()); // Force the delayed task onto the work queue. AdvanceMockTickClock(TimeDelta::FromMilliseconds(2)); LazyNow lazy_now_2(mock_tick_clock()); - sequence_manager()->WakeUpReadyDelayedQueues(&lazy_now_2); + sequence_manager()->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2); EXPECT_TRUE(queue->HasTaskToRunImmediately()); + sequence_manager()->ScheduleWork(); RunLoop().RunUntilIdle(); EXPECT_FALSE(queue->HasTaskToRunImmediately()); } @@ -4120,7 +4122,7 @@ TimeDelta::FromMilliseconds(10)); AdvanceMockTickClock(TimeDelta::FromMilliseconds(100)); LazyNow lazy_now(mock_tick_clock()); - sequence_manager()->WakeUpReadyDelayedQueues(&lazy_now); + sequence_manager()->MoveReadyDelayedTasksToWorkQueues(&lazy_now); EXPECT_THAT(tasks_alive, UnorderedElementsAre("Q1 I1 1", "Q1 D1 0", "Q2 D1 1", "Q3 I1 0",
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index 1b67160b..77bfc92 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -365,7 +365,9 @@ pending_task.delayed_run_time = time_domain_now; main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); LazyNow lazy_now(time_domain_now); - WakeUpForDelayedWork(&lazy_now); + MoveReadyDelayedTasksToWorkQueue(&lazy_now); + // if (IsQueueEnabled() || !main_thread_only().current_fence) + // sequence_manager_->ScheduleWork(); } else { // If |delayed_run_time| is in the future we can queue it as normal. PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), @@ -475,30 +477,26 @@ return wake_up->time; } -void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) { +void TaskQueueImpl::MoveReadyDelayedTasksToWorkQueue(LazyNow* lazy_now) { // Enqueue all delayed tasks that should be running now, skipping any that // have been canceled. + WorkQueue::TaskPusher delayed_work_queue_task_pusher( + main_thread_only().delayed_work_queue->CreateTaskPusher()); + while (!main_thread_only().delayed_incoming_queue.empty()) { - Task& task = - const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); - if (!task.task || task.task.IsCancelled()) { + Task* task = + const_cast<Task*>(&main_thread_only().delayed_incoming_queue.top()); + if (!task->task || task->task.IsCancelled()) { main_thread_only().delayed_incoming_queue.pop(); continue; } - if (task.delayed_run_time > lazy_now->Now()) + if (task->delayed_run_time > lazy_now->Now()) break; - ActivateDelayedFenceIfNeeded(task.delayed_run_time); - DCHECK(!task.enqueue_order_set()); - task.set_enqueue_order(sequence_manager_->GetNextSequenceNumber()); - main_thread_only().delayed_work_queue->Push(std::move(task)); + ActivateDelayedFenceIfNeeded(task->delayed_run_time); + DCHECK(!task->enqueue_order_set()); + task->set_enqueue_order(sequence_manager_->GetNextSequenceNumber()); + delayed_work_queue_task_pusher.Push(task); main_thread_only().delayed_incoming_queue.pop(); - - // Normally WakeUpForDelayedWork is called inside DoWork, but it also - // can be called elsewhere (e.g. tests and fast-path for posting - // delayed tasks). Ensure that there is a DoWork posting. No-op inside - // existing DoWork due to DoWork deduplication. - if (IsQueueEnabled() || !main_thread_only().current_fence) - sequence_manager_->ScheduleWork(); } UpdateDelayedWakeUp(lazy_now);
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h index 255f9df..c759083 100644 --- a/base/task/sequence_manager/task_queue_impl.h +++ b/base/task/sequence_manager/task_queue_impl.h
@@ -171,9 +171,8 @@ } // Enqueues any delayed tasks which should be run now on the - // |delayed_work_queue|. - // Must be called from the main thread. - void WakeUpForDelayedWork(LazyNow* lazy_now); + // |delayed_work_queue|. Must be called from the main thread. + void MoveReadyDelayedTasksToWorkQueue(LazyNow* lazy_now); base::internal::HeapHandle heap_handle() const { return main_thread_only().heap_handle;
diff --git a/base/task/sequence_manager/test/sequence_manager_for_test.h b/base/task/sequence_manager/test/sequence_manager_for_test.h index 82a6297b..16f1a43 100644 --- a/base/task/sequence_manager/test/sequence_manager_for_test.h +++ b/base/task/sequence_manager/test/sequence_manager_for_test.h
@@ -45,8 +45,8 @@ size_t QueuesToShutdownCount(); using internal::SequenceManagerImpl::GetNextSequenceNumber; + using internal::SequenceManagerImpl::MoveReadyDelayedTasksToWorkQueues; using internal::SequenceManagerImpl::ReloadEmptyWorkQueues; - using internal::SequenceManagerImpl::WakeUpReadyDelayedQueues; private: explicit SequenceManagerForTest(
diff --git a/base/task/sequence_manager/time_domain.cc b/base/task/sequence_manager/time_domain.cc index 1d81608..b34f32f 100644 --- a/base/task/sequence_manager/time_domain.cc +++ b/base/task/sequence_manager/time_domain.cc
@@ -121,7 +121,7 @@ } } -void TimeDomain::WakeUpReadyDelayedQueues(LazyNow* lazy_now) { +void TimeDomain::MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now) { DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); // Wake up any queues with pending delayed work. Note std::multimap stores // the elements sorted by key, so the begin() iterator points to the earliest @@ -129,7 +129,7 @@ while (!delayed_wake_up_queue_.empty() && delayed_wake_up_queue_.Min().wake_up.time <= lazy_now->Now()) { internal::TaskQueueImpl* queue = delayed_wake_up_queue_.Min().queue; - queue->WakeUpForDelayedWork(lazy_now); + queue->MoveReadyDelayedTasksToWorkQueue(lazy_now); } }
diff --git a/base/task/sequence_manager/time_domain.h b/base/task/sequence_manager/time_domain.h index 04cab726..4ffdf4d 100644 --- a/base/task/sequence_manager/time_domain.h +++ b/base/task/sequence_manager/time_domain.h
@@ -115,8 +115,9 @@ // Remove the TaskQueue from any internal data sctructures. void UnregisterQueue(internal::TaskQueueImpl* queue); - // Wake up each TaskQueue where the delay has elapsed. - void WakeUpReadyDelayedQueues(LazyNow* lazy_now); + // Wake up each TaskQueue where the delay has elapsed. Note this doesn't + // ScheduleWork. + void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now); struct ScheduledDelayedWakeUp { internal::DelayedWakeUp wake_up;
diff --git a/base/task/sequence_manager/time_domain_unittest.cc b/base/task/sequence_manager/time_domain_unittest.cc index e51be10..7a20bbd 100644 --- a/base/task/sequence_manager/time_domain_unittest.cc +++ b/base/task/sequence_manager/time_domain_unittest.cc
@@ -39,10 +39,10 @@ ~TestTimeDomain() override = default; + using TimeDomain::MoveReadyDelayedTasksToWorkQueues; using TimeDomain::NextScheduledRunTime; using TimeDomain::SetNextWakeUpForQueue; using TimeDomain::UnregisterQueue; - using TimeDomain::WakeUpReadyDelayedQueues; LazyNow CreateLazyNow() const override { return LazyNow(now_); } TimeTicks Now() const override { return now_; } @@ -234,7 +234,7 @@ EXPECT_TRUE(time_domain_->Empty()); } -TEST_F(TimeDomainTest, WakeUpReadyDelayedQueues) { +TEST_F(TimeDomainTest, MoveReadyDelayedTasksToWorkQueues) { TimeDelta delay = TimeDelta::FromMilliseconds(50); TimeTicks now = time_domain_->Now(); LazyNow lazy_now_1(now); @@ -245,17 +245,17 @@ EXPECT_EQ(delayed_runtime, time_domain_->NextScheduledRunTime()); - time_domain_->WakeUpReadyDelayedQueues(&lazy_now_1); + time_domain_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1); EXPECT_EQ(delayed_runtime, time_domain_->NextScheduledRunTime()); EXPECT_CALL(*time_domain_.get(), SetNextDelayedDoWork(_, TimeTicks::Max())); time_domain_->SetNow(delayed_runtime); LazyNow lazy_now_2(time_domain_->CreateLazyNow()); - time_domain_->WakeUpReadyDelayedQueues(&lazy_now_2); + time_domain_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2); ASSERT_FALSE(time_domain_->NextScheduledRunTime()); } -TEST_F(TimeDomainTest, WakeUpReadyDelayedQueuesWithIdenticalRuntimes) { +TEST_F(TimeDomainTest, MoveReadyDelayedTasksToWorkQueuesWithIdenticalRuntimes) { int sequence_num = 0; TimeDelta delay = TimeDelta::FromMilliseconds(50); TimeTicks now = time_domain_->Now(); @@ -273,7 +273,7 @@ task_queue_->SetDelayedWakeUpForTesting( internal::DelayedWakeUp{delayed_runtime, ++sequence_num}); - time_domain_->WakeUpReadyDelayedQueues(&lazy_now); + time_domain_->MoveReadyDelayedTasksToWorkQueues(&lazy_now); // The second task queue should wake up first since it has a lower sequence // number.
diff --git a/base/task/sequence_manager/work_queue.cc b/base/task/sequence_manager/work_queue.cc index 3cf0cb4..206c0f1 100644 --- a/base/task/sequence_manager/work_queue.cc +++ b/base/task/sequence_manager/work_queue.cc
@@ -70,7 +70,7 @@ // Make sure the |enqueue_order()| is monotonically increasing. DCHECK(was_empty || tasks_.back().enqueue_order() < task.enqueue_order()); - // Amoritized O(1). + // Amortized O(1). tasks_.push_back(std::move(task)); if (!was_empty) @@ -81,6 +81,42 @@ work_queue_sets_->OnTaskPushedToEmptyQueue(this); } +WorkQueue::TaskPusher::TaskPusher(WorkQueue* work_queue) + : work_queue_(work_queue), was_empty_(work_queue->Empty()) {} + +WorkQueue::TaskPusher::TaskPusher(TaskPusher&& other) + : work_queue_(other.work_queue_), was_empty_(other.was_empty_) { + other.work_queue_ = nullptr; +} + +void WorkQueue::TaskPusher::Push(Task* task) { + DCHECK(work_queue_); + +#ifndef NDEBUG + DCHECK(task->enqueue_order_set()); +#endif + + // Make sure the |enqueue_order()| is monotonically increasing. + DCHECK(work_queue_->tasks_.empty() || + work_queue_->tasks_.back().enqueue_order() < task->enqueue_order()); + + // Amortized O(1). + work_queue_->tasks_.push_back(std::move(*task)); +} + +WorkQueue::TaskPusher::~TaskPusher() { + // If |work_queue_| became non empty and it isn't blocked by a fence then we + // must notify |work_queue_->work_queue_sets_|. + if (was_empty_ && work_queue_ && !work_queue_->Empty() && + work_queue_->work_queue_sets_ && !work_queue_->BlockedByFence()) { + work_queue_->work_queue_sets_->OnTaskPushedToEmptyQueue(work_queue_); + } +} + +WorkQueue::TaskPusher WorkQueue::CreateTaskPusher() { + return TaskPusher(this); +} + void WorkQueue::PushNonNestableTaskToFront(Task task) { DCHECK(task.nestable == Nestable::kNonNestable); @@ -97,7 +133,7 @@ << " : " << name_; } - // Amoritized O(1). + // Amortized O(1). tasks_.push_front(std::move(task)); if (!work_queue_sets_)
diff --git a/base/task/sequence_manager/work_queue.h b/base/task/sequence_manager/work_queue.h index fd80f32b..469be50 100644 --- a/base/task/sequence_manager/work_queue.h +++ b/base/task/sequence_manager/work_queue.h
@@ -65,6 +65,27 @@ // it informs the WorkQueueSets if the head changed. void Push(Task task); + // RAII helper that helps efficiently push N Tasks to a WorkQueue. + class BASE_EXPORT TaskPusher { + public: + TaskPusher(const TaskPusher&) = delete; + TaskPusher(TaskPusher&& other); + ~TaskPusher(); + + void Push(Task* task); + + private: + friend class WorkQueue; + + explicit TaskPusher(WorkQueue* work_queue); + + WorkQueue* work_queue_; + const bool was_empty_; + }; + + // Returns an RAII helper to efficiently push multiple tasks. + TaskPusher CreateTaskPusher(); + // Pushes the task onto the front of the |tasks_| and if it's before any // fence it informs the WorkQueueSets the head changed. Use with caution this // API can easily lead to task starvation if misused.
diff --git a/base/task/sequence_manager/work_queue_unittest.cc b/base/task/sequence_manager/work_queue_unittest.cc index d4b4571..51e6d2a8 100644 --- a/base/task/sequence_manager/work_queue_unittest.cc +++ b/base/task/sequence_manager/work_queue_unittest.cc
@@ -158,6 +158,17 @@ EXPECT_EQ(work_queue_.get(), work_queue_sets_->GetOldestQueueInSet(0)); } +TEST_F(WorkQueueTest, PushMultiple) { + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); + + work_queue_->Push(FakeTaskWithEnqueueOrder(2)); + work_queue_->Push(FakeTaskWithEnqueueOrder(3)); + work_queue_->Push(FakeTaskWithEnqueueOrder(4)); + EXPECT_EQ(work_queue_.get(), work_queue_sets_->GetOldestQueueInSet(0)); + EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); + EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); +} + TEST_F(WorkQueueTest, PushAfterFenceHit) { work_queue_->InsertFence(EnqueueOrder::blocking_fence()); EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); @@ -166,6 +177,53 @@ EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); } +TEST_F(WorkQueueTest, CreateTaskPusherNothingPushed) { + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); + { WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); } + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); +} + +TEST_F(WorkQueueTest, CreateTaskPusherOneTask) { + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); + { + WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); + Task task = FakeTaskWithEnqueueOrder(2); + task_pusher.Push(&task); + } + EXPECT_EQ(work_queue_.get(), work_queue_sets_->GetOldestQueueInSet(0)); +} + +TEST_F(WorkQueueTest, CreateTaskPusherThreeTasks) { + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); + { + WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); + Task task1 = FakeTaskWithEnqueueOrder(2); + Task task2 = FakeTaskWithEnqueueOrder(3); + Task task3 = FakeTaskWithEnqueueOrder(4); + task_pusher.Push(&task1); + task_pusher.Push(&task2); + task_pusher.Push(&task3); + } + EXPECT_EQ(work_queue_.get(), work_queue_sets_->GetOldestQueueInSet(0)); + EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); + EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); +} + +TEST_F(WorkQueueTest, CreateTaskPusherAfterFenceHit) { + work_queue_->InsertFence(EnqueueOrder::blocking_fence()); + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); + { + WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); + Task task1 = FakeTaskWithEnqueueOrder(2); + Task task2 = FakeTaskWithEnqueueOrder(3); + Task task3 = FakeTaskWithEnqueueOrder(4); + task_pusher.Push(&task1); + task_pusher.Push(&task2); + task_pusher.Push(&task3); + } + EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0)); +} + TEST_F(WorkQueueTest, PushNonNestableTaskToFront) { EXPECT_EQ(nullptr, work_queue_sets_->GetOldestQueueInSet(0));
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index a041c55..ccecde3 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -367,12 +367,8 @@ // Bind the new test subdirectory to /data in the child process' namespace. new_options.paths_to_transfer.push_back( - {kDataPath, base::fuchsia::GetHandleFromFile( - base::File(nested_data_path, - base::File::FLAG_OPEN | base::File::FLAG_READ | - base::File::FLAG_DELETE_ON_CLOSE)) - .release()}); - + {kDataPath, + base::fuchsia::OpenDirectory(nested_data_path).TakeChannel().release()}); #endif // defined(OS_FUCHSIA) #if defined(OS_LINUX) @@ -452,9 +448,8 @@ zx_status_t status = job_handle.kill(); ZX_CHECK(status == ZX_OK, status); - // The child process' data dir should have been deleted automatically, - // thanks to the DELETE_ON_CLOSE flag. - DCHECK(!base::DirectoryExists(nested_data_path)); + // Cleanup the data directory. + CHECK(DeleteFile(nested_data_path, true)); #elif defined(OS_POSIX) if (exit_code != 0) { // On POSIX, in case the test does not exit cleanly, either due to a crash
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 0afd629..1ef3795 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -1fdc2abd281892f5d2c914bb83b6bae6108619c6 \ No newline at end of file +ddcb12bc41acc7d54223765e22f78a305954bcbc \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 1249cc9..077fa9d8 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -d5208460c502e92a7c0c718f986b482617ec1c90 \ No newline at end of file +bf01df1020cecebcf7bcc39fdd72c783bb14a923 \ No newline at end of file
diff --git a/buildtools/DEPS b/buildtools/DEPS index a56d460..89fab254 100644 --- a/buildtools/DEPS +++ b/buildtools/DEPS
@@ -3,6 +3,16 @@ vars = { 'chromium_url': 'https://chromium.googlesource.com', + # + # TODO(crbug.com/941824): These revisions need to be kept in sync + # between //DEPS and //buildtools/DEPS, so if you're updating one, + # update the other. There is a presubmit check that checks that + # you've done so; if you are adding new tools to //buildtools and + # hence new revisions to this list, make sure you update the + # _CheckBuildtoolsRevsAreInSync in PRESUBMIT.py to include the additional + # revisions. + # + # When changing these, also update the svn revisions in deps_revisions.gni 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'libcxx_revision': 'a50f5035629b7621e92acef968403f71b7d48553',
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc index 5a467fb..7244679 100644 --- a/cc/paint/display_item_list.cc +++ b/cc/paint/display_item_list.cc
@@ -153,7 +153,10 @@ for (const PaintOp* op : PaintOpBuffer::Iterator(&paint_op_buffer_)) { state->BeginDictionary(); state->SetString("name", PaintOpTypeToString(op->GetType())); - MathUtil::AddToTracedValue("visual_rect", bounds[i++], state.get()); + + // rtree_ generation drops empty rects + if (i < bounds.size()) + MathUtil::AddToTracedValue("visual_rect", bounds[i++], state.get()); SkPictureRecorder recorder; SkCanvas* canvas =
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h index 1eb89208..50f3e9e 100644 --- a/cc/paint/display_item_list.h +++ b/cc/paint/display_item_list.h
@@ -198,6 +198,7 @@ int max_ops_to_analyze = 1); private: + FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, TraceEmptyVisualRect); FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithNoOps); FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithOps); friend gpu::raster::RasterImplementation;
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc index 0abe50d53..e76d52b 100644 --- a/cc/paint/display_item_list_unittest.cc +++ b/cc/paint/display_item_list_unittest.cc
@@ -77,6 +77,31 @@ EXPECT_EQ(height, d); \ } while (false) +// CreateTracedValue should not crash if there are different numbers of +// visual_rect are paint_op +TEST(DisplayItemListTest, TraceEmptyVisualRect) { + // |layer_rect| is empty to cause rtree generation to skip it. + gfx::Rect layer_rect(0, 10); + PaintFlags red_paint; + red_paint.setColor(SK_ColorRED); + auto list = base::MakeRefCounted<DisplayItemList>(); + + gfx::Point offset(8, 9); + + list->StartPaint(); + list->push<SaveOp>(); + list->push<TranslateOp>(static_cast<float>(offset.x()), + static_cast<float>(offset.y())); + list->push<DrawRectOp>(SkRect::MakeLTRB(0.f, 0.f, 60.f, 60.f), red_paint); + list->push<RestoreOp>(); + list->EndPaintOfUnpaired(gfx::Rect(offset, layer_rect.size())); + list->Finalize(); + + // Pass: we don't crash + std::unique_ptr<base::Value> root = + list->CreateTracedValue(true)->ToBaseValue(); +} + TEST(DisplayItemListTest, SingleUnpairedRange) { gfx::Rect layer_rect(100, 100); PaintFlags blue_flags;
diff --git a/chrome/android/java/res/layout/bookmark_widget.xml b/chrome/android/java/res/layout/bookmark_widget.xml index 61af800..a0e17dfa 100644 --- a/chrome/android/java/res/layout/bookmark_widget.xml +++ b/chrome/android/java/res/layout/bookmark_widget.xml
@@ -7,7 +7,7 @@ android:id="@+id/bookmarks_list" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#ddffffff" + android:background="@color/bookmark_widget_background" android:divider="@null" android:drawSelectorOnTop="true" android:listSelector="@drawable/bookmark_widget_list_selector" />
diff --git a/chrome/android/java/res/layout/bookmark_widget_item.xml b/chrome/android/java/res/layout/bookmark_widget_item.xml index 2f80d4b..ecbe33b 100644 --- a/chrome/android/java/res/layout/bookmark_widget_item.xml +++ b/chrome/android/java/res/layout/bookmark_widget_item.xml
@@ -28,7 +28,6 @@ android:paddingEnd="16dp" android:singleLine="true" android:textAlignment="viewStart" - android:textColor="@color/default_text_color" - android:textSize="16sp" /> + android:textAppearance="@style/TextAppearance.BookmarkWidgetItemText" /> </LinearLayout>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index 892601f..76d28d9e 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -730,6 +730,10 @@ parent="@style/TextAppearance.AppCompat.Medium"> <item name="android:textColor">@color/standard_mode_tint</item> </style> + <style name="TextAppearance.BookmarkWidgetItemText" + parent="@style/TextAppearance.BlackTitle1"> + <item name="android:textColor">@color/default_text_color_dark</item> + </style> <!-- Download Home --> <style name="DateView">
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index fea2b31..a13f8f1 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -181,6 +181,7 @@ <!-- Bookmark widget colors --> <color name="bookmark_widget_pressed_highlight">@color/black_alpha_11</color> + <color name="bookmark_widget_background">#DDFFFFFF</color> <!-- Payments UI colors --> <color name="payments_section_edit_background">@color/modern_secondary_color</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java index bfe6add..ac0afc3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
@@ -11,6 +11,10 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.CommandLine; +import org.chromium.base.task.PostTask; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabBuilder; import org.chromium.chrome.browser.tab.TabDelegateFactory; @@ -20,6 +24,7 @@ import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.UiThreadTaskTraits; /** * Base class for task-focused activities that need to display a single tab. @@ -28,6 +33,8 @@ * activities - anything where maintaining multiple tabs is unnecessary. */ public abstract class SingleTabActivity extends ChromeActivity { + private static final int PREWARM_RENDERER_DELAY_MS = 500; + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -138,4 +145,31 @@ @Override public void onUpdateStateChanged() {} + + @Override + public void onStopWithNative() { + super.onStopWithNative(); + if (CommandLine.getInstance().hasSwitch(ChromeSwitches.AGGRESSIVELY_PREWARM_RENDERERS)) { + PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, new Runnable() { + @Override + public void run() { + // If we're not still stopped, we don't need the spare WebContents. + if (ApplicationStatus.getStateForActivity(SingleTabActivity.this) + == ActivityState.STOPPED) { + WarmupManager.getInstance().createSpareWebContents(!WarmupManager.FOR_CCT); + } + } + }, PREWARM_RENDERER_DELAY_MS); + } + } + + @Override + public void onTrimMemory(int level) { + super.onTrimMemory(level); + if (CommandLine.getInstance().hasSwitch(ChromeSwitches.AGGRESSIVELY_PREWARM_RENDERERS)) { + if (ChromeApplication.isSevereMemorySignal(level)) { + WarmupManager.getInstance().destroySpareWebContents(); + } + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java index 15684aa..185b31b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -19,7 +19,6 @@ import org.chromium.base.Log; import org.chromium.base.StrictModeContext; -import org.chromium.base.SysUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; @@ -53,11 +52,13 @@ private static final String TAG = "WarmupManager"; @VisibleForTesting - static final String WEBCONTENTS_STATUS_HISTOGRAM = "CustomTabs.SpareWebContents.Status"; + static final String WEBCONTENTS_STATUS_HISTOGRAM = "CustomTabs.SpareWebContents.Status2"; + + public static final boolean FOR_CCT = true; // See CustomTabs.SpareWebContentsStatus histogram. Append-only. @IntDef({WebContentsStatus.CREATED, WebContentsStatus.USED, WebContentsStatus.KILLED, - WebContentsStatus.DESTROYED}) + WebContentsStatus.DESTROYED, WebContentsStatus.STOLEN}) @Retention(RetentionPolicy.SOURCE) @interface WebContentsStatus { @VisibleForTesting @@ -68,7 +69,9 @@ int KILLED = 2; @VisibleForTesting int DESTROYED = 3; - int NUM_ENTRIES = 4; + @VisibleForTesting + int STOLEN = 4; + int NUM_ENTRIES = 5; } /** @@ -83,7 +86,7 @@ recordWebContentsStatus(WebContentsStatus.KILLED); destroySpareWebContentsInternal(); } - }; + } @SuppressLint("StaticFieldLeak") private static WarmupManager sWarmupManager; @@ -97,6 +100,7 @@ WebContents mSpareWebContents; private long mWebContentsCreationTimeMs; private RenderProcessGoneObserver mObserver; + private boolean mWebContentsCreatedForCCT; /** * @return The singleton instance for the WarmupManager, creating one if necessary. @@ -326,14 +330,14 @@ * * This creates a renderer that is suitable for any navigation. It can be picked up by any tab. * Can be called multiple times, and must be called from the UI thread. - * Note that this is a no-op on low-end devices. + * + * @param forCCT Whether this WebContents is being created for CCT. */ - public void createSpareWebContents() { + public void createSpareWebContents(boolean forCCT) { ThreadUtils.assertOnUiThread(); - if (!LibraryLoader.getInstance().isInitialized() || mSpareWebContents != null - || SysUtils.isLowEndDevice()) { - return; - } + if (!LibraryLoader.getInstance().isInitialized() || mSpareWebContents != null) return; + + mWebContentsCreatedForCCT = forCCT; mSpareWebContents = new WebContentsFactory().createWebContentsWithWarmRenderer( false /* incognito */, true /* initiallyHidden */); mObserver = new RenderProcessGoneObserver(); @@ -356,10 +360,12 @@ * Returns a spare WebContents or null, depending on the availability of one. * * The parameters are the same as for {@link WebContentsFactory#createWebContents()}. + * @param forCCT Whether this WebContents is being taken by CCT. * * @return a WebContents, or null. */ - public WebContents takeSpareWebContents(boolean incognito, boolean initiallyHidden) { + public WebContents takeSpareWebContents( + boolean incognito, boolean initiallyHidden, boolean forCCT) { ThreadUtils.assertOnUiThread(); if (incognito) return null; WebContents result = mSpareWebContents; @@ -368,7 +374,8 @@ result.removeObserver(mObserver); mObserver = null; if (!initiallyHidden) result.onShow(); - recordWebContentsStatus(WebContentsStatus.USED); + recordWebContentsStatus(mWebContentsCreatedForCCT == forCCT ? WebContentsStatus.USED + : WebContentsStatus.STOLEN); return result; } @@ -386,7 +393,8 @@ mObserver = null; } - private static void recordWebContentsStatus(@WebContentsStatus int status) { + private void recordWebContentsStatus(@WebContentsStatus int status) { + if (!mWebContentsCreatedForCCT) return; RecordHistogram.recordEnumeratedHistogram( WEBCONTENTS_STATUS_HISTOGRAM, status, WebContentsStatus.NUM_ENTRIES); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java index dbd32c45e..9eddd72 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java
@@ -20,8 +20,6 @@ import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyModel; -import java.util.Calendar; - /** * Prompt that asks users to confirm the expiration date before saving card to Google. * TODO(crbug.com/848955) @@ -135,11 +133,8 @@ if (buttonType == ModalDialogProperties.ButtonType.POSITIVE) { String monthString = mMonthInput.getText().toString().trim(); String yearString = mYearInput.getText().toString().trim(); - if (isValidExpirationDate(monthString, yearString)) { - mDelegate.onUserAccept(monthString, yearString); - mModalDialogManager.dismissDialog( - model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED); - } + mDelegate.onUserAccept(monthString, yearString); + mModalDialogManager.dismissDialog(model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED); } else if (buttonType == ModalDialogProperties.ButtonType.NEGATIVE) { mModalDialogManager.dismissDialog(model, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED); } @@ -150,36 +145,6 @@ mDelegate.onPromptDismissed(); } - private boolean isValidExpirationDate(String monthString, String yearString) { - if (monthString.isEmpty() || yearString.isEmpty()) { - return false; - } - - Calendar calendar = Calendar.getInstance(); - int currentMonth = calendar.get(Calendar.MONTH); - int currentYear = calendar.get(Calendar.YEAR) % 100; - int year, month; - try { - year = Integer.valueOf(yearString.trim()); - month = Integer.valueOf(monthString.trim()); - } catch (NumberFormatException e) { - return false; - } - - if (month <= 0 || month > 12) { - return false; - } - - if (year < currentYear) { - return false; - } - - if (year == currentYear) { - return month >= currentMonth; - } - return true; - } - /** * Validates the values of the input fields to determine whether the submit button should be * enabled. Also displays a detailed error message and highlights the fields for which the value
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java index 0adacd5..4f80741 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java
@@ -288,7 +288,7 @@ mWidgetId = widgetId; mPreferences = getWidgetState(mContext, mWidgetId); mIconColor = ApiCompatibilityUtils.getColor( - mContext.getResources(), R.color.default_icon_color); + mContext.getResources(), R.color.default_icon_color_dark); } @UiThread
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java index 52f6baf5..742c07d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
@@ -6,10 +6,12 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.content.Context; import android.content.res.Resources; import android.graphics.RectF; import android.support.annotation.IntDef; +import android.util.Pair; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Interpolator; @@ -17,6 +19,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; +import org.chromium.chrome.browser.compositor.animation.FloatProperty; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation; @@ -32,6 +35,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Iterator; /** * Handles all the drawing and events of a stack of stackTabs. @@ -222,6 +227,7 @@ // Running set of animations applied to tabs. private ChromeAnimation<?> mTabAnimations; + private Pair<AnimatorSet, ArrayList<FloatProperty>> mAnimatorSetTabAnimations; private Animator mViewAnimations; // The parent Layout @@ -548,17 +554,23 @@ // Build the AnimatorSet using the TabSwitcherAnimationFactory. // This will give us the appropriate AnimatorSet based on the current // state of the tab switcher and the OverviewAnimationType specified. - mTabAnimations = mAnimationFactory.createAnimatorSetForType(type, this, mStackTabs, - focusIndex, sourceIndex, mSpacing, getDiscardRange()); + mTabAnimations = mAnimationFactory.createChromeAnimationSetForType(type, this, + mStackTabs, focusIndex, sourceIndex, mSpacing, getDiscardRange()); + mAnimatorSetTabAnimations = mAnimationFactory.createAnimatorSetForType(type, this, + mStackTabs, focusIndex, sourceIndex, mSpacing, getDiscardRange()); } if (mTabAnimations != null) mTabAnimations.start(); + if (mAnimatorSetTabAnimations != null) mAnimatorSetTabAnimations.first.start(); if (mViewAnimations != null) mViewAnimations.start(); - if (mTabAnimations != null || mViewAnimations != null) { + if (mTabAnimations != null || mAnimatorSetTabAnimations != null + || mViewAnimations != null) { mLayout.onStackAnimationStarted(); } - if ((mTabAnimations == null && mViewAnimations == null) || finishImmediately) { + if ((mTabAnimations == null && mAnimatorSetTabAnimations == null + && mViewAnimations == null) + || finishImmediately) { finishAnimation(time); } } @@ -573,8 +585,12 @@ */ protected void finishAnimation(long time) { if (mTabAnimations != null) mTabAnimations.updateAndFinish(); + if (mAnimatorSetTabAnimations != null) mAnimatorSetTabAnimations.first.end(); if (mViewAnimations != null) mViewAnimations.end(); - if (mTabAnimations != null || mViewAnimations != null) mLayout.onStackAnimationFinished(); + if (mTabAnimations != null || mAnimatorSetTabAnimations != null + || mViewAnimations != null) { + mLayout.onStackAnimationFinished(); + } switch (mOverviewAnimationType) { case OverviewAnimationType.ENTER_STACK: @@ -628,6 +644,7 @@ mOverviewAnimationType = OverviewAnimationType.NONE; mTabAnimations = null; + mAnimatorSetTabAnimations = null; mViewAnimations = null; } @@ -692,8 +709,8 @@ || mOverviewAnimationType == OverviewAnimationType.UNDISCARD || mOverviewAnimationType == OverviewAnimationType.DISCARD_ALL) && (type == OverviewAnimationType.DISCARD - || type == OverviewAnimationType.UNDISCARD - || type == OverviewAnimationType.DISCARD_ALL)) { + || type == OverviewAnimationType.UNDISCARD + || type == OverviewAnimationType.DISCARD_ALL)) { return true; } } @@ -709,6 +726,17 @@ || mOverviewAnimationType == OverviewAnimationType.UNDISCARD || mOverviewAnimationType == OverviewAnimationType.DISCARD_ALL) { mTabAnimations.cancel(null, StackTab.Property.SCROLL_OFFSET); + if (mAnimatorSetTabAnimations != null) { + Iterator<FloatProperty> propertyIterator = + mAnimatorSetTabAnimations.second.iterator(); + Iterator<Animator> animatorIterator = + mAnimatorSetTabAnimations.first.getChildAnimations().iterator(); + + while (animatorIterator.hasNext()) { + CompositorAnimator a = (CompositorAnimator) animatorIterator.next(); + if (propertyIterator.next() == StackTab.SCROLL_OFFSET) a.cancel(); + } + } return true; } return false; @@ -738,30 +766,44 @@ public boolean onUpdateCompositorAnimations(long time, boolean jumpToEnd) { if (!jumpToEnd) updateScrollOffset(time); - boolean finished = true; + boolean chromeAnimationsFinished = true; if (mTabAnimations != null) { - if (jumpToEnd) { - finished = mTabAnimations.finished(); - } else { - finished = mTabAnimations.update(time); - } - finishAnimationsIfDone(time, jumpToEnd); + chromeAnimationsFinished = + jumpToEnd ? mTabAnimations.finished() : mTabAnimations.update(time); } + boolean animatorSetFinished = true; + if (mAnimatorSetTabAnimations != null) { + animatorSetFinished = jumpToEnd ? true : !mAnimatorSetTabAnimations.first.isRunning(); + } + + if (mTabAnimations != null || mAnimatorSetTabAnimations != null) { + finishAnimationsIfDone(time, jumpToEnd); + } if (jumpToEnd) forceScrollStop(); - return finished; + + return chromeAnimationsFinished && animatorSetFinished; } private void finishAnimationsIfDone(long time, boolean jumpToEnd) { boolean hasViewAnimations = mViewAnimations != null; - boolean hasTabAnimations = mTabAnimations != null; - boolean hasAnimations = hasViewAnimations || hasTabAnimations; boolean isViewFinished = hasViewAnimations ? !mViewAnimations.isRunning() : true; + + boolean hasTabAnimations = mTabAnimations != null; boolean isTabFinished = hasTabAnimations ? mTabAnimations.finished() : true; + boolean hasAnimatorSetTabAnimations = mAnimatorSetTabAnimations != null; + boolean isAnimatorSetTabFinished = + hasAnimatorSetTabAnimations ? !mAnimatorSetTabAnimations.first.isRunning() : true; + + boolean hasAnimations = + hasViewAnimations || hasTabAnimations || hasAnimatorSetTabAnimations; + boolean shouldFinish = jumpToEnd && hasAnimations; shouldFinish |= hasAnimations && (!hasViewAnimations || isViewFinished) - && (!hasTabAnimations || isTabFinished); + && (!hasTabAnimations || isTabFinished) + && (!hasAnimatorSetTabAnimations || isAnimatorSetTabFinished); + if (shouldFinish) finishAnimation(time); } @@ -853,9 +895,9 @@ private void discard(float x, float y, float amountX, float amountY) { if (mStackTabs == null || (mOverviewAnimationType != OverviewAnimationType.NONE - && mOverviewAnimationType != OverviewAnimationType.DISCARD - && mOverviewAnimationType != OverviewAnimationType.DISCARD_ALL - && mOverviewAnimationType != OverviewAnimationType.UNDISCARD)) { + && mOverviewAnimationType != OverviewAnimationType.DISCARD + && mOverviewAnimationType != OverviewAnimationType.DISCARD_ALL + && mOverviewAnimationType != OverviewAnimationType.UNDISCARD)) { return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java index 36f389db..0f583bd4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
@@ -6,11 +6,14 @@ import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.AnimatableAnimation.addAnimation; +import android.animation.AnimatorSet; import android.support.annotation.IntDef; +import android.util.Pair; import android.view.animation.Interpolator; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; +import org.chromium.chrome.browser.compositor.animation.FloatProperty; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation; @@ -19,6 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; /** * A factory that builds animations for the tab stack. @@ -165,8 +169,9 @@ * @param discardRange The range of the discard amount value. * @return The resulting TabSwitcherAnimation that will animate the tabs. */ - public ChromeAnimation<?> createAnimatorSetForType(@OverviewAnimationType int type, Stack stack, - StackTab[] tabs, int focusIndex, int sourceIndex, int spacing, float discardRange) { + public ChromeAnimation<?> createChromeAnimationSetForType(@OverviewAnimationType int type, + Stack stack, StackTab[] tabs, int focusIndex, int sourceIndex, int spacing, + float discardRange) { if (tabs == null) return null; switch (type) { case OverviewAnimationType.ENTER_STACK: @@ -194,6 +199,27 @@ } } + /** + * The wrapper method responsible for delegating the animations request to the appropriate + * helper method. Not all parameters are used for each request. + * + * @param type The type of animation to be created. This is what + * determines which helper method is called. + * @param stack The current stack. + * @param tabs The tabs that make up the current stack that will + * be animated. + * @param focusIndex The index of the tab that is the focus of this animation. + * @param sourceIndex The index of the tab that triggered this animation. + * @param spacing The default spacing between the tabs. + * @param discardRange The range of the discard amount value. + * @return The resulting TabSwitcherAnimation that will animate the tabs. + */ + public Pair<AnimatorSet, ArrayList<FloatProperty>> createAnimatorSetForType( + @OverviewAnimationType int type, Stack stack, StackTab[] tabs, int focusIndex, + int sourceIndex, int spacing, float discardRange) { + return null; + } + protected abstract float getScreenSizeInScrollDirection(); protected abstract float getScreenPositionInScrollDirection(StackTab tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 95dc3416..e1da8afd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -53,7 +53,6 @@ import org.chromium.chrome.browser.IntentHandler.ExternalAppId; import org.chromium.chrome.browser.KeyboardShortcuts; import org.chromium.chrome.browser.LaunchIntentDispatcher; -import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantFacade; import org.chromium.chrome.browser.browserservices.BrowserSessionContentHandler; @@ -731,7 +730,7 @@ // of users open several Custom Tabs in a row. The delay is there to avoid jank in the // transition animation when closing the tab. PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, - () -> WarmupManager.getInstance().createSpareWebContents(), 500); + () -> CustomTabsConnection.createSpareWebContents(), 500); } handleFinishAndClose();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 55d5d1ce..35ce0e0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -35,6 +35,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.StrictModeContext; +import org.chromium.base.SysUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.TimeUtils; import org.chromium.base.TraceEvent; @@ -429,7 +430,7 @@ return; } try (TraceEvent e = TraceEvent.scoped("CreateSpareWebContents")) { - WarmupManager.getInstance().createSpareWebContents(); + createSpareWebContents(); } }); } @@ -448,7 +449,7 @@ try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) { // (4) Profile profile = Profile.getLastUsedProfile(); - WarmupManager.getInstance().startPreconnectPredictorInitialization(profile); + WarmupManager.startPreconnectPredictorInitialization(profile); // (5) // The throttling database uses shared preferences, that can cause a @@ -508,7 +509,7 @@ boolean lowConfidenceMayLaunchUrl(List<Bundle> likelyBundles) { ThreadUtils.assertOnUiThread(); if (!preconnectUrls(likelyBundles)) return false; - WarmupManager.getInstance().createSpareWebContents(); + createSpareWebContents(); return true; } @@ -1376,7 +1377,7 @@ recordSpeculationStatusOnStart(SPECULATION_STATUS_ON_START_BACKGROUND_TAB); launchUrlInHiddenTab(session, url, extras); } else { - warmupManager.createSpareWebContents(); + createSpareWebContents(); } warmupManager.maybePreconnectUrlAndSubResources(profile, url); } @@ -1497,4 +1498,9 @@ @Nullable HiddenTabHolder.SpeculationParams getSpeculationParamsForTesting() { return mHiddenTabHolder.getSpeculationParamsForTesting(); } + + /* package */ static void createSpareWebContents() { + if (SysUtils.isLowEndDevice()) return; + WarmupManager.getInstance().createSpareWebContents(WarmupManager.FOR_CCT); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java index a875245..aa3a10a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -424,7 +424,7 @@ webContents.resumeLoadingCreatedWebContents(); } else { webContents = mWarmupManager.takeSpareWebContents(mIntentDataProvider.isIncognito(), - false /*initiallyHidden*/); + false /*initiallyHidden*/, WarmupManager.FOR_CCT); if (webContents != null) { webContentsStateOnLaunch = WebContentsState.SPARE_WEBCONTENTS; } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java index 8952325..35f45b51 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -346,11 +346,9 @@ if (params.getUrl().startsWith(WTAI_MC_URL_PREFIX)) { // wtai://wp/mc;number // number=string(phone-number) - Intent wtaiIntent = new Intent(Intent.ACTION_VIEW, + mDelegate.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(WebView.SCHEME_TEL - + params.getUrl().substring(WTAI_MC_URL_PREFIX.length()))); - wtaiIntent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); - mDelegate.startActivity(wtaiIntent, false); + + params.getUrl().substring(WTAI_MC_URL_PREFIX.length()))), false); if (DEBUG) Log.i(TAG, "OVERRIDE_WITH_EXTERNAL_INTENT wtai:// link handled"); RecordUserAction.record("Android.PhoneIntent"); return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT; @@ -405,9 +403,6 @@ // Sanitize the Intent, ensuring web pages can not bypass browser // security (only access to BROWSABLE activities). intent.addCategory(Intent.CATEGORY_BROWSABLE); - // Do not target packages that have not been launched directly by the - // user at least once. - intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); intent.setComponent(null); Intent selector = intent.getSelector(); if (selector != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java index af7db4d..e5e4886 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
@@ -32,6 +32,7 @@ import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; +import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.display.DisplayAndroid; import org.chromium.ui.display.DisplayUtil; @@ -44,7 +45,8 @@ * When initiated from native code, special code is needed to keep the Java and native infobar in * sync, see NativeInfoBar. */ -public class InfoBarContainer extends SwipableOverlayView implements UserData { +public class InfoBarContainer + extends SwipableOverlayView implements UserData, KeyboardVisibilityListener { private static final String TAG = "InfoBarContainer"; private static final Class<InfoBarContainer> USER_DATA_KEY = InfoBarContainer.class; @@ -248,8 +250,7 @@ mLayout.addAnimationListener(mIPHSupport); addObserver(mIPHSupport); - mTab.getWindowAndroid().getKeyboardDelegate().addKeyboardVisibilityListener( - this::updateVisibilityForKeyboard); + mTab.getWindowAndroid().getKeyboardDelegate().addKeyboardVisibilityListener(this); // Chromium's InfoBarContainer may add an InfoBar immediately during this initialization // call, so make sure everything in the InfoBarContainer is completely ready beforehand. @@ -426,6 +427,10 @@ if (activity != null && mBottomSheetObserver != null && activity.getBottomSheet() != null) { activity.getBottomSheet().removeObserver(mBottomSheetObserver); } + WindowAndroid windowAndroid = mTab.getWindowAndroid(); + if (windowAndroid != null) { + windowAndroid.getKeyboardDelegate().removeKeyboardVisibilityListener(this); + } mLayout.removeAnimationListener(mIPHSupport); removeObserver(mIPHSupport); mDestroyed = true; @@ -517,7 +522,8 @@ } } - private void updateVisibilityForKeyboard(boolean isKeyboardShowing) { + @Override + public void keyboardVisibilityChanged(boolean isKeyboardShowing) { boolean isShowing = (getVisibility() == View.VISIBLE); if (isKeyboardShowing) { if (isShowing) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java index 2c5f3ec5..5cd45ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -157,7 +157,9 @@ /** Controls the parameter of {@link NativeInitializationController#startBackgroundTasks}.*/ @VisibleForTesting public boolean shouldAllocateChildConnection() { - return true; + // If a spare WebContents exists, a child connection has already been allocated that will be + // used by the next created tab. + return !WarmupManager.getInstance().hasSpareWebContents(); } @CallSuper
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 41d7b40..ae67a091 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -973,7 +973,7 @@ boolean creatingWebContents = webContents == null; if (creatingWebContents) { webContents = WarmupManager.getInstance().takeSpareWebContents( - isIncognito(), initiallyHidden); + isIncognito(), initiallyHidden, isCurrentlyACustomTab()); if (webContents == null) { webContents = WebContentsFactory.createWebContents(isIncognito(), initiallyHidden); @@ -1541,7 +1541,12 @@ if (mPendingLoadParams != null) { assert isFrozen(); - initWebContents(WebContentsFactory.createWebContents(isIncognito(), isHidden())); + WebContents webContents = WarmupManager.getInstance().takeSpareWebContents( + isIncognito(), isHidden(), isCurrentlyACustomTab()); + if (webContents == null) { + webContents = WebContentsFactory.createWebContents(isIncognito(), isHidden()); + } + initWebContents(webContents); loadUrl(mPendingLoadParams); mPendingLoadParams = null; return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java index 583f60a0..d7660f1c8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
@@ -7,6 +7,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.snackbar.Snackbar; import org.chromium.chrome.browser.snackbar.SnackbarManager; +import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.webapk.lib.common.WebApkConstants; /** @@ -72,6 +73,11 @@ return false; } + // This UI isn't great for no-touch and will be handled a different way. + if (FeatureUtilities.isNoTouchModeEnabled()) { + return false; + } + // This will be null for Webapps or bound WebAPKs. String packageName = activity.getWebApkPackageName(); // Show for unbound WebAPKs.
diff --git a/chrome/android/java_templates/ChromeSwitches.java.tmpl b/chrome/android/java_templates/ChromeSwitches.java.tmpl index 0fa50fbf..436000a 100644 --- a/chrome/android/java_templates/ChromeSwitches.java.tmpl +++ b/chrome/android/java_templates/ChromeSwitches.java.tmpl
@@ -77,6 +77,12 @@ */ public static final String DISABLE_TAB_MERGING_FOR_TESTING = "disable-tab-merging"; + /** + * Aggressively pre-warms renderers when Chrome is backgrounded. Currently only works for + * SingleTabActivity-derived Activities. + */ + public static final String AGGRESSIVELY_PREWARM_RENDERERS = "aggressively-prewarm-renderers"; + /////////////////////////////////////////////////////////////////////////////////////////////// // Native Switches ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index 11af81e..b4fb256 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -915,7 +915,6 @@ } @Test - @DisabledTest(message = "crbug.com/940831") @LargeTest @Feature({"Android-TabSwitcher"}) @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java index cca31e5..3b10124 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java
@@ -4,9 +4,6 @@ package org.chromium.chrome.browser; -import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_LOW_END_DEVICE; -import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; - import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.annotation.UiThreadTest; @@ -24,7 +21,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.MetricsUtils; -import org.chromium.base.test.util.Restriction; import org.chromium.chrome.R; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.profiles.Profile; @@ -74,24 +70,15 @@ @Test @SmallTest - @UiThreadTest - @Restriction(RESTRICTION_TYPE_LOW_END_DEVICE) - public void testNoSpareRendererOnLowEndDevices() throws Throwable { - mWarmupManager.createSpareWebContents(); - Assert.assertFalse(mWarmupManager.hasSpareWebContents()); - } - - @Test - @SmallTest - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testCreateAndTakeSpareRenderer() { final AtomicBoolean isRenderViewReady = new AtomicBoolean(); final AtomicReference<WebContents> webContentsReference = new AtomicReference<>(); ThreadUtils.runOnUiThread(() -> { - mWarmupManager.createSpareWebContents(); + mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); Assert.assertTrue(mWarmupManager.hasSpareWebContents()); - WebContents webContents = mWarmupManager.takeSpareWebContents(false, false); + WebContents webContents = + mWarmupManager.takeSpareWebContents(false, false, !WarmupManager.FOR_CCT); Assert.assertNotNull(webContents); Assert.assertFalse(mWarmupManager.hasSpareWebContents()); WebContentsObserver observer = new WebContentsObserver(webContents) { @@ -119,10 +106,10 @@ @Test @SmallTest @UiThreadTest - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testTakeSpareWebContents() throws Throwable { - mWarmupManager.createSpareWebContents(); - WebContents webContents = mWarmupManager.takeSpareWebContents(false, false); + mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); + WebContents webContents = + mWarmupManager.takeSpareWebContents(false, false, !WarmupManager.FOR_CCT); Assert.assertNotNull(webContents); Assert.assertFalse(mWarmupManager.hasSpareWebContents()); webContents.destroy(); @@ -131,31 +118,30 @@ @Test @SmallTest @UiThreadTest - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testTakeSpareWebContentsChecksArguments() throws Throwable { - mWarmupManager.createSpareWebContents(); - Assert.assertNull(mWarmupManager.takeSpareWebContents(true, false)); - Assert.assertNull(mWarmupManager.takeSpareWebContents(true, true)); + mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); + Assert.assertNull(mWarmupManager.takeSpareWebContents(true, false, !WarmupManager.FOR_CCT)); + Assert.assertNull(mWarmupManager.takeSpareWebContents(true, true, !WarmupManager.FOR_CCT)); Assert.assertTrue(mWarmupManager.hasSpareWebContents()); - Assert.assertNotNull(mWarmupManager.takeSpareWebContents(false, true)); + Assert.assertNotNull( + mWarmupManager.takeSpareWebContents(false, true, !WarmupManager.FOR_CCT)); Assert.assertFalse(mWarmupManager.hasSpareWebContents()); } @Test @SmallTest @UiThreadTest - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testClearsDeadWebContents() throws Throwable { - mWarmupManager.createSpareWebContents(); + mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); WebContentsUtils.simulateRendererKilled(mWarmupManager.mSpareWebContents, false); - Assert.assertNull(mWarmupManager.takeSpareWebContents(false, false)); + Assert.assertNull( + mWarmupManager.takeSpareWebContents(false, false, !WarmupManager.FOR_CCT)); } @Test @SmallTest @UiThreadTest - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testRecordSpareWebContentsStatus() throws Throwable { + public void testRecordWebContentsStatus() throws Throwable { String name = WarmupManager.WEBCONTENTS_STATUS_HISTOGRAM; MetricsUtils.HistogramDelta createdDelta = new MetricsUtils.HistogramDelta(name, WarmupManager.WebContentsStatus.CREATED); @@ -165,27 +151,45 @@ new MetricsUtils.HistogramDelta(name, WarmupManager.WebContentsStatus.KILLED); MetricsUtils.HistogramDelta destroyedDelta = new MetricsUtils.HistogramDelta(name, WarmupManager.WebContentsStatus.DESTROYED); + MetricsUtils.HistogramDelta stolenDelta = + new MetricsUtils.HistogramDelta(name, WarmupManager.WebContentsStatus.STOLEN); // Created, used. - mWarmupManager.createSpareWebContents(); + mWarmupManager.createSpareWebContents(WarmupManager.FOR_CCT); Assert.assertEquals(1, createdDelta.getDelta()); - Assert.assertNotNull(mWarmupManager.takeSpareWebContents(false, false)); + Assert.assertNotNull( + mWarmupManager.takeSpareWebContents(false, false, WarmupManager.FOR_CCT)); Assert.assertEquals(1, usedDelta.getDelta()); // Created, killed. - mWarmupManager.createSpareWebContents(); + mWarmupManager.createSpareWebContents(WarmupManager.FOR_CCT); Assert.assertEquals(2, createdDelta.getDelta()); Assert.assertNotNull(mWarmupManager.mSpareWebContents); WebContentsUtils.simulateRendererKilled(mWarmupManager.mSpareWebContents, false); Assert.assertEquals(1, killedDelta.getDelta()); - Assert.assertNull(mWarmupManager.takeSpareWebContents(false, false)); + Assert.assertNull(mWarmupManager.takeSpareWebContents(false, false, WarmupManager.FOR_CCT)); // Created, destroyed. - mWarmupManager.createSpareWebContents(); + mWarmupManager.createSpareWebContents(WarmupManager.FOR_CCT); Assert.assertEquals(3, createdDelta.getDelta()); Assert.assertNotNull(mWarmupManager.mSpareWebContents); mWarmupManager.destroySpareWebContents(); Assert.assertEquals(1, destroyedDelta.getDelta()); + + // Created, stolen. + mWarmupManager.createSpareWebContents(WarmupManager.FOR_CCT); + Assert.assertEquals(4, createdDelta.getDelta()); + Assert.assertNotNull( + mWarmupManager.takeSpareWebContents(false, false, !WarmupManager.FOR_CCT)); + Assert.assertEquals(1, stolenDelta.getDelta()); + + // Created, used, not for CCT. + mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); + Assert.assertEquals(4, createdDelta.getDelta()); + Assert.assertNotNull( + mWarmupManager.takeSpareWebContents(false, false, !WarmupManager.FOR_CCT)); + Assert.assertEquals(1, stolenDelta.getDelta()); + Assert.assertEquals(1, usedDelta.getDelta()); } /** Checks that the View inflation works. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index b639588..7852f56f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -1589,8 +1589,8 @@ @Test @SmallTest @Feature({"ContextualSearch"}) - @DisableIf.Build(message = "Flaky except on M-Phone. See https://crbug.com/837998", - sdk_is_less_than = Build.VERSION_CODES.M, sdk_is_greater_than = Build.VERSION_CODES.M) + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.M, + message = "Flaky except on M+ Phones. See https://crbug.com/837998") @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) public void testLongPressGestureFollowedByTapDoesntSelect() throws InterruptedException, TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java index 9450fbd..4007305e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.customtabs; +import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_LOW_END_DEVICE; import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; import android.content.ComponentName; @@ -122,7 +123,8 @@ ThreadUtils.runOnUiThreadBlocking(() -> { WarmupManager warmupManager = WarmupManager.getInstance(); Assert.assertTrue(warmupManager.hasSpareWebContents()); - WebContents webContents = warmupManager.takeSpareWebContents(false, false); + WebContents webContents = + warmupManager.takeSpareWebContents(false, false, WarmupManager.FOR_CCT); Assert.assertNotNull(webContents); Assert.assertFalse(warmupManager.hasSpareWebContents()); webContents.destroy(); @@ -131,6 +133,20 @@ @Test @SmallTest + @Restriction(RESTRICTION_TYPE_LOW_END_DEVICE) + public void testDoNotCreateSpareRendererOnLowEnd() throws Exception { + CustomTabsTestUtils.warmUpAndWait(); + // On UI thread because: + // 1. takeSpareWebContents needs to be called from the UI thread. + // 2. warmup() is non-blocking and posts tasks to the UI thread, it ensures proper ordering. + ThreadUtils.runOnUiThreadBlocking(() -> { + WarmupManager warmupManager = WarmupManager.getInstance(); + Assert.assertFalse(warmupManager.hasSpareWebContents()); + }); + } + + @Test + @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testCreateSpareRendererCanBeRecreated() throws Exception { CustomTabsTestUtils.warmUpAndWait(); @@ -352,12 +368,14 @@ mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, urls); ThreadUtils.runOnUiThreadBlocking( - () -> Assert.assertNull(WarmupManager.getInstance() - .takeSpareWebContents(false, false))); + () + -> Assert.assertNull(WarmupManager.getInstance().takeSpareWebContents( + false, false, WarmupManager.FOR_CCT))); } private void assertSpareWebContentsNotNullAndDestroy() { - WebContents webContents = WarmupManager.getInstance().takeSpareWebContents(false, false); + WebContents webContents = WarmupManager.getInstance().takeSpareWebContents( + false, false, WarmupManager.FOR_CCT); Assert.assertNotNull(webContents); webContents.destroy(); } @@ -558,8 +576,9 @@ Assert.assertTrue(mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null)); ThreadUtils.runOnUiThreadBlocking( - () -> Assert.assertNull(WarmupManager.getInstance() - .takeSpareWebContents(false, false))); + () + -> Assert.assertNull(WarmupManager.getInstance().takeSpareWebContents( + false, false, WarmupManager.FOR_CCT))); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java index 4f5cc0f..e4e83d5d3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -1950,18 +1950,6 @@ Assert.assertEquals(expectStartFile, mDelegate.startFileIntentCalled); Assert.assertEquals(expectProxyForIA, mDelegate.mCalledWithProxy); - if (startActivityCalled) { - final Intent intent = mDelegate.startActivityIntent; - final Uri uri = intent.getData(); - if (uri == null || uri.getScheme() == null || !uri.getScheme().equals("market")) { - Assert.assertTrue("The intent URL " + mUrl + " (" + uri - + ") doesn't have FLAG_EXCLUDE_STOPPED_PACKAGES set\n", - (mDelegate.startActivityIntent.getFlags() - & Intent.FLAG_EXCLUDE_STOPPED_PACKAGES) - != 0); - } - } - if (startActivityCalled && expectSaneIntent) { checkIntentSanity(mDelegate.startActivityIntent, "Intent"); if (mDelegate.startActivityIntent.getSelector() != null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java index 04eb55ae..84b0fda 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java
@@ -120,11 +120,8 @@ /** * Verify that the spare WebContents is used. - * - * Spare WebContents are not created on low-devices, so don't run the test. */ @Test - @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @MediumTest @Feature({"Browser"}) public void testCreateNewTabTakesSpareWebContents() throws Throwable { @@ -132,7 +129,7 @@ @Override public void run() { Tab currentTab = mActivityTestRule.getActivity().getActivityTab(); - WarmupManager.getInstance().createSpareWebContents(); + WarmupManager.getInstance().createSpareWebContents(!WarmupManager.FOR_CCT); Assert.assertTrue(WarmupManager.getInstance().hasSpareWebContents()); mActivityTestRule.getActivity().getCurrentTabCreator().createNewTab( new LoadUrlParams(mTestServer.getURL(TEST_PATH)),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java index 35fc421..3b25edd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -334,6 +334,8 @@ */ @Test @MediumTest + @DisableIf. + Build(message = "K/M https://crbug.com/897259", sdk_is_less_than = Build.VERSION_CODES.N) @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL}) public void testPresentationLocksFocus() throws InterruptedException { presentationLocksFocusImpl(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java index bbe4a99..fe57b658 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java
@@ -344,7 +344,8 @@ private WebContents prepareSpareWebcontents() { WebContents webContents = mock(WebContents.class); - when(mWarmupManager.takeSpareWebContents(anyBoolean(), anyBoolean())) + when(mWarmupManager.takeSpareWebContents( + anyBoolean(), anyBoolean(), eq(WarmupManager.FOR_CCT))) .thenReturn(webContents); return webContents; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 65ea7792..00f5271 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1072,16 +1072,12 @@ "performance_manager/common/page_almost_idle_data.h", "performance_manager/decorators/page_almost_idle_decorator.cc", "performance_manager/decorators/page_almost_idle_decorator.h", - "performance_manager/frame_resource_coordinator.cc", - "performance_manager/frame_resource_coordinator.h", "performance_manager/graph/frame_node_impl.cc", "performance_manager/graph/frame_node_impl.h", "performance_manager/graph/graph.cc", "performance_manager/graph/graph.h", "performance_manager/graph/graph_introspector_impl.cc", "performance_manager/graph/graph_introspector_impl.h", - "performance_manager/graph/graph_node_provider_impl.cc", - "performance_manager/graph/graph_node_provider_impl.h", "performance_manager/graph/node_attached_data.cc", "performance_manager/graph/node_attached_data.h", "performance_manager/graph/node_attached_data_impl.h", @@ -1102,21 +1098,14 @@ "performance_manager/observers/page_signal_generator_impl.h", "performance_manager/observers/working_set_trimmer_win.cc", "performance_manager/observers/working_set_trimmer_win.h", - "performance_manager/page_resource_coordinator.cc", - "performance_manager/page_resource_coordinator.h", "performance_manager/performance_manager.cc", "performance_manager/performance_manager.h", "performance_manager/performance_manager_tab_helper.cc", "performance_manager/performance_manager_tab_helper.h", - "performance_manager/process_resource_coordinator.cc", - "performance_manager/process_resource_coordinator.h", "performance_manager/render_process_user_data.cc", "performance_manager/render_process_user_data.h", "performance_manager/resource_coordinator_clock.cc", "performance_manager/resource_coordinator_clock.h", - "performance_manager/resource_coordinator_interface.h", - "performance_manager/system_resource_coordinator.cc", - "performance_manager/system_resource_coordinator.h", "performance_manager/webui_graph_dump_impl.cc", "performance_manager/webui_graph_dump_impl.h", "performance_monitor/metric_evaluator_helper_win.cc", @@ -1462,6 +1451,8 @@ "resource_coordinator/utils.h", "resources_util.cc", "resources_util.h", + "scoped_visibility_tracker.cc", + "scoped_visibility_tracker.h", "search/instant_io_context.cc", "search/instant_io_context.h", "search/ntp_icon_source.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index e352258..cd01abad 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3494,11 +3494,6 @@ "")}, #if defined(OS_CHROMEOS) - {"enable-app-shortcut-search", - flag_descriptions::kEnableAppShortcutSearchName, - flag_descriptions::kEnableAppShortcutSearchDescription, kOsCrOS, - FEATURE_VALUE_TYPE(app_list_features::kEnableAppShortcutSearch)}, - {"enable-play-store-search", flag_descriptions::kEnablePlayStoreSearchName, flag_descriptions::kEnablePlayStoreSearchDescription, kOsCrOS, FEATURE_VALUE_TYPE(app_list_features::kEnablePlayStoreAppSearch)}, @@ -4091,6 +4086,13 @@ FEATURE_VALUE_TYPE(views::kInstallableInkDropFeature)}, #endif // defined(TOOLKIT_VIEWS) +#if defined(OS_CHROMEOS) + {"enable-assistant-launcher-integration", + flag_descriptions::kEnableAssistantLauncherIntegrationName, + flag_descriptions::kEnableAssistantLauncherIntegrationDescription, kOsCrOS, + FEATURE_VALUE_TYPE(app_list_features::kEnableEmbeddedAssistantUI)}, +#endif // OS_CHROMEOS + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 20de66e..f532dbdc 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5611,3 +5611,13 @@ Profile* profile = Profile::FromBrowserContext(browser_context); return AccessibilityLabelsServiceFactory::GetForProfile(profile)->GetAXMode(); } + +#if defined(OS_ANDROID) +content::ContentBrowserClient::WideColorGamutHeuristic +ChromeContentBrowserClient::GetWideColorGamutHeuristic() const { + if (features::UseDisplayWideColorGamut()) { + return WideColorGamutHeuristic::kUseDisplay; + } + return WideColorGamutHeuristic::kNone; +} +#endif
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 5ba3c8dc..36e37d1 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -579,6 +579,11 @@ ui::AXMode GetAXModeForBrowserContext( content::BrowserContext* browser_context) override; +#if defined(OS_ANDROID) + ContentBrowserClient::WideColorGamutHeuristic GetWideColorGamutHeuristic() + const override; +#endif + // Determines the committed previews state for the passed in params. static content::PreviewsState DetermineCommittedPreviewsForURL( const GURL& url,
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc index 75d7cec..044c8c0e 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc +++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
@@ -22,6 +22,7 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" +#include "net/base/url_util.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "url/gurl.h" @@ -85,9 +86,9 @@ kDefaultToPersistCookieValue, std::string() /* domain */, std::string() /* path */, base::Time::Now() /* creation_time */, base::Time() /* expiration_time */, - base::Time::Now() /* last_access_time */, true /* secure */, - false /* http_only */, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_DEFAULT), + base::Time::Now() /* last_access_time */, + !net::IsLocalhost(app_url) /* secure */, false /* http_only */, + net::CookieSameSite::STRICT_MODE, net::COOKIE_PRIORITY_DEFAULT), "https", false /* modify_http_only */, base::BindOnce(&AndroidSmsAppSetupControllerImpl:: OnSetRememberDeviceByDefaultCookieResult, @@ -272,9 +273,9 @@ std::string() /* domain */, std::string() /* path */, base::Time::Now() /* creation_time */, base::Time() /* expiration_time */, - base::Time::Now() /* last_access_time */, true /* secure */, - false /* http_only */, net::CookieSameSite::STRICT_MODE, - net::COOKIE_PRIORITY_DEFAULT), + base::Time::Now() /* last_access_time */, + !net::IsLocalhost(app_url) /* secure */, false /* http_only */, + net::CookieSameSite::STRICT_MODE, net::COOKIE_PRIORITY_DEFAULT), "https", false /* modify_http_only */, base::BindOnce( &AndroidSmsAppSetupControllerImpl::OnSetMigrationCookieResult,
diff --git a/chrome/browser/chromeos/android_sms/android_sms_switches.cc b/chrome/browser/chromeos/android_sms/android_sms_switches.cc index 19b460d..e6ca818 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_switches.cc +++ b/chrome/browser/chromeos/android_sms/android_sms_switches.cc
@@ -8,4 +8,7 @@ const char kAlternateAndroidMessagesUrl[] = "alternate-android-messages-url"; +const char kAlternateAndroidMessagesInstallUrl[] = + "alternate-android-messages-install-url"; + } // namespace switches
diff --git a/chrome/browser/chromeos/android_sms/android_sms_switches.h b/chrome/browser/chromeos/android_sms/android_sms_switches.h index d8020ff..4106bd0 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_switches.h +++ b/chrome/browser/chromeos/android_sms/android_sms_switches.h
@@ -11,6 +11,10 @@ // Android Messages for Web url used by AndroidSmsService. extern const char kAlternateAndroidMessagesUrl[]; +// When specified with a url string as parameter, the given url overrides the +// Android Messages for Web PWA installation url used by AndroidSmsService. +extern const char kAlternateAndroidMessagesInstallUrl[]; + } // namespace switches #endif // CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_SWITCHES_H_
diff --git a/chrome/browser/chromeos/android_sms/android_sms_urls.cc b/chrome/browser/chromeos/android_sms/android_sms_urls.cc index f2c34f2f..9b26907 100644 --- a/chrome/browser/chromeos/android_sms/android_sms_urls.cc +++ b/chrome/browser/chromeos/android_sms/android_sms_urls.cc
@@ -56,12 +56,22 @@ } GURL GetAndroidMessagesURL(bool use_install_url, PwaDomain pwa_domain) { - // If a custom URL was passed via a command line argument, use it. - std::string url_from_command_line_arg = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kAlternateAndroidMessagesUrl); - if (!url_from_command_line_arg.empty()) - return GURL(url_from_command_line_arg); + // If present, use commandline override for the preferred domain. + if (pwa_domain == GetPreferredPwaDomain()) { + std::string url_from_command_line_arg; + if (use_install_url) { + url_from_command_line_arg = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kAlternateAndroidMessagesInstallUrl); + } else { + url_from_command_line_arg = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kAlternateAndroidMessagesUrl); + } + + if (!url_from_command_line_arg.empty()) + return GURL(url_from_command_line_arg); + } switch (pwa_domain) { case PwaDomain::kProdAndroid:
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc index 3843dda..d85d40d7 100644 --- a/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/policy/arc_policy_bridge_unittest.cc
@@ -547,7 +547,7 @@ "\",\"vpnConfigDisabled\":true}"); } -TEST_P(ArcPolicyBridgeAffiliatedTest, ApkCacheEnabledTest) { +TEST_P(ArcPolicyBridgeAffiliatedTest, DISABLED_ApkCacheEnabledTest) { const std::string apk_cache_enabled_policy( "{\"apkCacheEnabled\":true,\"guid\":\"" + instance_guid() + "\"}"); policy_map().Set(policy::key::kArcPolicy, policy::POLICY_LEVEL_MANDATORY,
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.cc index 140f78f..657c5c9 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.cc
@@ -16,7 +16,7 @@ DCHECK(position); category_ = data.substr(0, position); name_ = data.substr(position + 1); - DCHECK(!category_.empty() && !name_.empty()); + DCHECK(!category_.empty()); position = name_.find('('); if (position == std::string::npos) return;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc index da7bedb..ce26725 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc
@@ -47,18 +47,8 @@ constexpr char kDequeueBufferQuery[] = "android:dequeueBuffer"; constexpr char kQueueBufferQuery[] = "android:queueBuffer"; -constexpr char kAttachSurfaceQueury[] = - "toplevel:OnLibevent/exo:Surface::Attach"; -constexpr char kProduceTransferableResourceQuery[] = - "toplevel:OnLibevent/exo:Surface::Commit/" - "exo:Buffer::ProduceTransferableResource"; -constexpr char kReleaseContentQuery[] = - "toplevel:MessageLoop::RunTask/exo:Buffer::ReleaseContents"; constexpr char kBarrierOrderingSubQuery[] = "gpu:CommandBufferProxyImpl::OrderingBarrier"; -constexpr char kBarrierFlushQuery[] = - "toplevel:MessageLoop::RunTask/gpu:Scheduler::RunNextTask/" - "gpu:CommandBufferStub::OnAsyncFlush"; constexpr char kBufferInUseQuery[] = "exo:BufferInUse"; constexpr char kHandleMessageRefreshQuery[] = "android:onMessageReceived/android:handleMessageRefresh"; @@ -69,6 +59,14 @@ constexpr char kVsyncQuery0[] = "android:HW_VSYNC_0|0"; constexpr char kVsyncQuery1[] = "android:HW_VSYNC_0|1"; +constexpr char kBarrierFlushMatcher[] = "gpu:CommandBufferStub::OnAsyncFlush"; + +constexpr char kExoSurfaceAttachMatcher[] = "exo:Surface::Attach"; +constexpr char kExoBufferProduceResourceMatcher[] = + "exo:Buffer::ProduceTransferableResource"; +constexpr char kExoBufferReleaseContentsMatcher[] = + "exo:Buffer::ReleaseContents"; + constexpr ssize_t kInvalidBufferIndex = -1; // Helper factory class that produces graphic buffer events from the giving @@ -91,16 +89,17 @@ BufferGraphicsEventMapper() { // exo rules rules_.emplace_back(std::make_pair( - std::make_unique<ArcTracingEventMatcher>("exo:Surface::Attach"), + std::make_unique<ArcTracingEventMatcher>(kExoSurfaceAttachMatcher), MappingRule(BufferEventType::kExoSurfaceAttach, BufferEventType::kNone))); rules_.emplace_back( std::make_pair(std::make_unique<ArcTracingEventMatcher>( - "exo:Buffer::ProduceTransferableResource"), + kExoBufferProduceResourceMatcher), MappingRule(BufferEventType::kExoProduceResource, BufferEventType::kNone))); rules_.emplace_back(std::make_pair( - std::make_unique<ArcTracingEventMatcher>("exo:Buffer::ReleaseContents"), + std::make_unique<ArcTracingEventMatcher>( + kExoBufferReleaseContentsMatcher), MappingRule(BufferEventType::kNone, BufferEventType::kExoReleased))); rules_.emplace_back(std::make_pair( std::make_unique<ArcTracingEventMatcher>("exo:BufferInUse(step=bound)"), @@ -117,11 +116,10 @@ "gpu:CommandBufferProxyImpl::OrderingBarrier"), MappingRule(BufferEventType::kChromeBarrierOrder, BufferEventType::kNone))); - rules_.emplace_back( - std::make_pair(std::make_unique<ArcTracingEventMatcher>( - "gpu:CommandBufferStub::OnAsyncFlush"), - MappingRule(BufferEventType::kNone, - BufferEventType::kChromeBarrierFlush))); + rules_.emplace_back(std::make_pair( + std::make_unique<ArcTracingEventMatcher>(kBarrierFlushMatcher), + MappingRule(BufferEventType::kNone, + BufferEventType::kChromeBarrierFlush))); // android rules rules_.emplace_back(std::make_pair( @@ -177,19 +175,18 @@ "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=WaitForAck)"), MappingRule(BufferEventType::kChromeOSWaitForAck, BufferEventType::kNone))); - rules_.emplace_back(std::make_pair( - std::make_unique<ArcTracingEventMatcher>( - "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=" - "WaitForPresentation)"), - MappingRule(BufferEventType::kChromeOSWaitForPresentation, - BufferEventType::kNone))); + rules_.emplace_back( + std::make_pair(std::make_unique<ArcTracingEventMatcher>( + "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=" + "WaitForPresentation)"), + MappingRule(BufferEventType::kChromeOSPresentationDone, + BufferEventType::kNone))); matcher = std::make_unique<ArcTracingEventMatcher>( "viz,benchmark:Graphics.Pipeline.DrawAndSwap"); matcher->SetPhase(TRACE_EVENT_PHASE_ASYNC_END); - rules_.emplace_back( - std::make_pair(std::move(matcher), - MappingRule(BufferEventType::kNone, - BufferEventType::kChromeOSDrawFinished))); + rules_.emplace_back(std::make_pair( + std::move(matcher), MappingRule(BufferEventType::kNone, + BufferEventType::kChromeOSSwapDone))); } ~BufferGraphicsEventMapper() = default; @@ -361,21 +358,76 @@ } } +std::string RouteToSelector(const std::vector<const ArcTracingEvent*>& route) { + std::string result; + for (const ArcTracingEvent* segment : route) + result = result + "/" + segment->GetCategory() + ":" + segment->GetName(); + return result; +} + +void DetermineHierarchy(std::vector<const ArcTracingEvent*>* route, + const ArcTracingEvent* event, + const ArcTracingEventMatcher& matcher, + std::string* out_query) { + if (!out_query->empty()) + return; + + route->emplace_back(event); + + if (matcher.Match(*event)) { + *out_query = RouteToSelector(*route); + } else { + for (const auto& child : event->children()) + DetermineHierarchy(route, child.get(), matcher, out_query); + } + + route->pop_back(); +} + BufferToEvents GetChromeEvents( const ArcTracingModel& common_model, std::map<std::string, int>* buffer_id_to_task_id) { + // The tracing hierarchy may be easy changed any time in Chrome. This makes + // using static queries fragile and dependent of many external components. To + // provide the reliable way of requesting the needed information, let scan + // |common_model| for top level events and determine the hierarchy of + // interesting events dynamically. + const ArcTracingModel::TracingEventPtrs top_level_events = + common_model.Select("toplevel:"); + std::vector<const ArcTracingEvent*> route; + std::string barrier_flush_query; + const ArcTracingEventMatcher barrier_flush_matcher(kBarrierFlushMatcher); + std::string attach_surface_query; + const ArcTracingEventMatcher attach_surface_matcher(kExoSurfaceAttachMatcher); + std::string produce_resource_query; + const ArcTracingEventMatcher produce_resource_matcher( + kExoBufferProduceResourceMatcher); + std::string release_contents_query; + const ArcTracingEventMatcher release_contents_matcher( + kExoBufferReleaseContentsMatcher); + for (const ArcTracingEvent* top_level_event : top_level_events) { + DetermineHierarchy(&route, top_level_event, barrier_flush_matcher, + &barrier_flush_query); + DetermineHierarchy(&route, top_level_event, attach_surface_matcher, + &attach_surface_query); + DetermineHierarchy(&route, top_level_event, produce_resource_matcher, + &produce_resource_query); + DetermineHierarchy(&route, top_level_event, release_contents_matcher, + &release_contents_query); + } + BufferToEvents per_buffer_chrome_events; // Only exo:Surface::Attach has app id argument. - ProcessChromeEvents(common_model, kAttachSurfaceQueury, + ProcessChromeEvents(common_model, attach_surface_query, &per_buffer_chrome_events, buffer_id_to_task_id); - ProcessChromeEvents(common_model, kReleaseContentQuery, + ProcessChromeEvents(common_model, release_contents_query, &per_buffer_chrome_events, nullptr /* buffer_id_to_task_id */); // Handle ProduceTransferableResource events. They have extra link to barrier // events. Use buffer_id to bind events for the same graphics buffer. const ArcTracingModel::TracingEventPtrs produce_resource_events = - common_model.Select(kProduceTransferableResourceQuery); + common_model.Select(produce_resource_query); std::map<int, std::string> put_offset_to_buffer_id_map; for (const ArcTracingEvent* event : produce_resource_events) { const std::string buffer_id = event->GetArgAsString( @@ -416,7 +468,7 @@ // Find associated barrier flush event using put_offset argument. const ArcTracingModel::TracingEventPtrs barrier_flush_events = - common_model.Select(kBarrierFlushQuery); + common_model.Select(barrier_flush_query); for (const ArcTracingEvent* event : barrier_flush_events) { const int put_offset = event->GetArgAsInteger(kArgumentPutOffset, 0 /* default_value */); @@ -672,7 +724,7 @@ !IsInRange(type, BufferEventType::kVsync, BufferEventType::kSurfaceFlingerCompositionDone) && !IsInRange(type, BufferEventType::kChromeOSDraw, - BufferEventType::kChromeOSDrawFinished)) { + BufferEventType::kChromeOSSwapDone)) { return false; } @@ -942,4 +994,10 @@ return true; } +std::ostream& operator<<(std::ostream& os, + ArcTracingGraphicsModel::BufferEventType event_type) { + return os << static_cast<typename std::underlying_type< + ArcTracingGraphicsModel::BufferEventType>::type>(event_type); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h index bea1e39..1709164 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h
@@ -68,11 +68,11 @@ kSurfaceFlingerCompositionDone, // 403 // Chrome OS top level events. - kChromeOSDraw = 500, // 500 - kChromeOSSwap, // 501 - kChromeOSWaitForAck, // 502 - kChromeOSWaitForPresentation, // 503 - kChromeOSDrawFinished, // 504 + kChromeOSDraw = 500, // 500 + kChromeOSSwap, // 501 + kChromeOSWaitForAck, // 502 + kChromeOSPresentationDone, // 503 + kChromeOSSwapDone, // 504 }; struct BufferEvent { @@ -142,6 +142,9 @@ DISALLOW_COPY_AND_ASSIGN(ArcTracingGraphicsModel); }; +std::ostream& operator<<(std::ostream& os, + ArcTracingGraphicsModel::BufferEventType); + } // namespace arc #endif // CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_TRACING_GRAPHICS_MODEL_H_
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc index c432b7e..9490722 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc
@@ -62,15 +62,26 @@ int64_t previous_timestamp = 0; std::set<GraphicsEventType> used_types; for (const auto& event : events) { - if (event.timestamp < previous_timestamp) + if (event.timestamp < previous_timestamp) { + LOG(ERROR) << "Timestamp sequence broken: " << event.timestamp << " vs " + << previous_timestamp << "."; return false; + } previous_timestamp = event.timestamp; - if (!allowed_types.count(event.type)) + if (!allowed_types.count(event.type)) { + LOG(ERROR) << "Unexpected event type " << event.type << "."; return false; + } used_types.insert(event.type); } - if (used_types.size() != allowed_types.size()) + if (used_types.size() != allowed_types.size()) { + for (const auto& allowed_type : allowed_types) { + if (!used_types.count(allowed_type)) + LOG(ERROR) << "Required event type " << allowed_type + << " << is not found."; + } return false; + } return true; } @@ -141,8 +152,8 @@ GraphicsEventType::kChromeOSDraw, GraphicsEventType::kChromeOSSwap, GraphicsEventType::kChromeOSWaitForAck, - GraphicsEventType::kChromeOSWaitForPresentation, - GraphicsEventType::kChromeOSDrawFinished, + GraphicsEventType::kChromeOSPresentationDone, + GraphicsEventType::kChromeOSSwapDone, })); EXPECT_FALSE(graphics_model.view_buffers().empty()); for (const auto& view : graphics_model.view_buffers()) {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index a10c1d60..6d44a28 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -640,6 +640,8 @@ TestCase("transferFromDownloadsToTeamDrive").EnableDriveFs(), TestCase("transferBetweenTeamDrives").DisableDriveFs(), TestCase("transferBetweenTeamDrives").EnableDriveFs(), + TestCase("transferDragAndDrop"), + TestCase("transferDragAndHover"), TestCase("transferFromDownloadsToDownloads"))); WRAPPED_INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc index 72c1969b..0d2410ff 100644 --- a/chrome/browser/chromeos/login/screens/reset_screen.cc +++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -41,20 +41,6 @@ constexpr const char kUserActionTPMFirmwareUpdateLearnMore[] = "tpm-firmware-update-learn-more-link"; -constexpr const char kContextKeyIsRollbackAvailable[] = "rollback-available"; -constexpr const char kContextKeyIsRollbackChecked[] = "rollback-checked"; -constexpr const char kContextKeyIsTPMFirmwareUpdateAvailable[] = - "tpm-firmware-update-available"; -constexpr const char kContextKeyIsTPMFirmwareUpdateChecked[] = - "tpm-firmware-update-checked"; -constexpr const char kContextKeyIsTPMFirmwareUpdateEditable[] = - "tpm-firmware-update-editable"; -constexpr const char kContextKeyTPMFirmwareUpdateMode[] = - "tpm-firmware-update-mode"; -constexpr const char kContextKeyIsConfirmational[] = "is-confirmational-view"; -constexpr const char kContextKeyIsOfficialBuild[] = "is-official-build"; -constexpr const char kContextKeyScreenState[] = "screen-state"; - void StartTPMFirmwareUpdate( tpm_firmware_update::Mode requested_mode, const std::set<tpm_firmware_update::Mode>& available_modes) { @@ -101,21 +87,21 @@ exit_callback_(exit_callback), weak_ptr_factory_(this) { DCHECK(view_); - if (view_) + if (view_) { view_->Bind(this); - context_.SetInteger(kContextKeyScreenState, STATE_RESTART_REQUIRED); - context_.SetBoolean(kContextKeyIsRollbackAvailable, false); - context_.SetBoolean(kContextKeyIsRollbackChecked, false); - context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, false); - context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked, false); - context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable, true); - context_.SetInteger(kContextKeyTPMFirmwareUpdateMode, - static_cast<int>(tpm_firmware_update::Mode::kPowerwash)); - context_.SetBoolean(kContextKeyIsConfirmational, false); - context_.SetBoolean(kContextKeyIsOfficialBuild, false); + view_->SetScreenState(ResetView::State::kRestartRequired); + view_->SetIsRollbackAvailable(false); + view_->SetIsRollbackChecked(false); + view_->SetIsTpmFirmwareUpdateAvailable(false); + view_->SetIsTpmFirmwareUpdateChecked(false); + view_->SetIsTpmFirmwareUpdateEditable(true); + view_->SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode::kPowerwash); + view_->SetIsConfirmational(false); + view_->SetIsOfficialBuild(false); #if defined(OFFICIAL_BUILD) - context_.SetBoolean(kContextKeyIsOfficialBuild, true); + view_->SetIsOfficialBuild(true); #endif + } } ResetScreen::~ResetScreen() { @@ -139,22 +125,23 @@ reset::DialogViewType dialog_type = reset::DIALOG_VIEW_TYPE_SIZE; // used by UMA metrics. - ContextEditor context_editor = GetContextEditor(); - bool restart_required = user_manager::UserManager::Get()->IsUserLoggedIn() || !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kFirstExecAfterBoot); if (restart_required) { - context_editor.SetInteger(kContextKeyScreenState, STATE_RESTART_REQUIRED); + if (view_) + view_->SetScreenState(ResetView::State::kRestartRequired); dialog_type = reset::DIALOG_SHORTCUT_RESTART_REQUIRED; } else { - context_editor.SetInteger(kContextKeyScreenState, STATE_POWERWASH_PROPOSAL); + if (view_) + view_->SetScreenState(ResetView::State::kPowerwashProposal); } // Set availability of Rollback feature. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableRollbackOption)) { - context_editor.SetBoolean(kContextKeyIsRollbackAvailable, false); + if (view_) + view_->SetIsRollbackAvailable(false); dialog_type = reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE; } else { chromeos::DBusThreadManager::Get() @@ -177,10 +164,11 @@ // availability test to initialize the dialog. This avoids a race condition // where the powerwash dialog gets shown immediately after reboot before the // init job to determine update availability has completed. - context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, true); - context_editor.SetInteger( - kContextKeyTPMFirmwareUpdateMode, - prefs->GetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode)); + if (view_) { + view_->SetIsTpmFirmwareUpdateAvailable(true); + view_->SetTpmFirmwareUpdateMode(static_cast<tpm_firmware_update::Mode>( + prefs->GetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode))); + } } else { // If a TPM firmware update hasn't previously been requested, check the // system to see whether to offer the checkbox to update TPM firmware. Note @@ -192,10 +180,10 @@ base::TimeDelta::FromSeconds(10)); } - context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked, - tpm_firmware_update_requested); - context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable, - !tpm_firmware_update_requested); + if (view_) { + view_->SetIsTpmFirmwareUpdateChecked(tpm_firmware_update_requested); + view_->SetIsTpmFirmwareUpdateEditable(!tpm_firmware_update_requested); + } // Clear prefs so the reset screen isn't triggered again the next time the // device is about to show the login screen. @@ -236,50 +224,45 @@ } void ResetScreen::OnCancel() { - if (context_.GetInteger(kContextKeyScreenState, STATE_RESTART_REQUIRED) == - STATE_REVERT_PROMISE) { + if (view_ && view_->GetScreenState() == ResetView::State::kRevertPromise) { return; } - // Hide Rollback view for the next show. - if (context_.GetBoolean(kContextKeyIsRollbackAvailable) && - context_.GetBoolean(kContextKeyIsRollbackChecked)) { + if (view_ && view_->GetIsRollbackAvailable() && view_->GetIsRollbackChecked()) OnToggleRollback(); - } DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); exit_callback_.Run(); } void ResetScreen::OnPowerwash() { - if (context_.GetInteger(kContextKeyScreenState, 0) != - STATE_POWERWASH_PROPOSAL) + if (view_ && + view_->GetScreenState() != ResetView::State::kPowerwashProposal) { return; + } - GetContextEditor().SetBoolean(kContextKeyIsConfirmational, false); - CommitContextChanges(); + if (view_) + view_->SetIsConfirmational(false); - if (context_.GetBoolean(kContextKeyIsRollbackChecked) && - !context_.GetBoolean(kContextKeyIsRollbackAvailable)) { + if (view_ && view_->GetIsRollbackChecked() && + !view_->GetIsRollbackAvailable()) { NOTREACHED() << "Rollback was checked but not available. Starting powerwash."; } - if (context_.GetBoolean(kContextKeyIsRollbackAvailable) && - context_.GetBoolean(kContextKeyIsRollbackChecked)) { - GetContextEditor().SetInteger(kContextKeyScreenState, STATE_REVERT_PROMISE); + if (view_ && view_->GetIsRollbackAvailable() && + view_->GetIsRollbackChecked()) { + view_->SetScreenState(ResetView::State::kRevertPromise); DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this); VLOG(1) << "Starting Rollback"; DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback(); - } else if (context_.GetBoolean(kContextKeyIsTPMFirmwareUpdateChecked)) { + } else if (view_ && view_->GetIsTpmFirmwareUpdateChecked()) { VLOG(1) << "Starting TPM firmware update"; // Re-check availability with a couple seconds timeout. This addresses the // case where the powerwash dialog gets shown immediately after reboot and // the decision on whether the update is available is not known immediately. tpm_firmware_update::GetAvailableUpdateModes( - base::BindOnce( - &StartTPMFirmwareUpdate, - static_cast<tpm_firmware_update::Mode>( - context_.GetInteger(kContextKeyTPMFirmwareUpdateMode))), + base::BindOnce(&StartTPMFirmwareUpdate, + view_->GetTpmFirmwareUpdateMode()), base::TimeDelta::FromSeconds(10)); } else { VLOG(1) << "Starting Powerwash"; @@ -290,7 +273,7 @@ void ResetScreen::OnRestart() { PrefService* prefs = g_browser_process->local_state(); prefs->SetBoolean(prefs::kFactoryResetRequested, true); - if (context_.GetBoolean(kContextKeyIsTPMFirmwareUpdateChecked)) { + if (view_ && view_->GetIsTpmFirmwareUpdateChecked()) { prefs->SetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode, static_cast<int>(tpm_firmware_update::Mode::kPowerwash)); } else { @@ -304,39 +287,38 @@ void ResetScreen::OnToggleRollback() { // Hide Rollback if visible. - if (context_.GetBoolean(kContextKeyIsRollbackAvailable) && - context_.GetBoolean(kContextKeyIsRollbackChecked)) { + if (view_ && view_->GetIsRollbackAvailable() && + view_->GetIsRollbackChecked()) { VLOG(1) << "Hiding rollback view on reset screen"; - GetContextEditor().SetBoolean(kContextKeyIsRollbackChecked, false); + view_->SetIsRollbackChecked(false); return; } // Show Rollback if available. VLOG(1) << "Requested rollback availability" - << context_.GetBoolean(kContextKeyIsRollbackAvailable); - if (context_.GetBoolean(kContextKeyIsRollbackAvailable) && - !context_.GetBoolean(kContextKeyIsRollbackChecked)) { + << view_->GetIsRollbackAvailable(); + if (view_->GetIsRollbackAvailable() && !view_->GetIsRollbackChecked()) { UMA_HISTOGRAM_ENUMERATION( "Reset.ChromeOS.PowerwashDialogShown", reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE, reset::DIALOG_VIEW_TYPE_SIZE); - GetContextEditor().SetBoolean(kContextKeyIsRollbackChecked, true); + view_->SetIsRollbackChecked(true); } } void ResetScreen::OnShowConfirm() { reset::DialogViewType dialog_type = - context_.GetBoolean(kContextKeyIsRollbackChecked) + view_->GetIsRollbackChecked() ? reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK : reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY; UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown", dialog_type, reset::DIALOG_VIEW_TYPE_SIZE); - GetContextEditor().SetBoolean(kContextKeyIsConfirmational, true); + view_->SetIsConfirmational(true); } void ResetScreen::OnConfirmationDismissed() { - GetContextEditor().SetBoolean(kContextKeyIsConfirmational, false); + view_->SetIsConfirmational(false); } void ResetScreen::ShowHelpArticle(HelpAppLauncher::HelpTopic topic) { @@ -356,7 +338,7 @@ if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR || status.status == UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) { - GetContextEditor().SetInteger(kContextKeyScreenState, STATE_ERROR); + view_->SetScreenState(ResetView::State::kError); // Show error screen. base_screen_delegate_->GetErrorScreen()->SetUIState( NetworkError::UI_STATE_ROLLBACK_ERROR); @@ -377,19 +359,15 @@ UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown", dialog_type, reset::DIALOG_VIEW_TYPE_SIZE); - GetContextEditor().SetBoolean(kContextKeyIsRollbackAvailable, can_rollback); + view_->SetIsRollbackAvailable(can_rollback); } void ResetScreen::OnTPMFirmwareUpdateAvailableCheck( const std::set<tpm_firmware_update::Mode>& modes) { bool available = modes.count(tpm_firmware_update::Mode::kPowerwash) > 0; - ContextEditor context_editor = GetContextEditor(); - context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, available); - if (available) { - context_editor.SetInteger( - kContextKeyTPMFirmwareUpdateMode, - static_cast<int>(tpm_firmware_update::Mode::kPowerwash)); - } + view_->SetIsTpmFirmwareUpdateAvailable(available); + if (available) + view_->SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode::kPowerwash); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.h b/chrome/browser/chromeos/login/screens/reset_screen.h index 0e6adc0..a962c86 100644 --- a/chrome/browser/chromeos/login/screens/reset_screen.h +++ b/chrome/browser/chromeos/login/screens/reset_screen.h
@@ -54,13 +54,6 @@ void OnTPMFirmwareUpdateAvailableCheck( const std::set<tpm_firmware_update::Mode>& modes); - enum State { - STATE_RESTART_REQUIRED = 0, - STATE_REVERT_PROMISE, - STATE_POWERWASH_PROPOSAL, - STATE_ERROR - }; - void OnCancel(); void OnPowerwash(); void OnRestart();
diff --git a/chrome/browser/chromeos/login/screens/reset_view.h b/chrome/browser/chromeos/login/screens/reset_view.h index 22c3dcc..514d651f 100644 --- a/chrome/browser/chromeos/login/screens/reset_view.h +++ b/chrome/browser/chromeos/login/screens/reset_view.h
@@ -9,6 +9,10 @@ namespace chromeos { +namespace tpm_firmware_update { +enum class Mode; +} + class ResetScreen; // Interface for dependency injection between ResetScreen and its actual @@ -23,6 +27,29 @@ virtual void Unbind() = 0; virtual void Show() = 0; virtual void Hide() = 0; + + enum class State { + kRestartRequired = 0, + kRevertPromise, + kPowerwashProposal, + kError, + }; + + virtual void SetIsRollbackAvailable(bool value) = 0; + virtual void SetIsRollbackChecked(bool value) = 0; + virtual void SetIsTpmFirmwareUpdateAvailable(bool value) = 0; + virtual void SetIsTpmFirmwareUpdateChecked(bool value) = 0; + virtual void SetIsTpmFirmwareUpdateEditable(bool value) = 0; + virtual void SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode value) = 0; + virtual void SetIsConfirmational(bool value) = 0; + virtual void SetIsOfficialBuild(bool value) = 0; + virtual void SetScreenState(State value) = 0; + + virtual State GetScreenState() = 0; + virtual tpm_firmware_update::Mode GetTpmFirmwareUpdateMode() = 0; + virtual bool GetIsRollbackAvailable() = 0; + virtual bool GetIsRollbackChecked() = 0; + virtual bool GetIsTpmFirmwareUpdateChecked() = 0; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc index 127d817..734d72c 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc +++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" -#include "base/system/sys_info.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part_chromeos.h" #include "chrome/browser/chrome_notification_types.h" @@ -242,8 +241,7 @@ oobe_configuration_->CheckConfiguration(); } - if (!base::SysInfo::IsRunningOnChromeOS() && - login_account_id == user_manager::StubAccountId()) { + if (login_account_id == user_manager::StubAccountId()) { // Start a user session with stub user. This also happens on a dev machine // when running Chrome w/o login flow. See PreEarlyInitialization(). // In these contexts, emulate as if sync has been initialized.
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index d2bc4e9..effddd1e 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -523,14 +523,10 @@ } void WizardController::ShowWelcomeScreen() { - VLOG(1) << "Showing welcome screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_WELCOME); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_WELCOME)); } void WizardController::ShowNetworkScreen() { - VLOG(1) << "Showing network screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_NETWORK); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_NETWORK)); } @@ -550,14 +546,7 @@ login_screen_started_ = true; } -void WizardController::ShowPreviousScreen() { - DCHECK(previous_screen_); - SetCurrentScreen(previous_screen_); -} - void WizardController::ShowEulaScreen() { - VLOG(1) << "Showing EULA screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_EULA); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_EULA)); } @@ -570,38 +559,26 @@ } void WizardController::ShowDemoModePreferencesScreen() { - VLOG(1) << "Showing demo mode preferences screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_DEMO_PREFERENCES)); } void WizardController::ShowDemoModeSetupScreen() { - VLOG(1) << "Showing demo mode setup screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_DEMO_SETUP); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_DEMO_SETUP)); } void WizardController::ShowResetScreen() { - VLOG(1) << "Showing reset screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_RESET); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_RESET)); } void WizardController::ShowKioskEnableScreen() { - VLOG(1) << "Showing kiosk enable screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_KIOSK_ENABLE); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_KIOSK_ENABLE)); } void WizardController::ShowKioskAutolaunchScreen() { - VLOG(1) << "Showing kiosk autolaunch screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_KIOSK_AUTOLAUNCH); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_KIOSK_AUTOLAUNCH)); } void WizardController::ShowEnableDebuggingScreen() { - VLOG(1) << "Showing enable developer features screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING)); } @@ -616,15 +593,11 @@ return; } - VLOG(1) << "Showing Terms of Service screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_TERMS_OF_SERVICE); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_TERMS_OF_SERVICE)); } void WizardController::ShowSyncConsentScreen() { #if defined(GOOGLE_CHROME_BUILD) - VLOG(1) << "Showing Sync Consent screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_SYNC_CONSENT); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_SYNC_CONSENT)); #else OnSyncConsentFinished(); @@ -632,22 +605,15 @@ } void WizardController::ShowFingerprintSetupScreen() { - VLOG(1) << "Showing Fingerprint Setup screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_FINGERPRINT_SETUP); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_FINGERPRINT_SETUP)); } void WizardController::ShowMarketingOptInScreen() { - VLOG(1) << "Showing Marketing Opt-In screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_MARKETING_OPT_IN); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_MARKETING_OPT_IN)); } void WizardController::ShowArcTermsOfServiceScreen() { if (arc::IsArcTermsOfServiceOobeNegotiationNeeded()) { - VLOG(1) << "Showing ARC Terms of Service screen."; - UpdateStatusAreaVisibilityForScreen( - OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE)); ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean( arc::prefs::kArcTermsShownInOobe, true); @@ -657,26 +623,18 @@ } void WizardController::ShowRecommendAppsScreen() { - VLOG(1) << "Showing Recommend Apps screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_RECOMMEND_APPS); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_RECOMMEND_APPS)); } void WizardController::ShowAppDownloadingScreen() { - VLOG(1) << "Showing App Downloading screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_APP_DOWNLOADING); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_APP_DOWNLOADING)); } void WizardController::ShowWrongHWIDScreen() { - VLOG(1) << "Showing wrong HWID screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_WRONG_HWID); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_WRONG_HWID)); } void WizardController::ShowAutoEnrollmentCheckScreen() { - VLOG(1) << "Showing Auto-enrollment check screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK); AutoEnrollmentCheckScreen* screen = AutoEnrollmentCheckScreen::Get(screen_manager()); if (retry_auto_enrollment_check_) @@ -686,33 +644,22 @@ } void WizardController::ShowArcKioskSplashScreen() { - VLOG(1) << "Showing ARC kiosk splash screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_ARC_KIOSK_SPLASH); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ARC_KIOSK_SPLASH)); } void WizardController::ShowHIDDetectionScreen() { - VLOG(1) << "Showing HID discovery screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_HID_DETECTION); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_OOBE_HID_DETECTION)); } void WizardController::ShowDeviceDisabledScreen() { - VLOG(1) << "Showing device disabled screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_DEVICE_DISABLED); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_DEVICE_DISABLED)); } void WizardController::ShowEncryptionMigrationScreen() { - VLOG(1) << "Showing encryption migration screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_ENCRYPTION_MIGRATION); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ENCRYPTION_MIGRATION)); } void WizardController::ShowSupervisionTransitionScreen() { - VLOG(1) << "Showing supervision transition screen."; - UpdateStatusAreaVisibilityForScreen( - OobeScreen::SCREEN_SUPERVISION_TRANSITION); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_SUPERVISION_TRANSITION)); } @@ -726,14 +673,10 @@ } void WizardController::ShowMultiDeviceSetupScreen() { - VLOG(1) << "Showing MultiDevice setup screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_MULTIDEVICE_SETUP); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_MULTIDEVICE_SETUP)); } void WizardController::ShowDiscoverScreen() { - VLOG(1) << "Showing Discover screen."; - UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_DISCOVER); SetCurrentScreen(GetScreen(OobeScreen::SCREEN_DISCOVER)); } @@ -1278,7 +1221,6 @@ } void WizardController::StartOOBEUpdate() { - VLOG(1) << "StartOOBEUpdate"; SetCurrentScreenSmooth(GetScreen(OobeScreen::SCREEN_OOBE_UPDATE), true); UpdateScreen::Get(screen_manager())->StartNetworkCheck(); } @@ -1543,7 +1485,6 @@ /////////////////////////////////////////////////////////////////////////////// // WizardController, BaseScreenDelegate overrides: void WizardController::ShowErrorScreen() { - VLOG(1) << "Showing error screen."; SetCurrentScreen(GetScreen(OobeScreen::SCREEN_ERROR_MESSAGE)); }
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h index 8b06156..1e43b3b0 100644 --- a/chrome/browser/chromeos/login/wizard_controller.h +++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -187,9 +187,6 @@ // Shows images login screen. void ShowLoginScreen(const LoginScreenContext& context); - // Shows previous screen. Should only be called if previous screen exists. - void ShowPreviousScreen(); - // Shared actions to be performed on a screen exit. // |exit_code| is the screen specific exit code reported by the screen. void OnScreenExit(OobeScreen screen, int exit_code); @@ -227,15 +224,7 @@ void OnAssistantOptInFlowScreenExit(); void OnMultiDeviceSetupScreenExit(); void OnResetScreenExit(); - void OnHIDDetectionCompleted(); void OnDeviceModificationCanceled(); - void OnFingerprintSetupFinished(); - void OnAppDownloadingFinished(); - void OnDemoSetupFinished(); - void OnDemoSetupCanceled(); - void OnDemoPreferencesContinued(); - void OnDemoPreferencesCanceled(); - void OnSupervisionTransitionFinished(); void OnSupervisionTransitionScreenExit(); void OnOobeFlowFinished();
diff --git a/chrome/browser/devtools/chrome_devtools_session.cc b/chrome/browser/devtools/chrome_devtools_session.cc index 80388aa3..42b6cee6 100644 --- a/chrome/browser/devtools/chrome_devtools_session.cc +++ b/chrome/browser/devtools/chrome_devtools_session.cc
@@ -11,6 +11,7 @@ #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host_client.h" #include "content/public/browser/devtools_manager_delegate.h" +#include "content/public/common/content_switches.h" #if defined(OS_CHROMEOS) #include "chrome/browser/devtools/protocol/window_manager_handler.h" @@ -52,6 +53,12 @@ client_->DispatchProtocolMessage(agent_host_, message->serialize(binary)); } +static bool EnableInternalDevToolsBinaryProtocol() { + static bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableInternalDevToolsBinaryProtocol); + return enabled; +} + void ChromeDevToolsSession::HandleCommand( const std::string& method, const std::string& message, @@ -63,9 +70,14 @@ int call_id; std::string unused; + // We also check for --enable-internal-dev-tools-binary-protocol here, + // because if this flag is set, then content::DevToolsSession will + // send us binary even if the |client_| did not ask for it. + bool binary = + client_->UsesBinaryProtocol() || EnableInternalDevToolsBinaryProtocol(); std::unique_ptr<protocol::DictionaryValue> value = - protocol::DictionaryValue::cast(protocol::StringUtil::parseMessage( - message, client_->UsesBinaryProtocol())); + protocol::DictionaryValue::cast( + protocol::StringUtil::parseMessage(message, binary)); if (!dispatcher_->parseCommand(value.get(), &call_id, &unused)) return; pending_commands_[call_id] = std::move(callback);
diff --git a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc index 943b5b2..73e3fd3b 100644 --- a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc +++ b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
@@ -15,6 +15,7 @@ #include "components/dom_distiller/core/distiller.h" #include "components/dom_distiller/core/dom_distiller_store.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/leveldb_proto/content/proto_database_provider_factory.h" #include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/public/proto_database_provider.h" #include "content/public/browser/browser_context.h" @@ -59,14 +60,19 @@ base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); - auto db = leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB<ArticleEntry>( - background_task_runner); - base::FilePath database_dir( profile->GetPath().Append(FILE_PATH_LITERAL("Articles"))); + leveldb_proto::ProtoDatabaseProvider* db_provider = + leveldb_proto::ProtoDatabaseProviderFactory::GetForBrowserContext( + profile); + + auto db = db_provider->GetDB<ArticleEntry>( + leveldb_proto::ProtoDbType::DOM_DISTILLER_STORE, database_dir, + background_task_runner); + std::unique_ptr<DomDistillerStore> dom_distiller_store( - new DomDistillerStore(std::move(db), database_dir)); + new DomDistillerStore(std::move(db))); std::unique_ptr<DistillerPageFactory> distiller_page_factory( new DistillerPageWebContentsFactory(profile));
diff --git a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc index 331df64..1d2880d 100644 --- a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc +++ b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
@@ -135,7 +135,7 @@ std::unique_ptr<DistillerPageFactory>(distiller_page_factory_), std::unique_ptr<DistilledPagePrefs>(new DistilledPagePrefs( Profile::FromBrowserContext(context)->GetPrefs())))); - fake_db->InitCallback(true); + fake_db->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db->LoadCallback(true); if (expect_distillation_) { // There will only be destillation of an article if the database contains
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index b3c74da..65051af 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc
@@ -52,7 +52,6 @@ const char kTestWebSocketPort[] = "testWebSocketPort"; const char kFtpServerPort[] = "ftpServer.port"; const char kEmbeddedTestServerPort[] = "testServer.port"; -const char kNativeCrxBindingsEnabled[] = "nativeCrxBindingsEnabled"; } // namespace @@ -75,8 +74,6 @@ test_config_->SetInteger(kEmbeddedTestServerPort, embedded_test_server()->port()); } - // TODO(devlin): Remove this. - test_config_->SetBoolean(kNativeCrxBindingsEnabled, true); TestGetConfigFunction::set_test_config_state(test_config_.get()); }
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.cc b/chrome/browser/extensions/extension_uninstall_dialog.cc index 4b79106..c17540d 100644 --- a/chrome/browser/extensions/extension_uninstall_dialog.cc +++ b/chrome/browser/extensions/extension_uninstall_dialog.cc
@@ -98,7 +98,6 @@ extension_ = extension; uninstall_reason_ = reason; - uninstall_source_ = source; if (parent() && parent_window_tracker_->WasNativeWindowClosed()) { OnDialogClosed(CLOSE_ACTION_CANCELED);
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.h b/chrome/browser/extensions/extension_uninstall_dialog.h index e7cf0e7..0612e33 100644 --- a/chrome/browser/extensions/extension_uninstall_dialog.h +++ b/chrome/browser/extensions/extension_uninstall_dialog.h
@@ -119,7 +119,6 @@ return triggering_extension_.get(); } const gfx::ImageSkia& icon() const { return icon_->image_skia(); } gfx::NativeWindow parent() { return parent_; } - UninstallSource uninstall_source() { return uninstall_source_; } private: // Uninstalls the extension. Returns true on success, and populates |error| on @@ -173,8 +172,6 @@ UninstallReason uninstall_reason_ = UNINSTALL_REASON_FOR_TESTING; - UninstallSource uninstall_source_ = UNINSTALL_SOURCE_FOR_TESTING; - ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> observer_; base::ThreadChecker thread_checker_;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 78819f12..91affac 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -721,8 +721,8 @@ }, { "name": "enable-app-data-search", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "jennyz", "kaznacheev" ], + "expiry_milestone": 78 }, { "name": "enable-app-grid-ghost", @@ -740,11 +740,6 @@ "expiry_milestone": 74 }, { - "name": "enable-app-shortcut-search", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-appcontainer", "owners": [ "forshaw", "wfh" ], "expiry_milestone": 76 @@ -760,6 +755,11 @@ "expiry_milestone": 76 }, { + "name": "enable-assistant-launcher-integration", + "owners": [ "croissant-eng" ], + "expiry_milestone": 78 + }, + { "name": "enable-assistant-app-support", "owners": [ "croissant-eng" ], "expiry_milestone": 76 @@ -1503,8 +1503,8 @@ }, { "name": "enable-play-store-search", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "jennyz", "kaznacheev" ], + "expiry_milestone": 78 }, { "name": "enable-previews-android-omnibox-ui",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e4c7bec..6c232da 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3123,11 +3123,6 @@ "Allow App List search box to autocomplete queries for Google searches and " "apps."; -const char kEnableAppShortcutSearchName[] = - "Enable app shortcut search in launcher"; -const char kEnableAppShortcutSearchDescription[] = - "Enables app shortcut search in launcher"; - const char kEnableAppDataSearchName[] = "Enable app data search in launcher"; const char kEnableAppDataSearchDescription[] = "Allow launcher search to access data available through Firebase App " @@ -3139,14 +3134,20 @@ "If audio focus is enabled in Chrome then this will delegate audio focus " "control in Android apps to Chrome."; -const char kEnableAssistantVoiceMatchName[] = "Enable Assistant Voice Match"; -const char kEnableAssistantVoiceMatchDescription[] = - "Enable the Assistant Voice Match feature"; - const char kEnableAssistantAppSupportName[] = "Enable Assistant App Support"; const char kEnableAssistantAppSupportDescription[] = "Enable the Assistant App Support feature"; +const char kEnableAssistantLauncherIntegrationName[] = + "Assistant & Launcher integration"; +const char kEnableAssistantLauncherIntegrationDescription[] = + "Combine Launcher search with the power of Assistant to provide the most " + "useful answer for each query. Requires Assistant to be enabled."; + +const char kEnableAssistantVoiceMatchName[] = "Enable Assistant Voice Match"; +const char kEnableAssistantVoiceMatchDescription[] = + "Enable the Assistant Voice Match feature"; + const char kEnableChromeOsAccountManagerName[] = "Enable Account Manager"; const char kEnableChromeOsAccountManagerDescription[] = "Enables the Chrome OS Account Manager";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6efa6473..5577fe28 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1868,21 +1868,21 @@ extern const char kEnableAppListSearchAutocompleteName[]; extern const char kEnableAppListSearchAutocompleteDescription[]; -extern const char kEnableAppShortcutSearchName[]; -extern const char kEnableAppShortcutSearchDescription[]; - extern const char kEnableAppDataSearchName[]; extern const char kEnableAppDataSearchDescription[]; extern const char kEnableArcUnifiedAudioFocusName[]; extern const char kEnableArcUnifiedAudioFocusDescription[]; -extern const char kEnableAssistantVoiceMatchName[]; -extern const char kEnableAssistantVoiceMatchDescription[]; - extern const char kEnableAssistantAppSupportName[]; extern const char kEnableAssistantAppSupportDescription[]; +extern const char kEnableAssistantLauncherIntegrationName[]; +extern const char kEnableAssistantLauncherIntegrationDescription[]; + +extern const char kEnableAssistantVoiceMatchName[]; +extern const char kEnableAssistantVoiceMatchDescription[]; + extern const char kEnableChromeOsAccountManagerName[]; extern const char kEnableChromeOsAccountManagerDescription[];
diff --git a/chrome/browser/lifetime/termination_notification.cc b/chrome/browser/lifetime/termination_notification.cc index 40d80659..0846a992 100644 --- a/chrome/browser/lifetime/termination_notification.cc +++ b/chrome/browser/lifetime/termination_notification.cc
@@ -13,7 +13,6 @@ #include "content/public/browser/notification_service.h" #if defined(OS_CHROMEOS) -#include "base/system/sys_info.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power_policy_controller.h" #include "chromeos/dbus/session_manager_client.h" @@ -53,7 +52,8 @@ if (chromeos::PowerPolicyController::IsInitialized()) chromeos::PowerPolicyController::Get()->NotifyChromeIsExiting(); - if (base::SysInfo::IsRunningOnChromeOS()) { + if (chromeos::DBusThreadManager::IsInitialized() && + !chromeos::DBusThreadManager::Get()->IsUsingFakes()) { // If we're on a ChromeOS device, reboot if an update has been applied, // or else signal the session manager to log out. chromeos::UpdateEngineClient* update_engine_client =
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc index c0e1bd36..be22091 100644 --- a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc
@@ -14,40 +14,11 @@ } HttpsEngagementPageLoadMetricsObserver::HttpsEngagementPageLoadMetricsObserver( - content::BrowserContext* context) - : currently_in_foreground_(false) { + content::BrowserContext* context) { engagement_service_ = HttpsEngagementServiceFactory::GetForBrowserContext(context); } -page_load_metrics::PageLoadMetricsObserver::ObservePolicy -HttpsEngagementPageLoadMetricsObserver::OnStart( - content::NavigationHandle* navigation_handle, - const GURL& currently_committed_url, - bool started_in_foreground) { - if (started_in_foreground) - OnShown(); - return CONTINUE_OBSERVING; -} - -page_load_metrics::PageLoadMetricsObserver::ObservePolicy -HttpsEngagementPageLoadMetricsObserver::OnHidden( - const page_load_metrics::mojom::PageLoadTiming& timing, - const page_load_metrics::PageLoadExtraInfo& extra_info) { - if (currently_in_foreground_) { - foreground_time_ += base::TimeTicks::Now() - last_time_shown_; - currently_in_foreground_ = false; - } - return CONTINUE_OBSERVING; -} - -page_load_metrics::PageLoadMetricsObserver::ObservePolicy -HttpsEngagementPageLoadMetricsObserver::OnShown() { - last_time_shown_ = base::TimeTicks::Now(); - currently_in_foreground_ = true; - return CONTINUE_OBSERVING; -} - void HttpsEngagementPageLoadMetricsObserver::OnComplete( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& extra_info) { @@ -56,23 +27,23 @@ } // Don't record anything if the user never saw it. - if (!currently_in_foreground_ && foreground_time_.is_zero()) + base::TimeDelta foreground_time = GetDelegate()->GetForegroundDuration(); + if (foreground_time.is_zero()) return; - if (currently_in_foreground_) - OnHidden(timing, extra_info); - if (extra_info.url.SchemeIs(url::kHttpsScheme)) { - if (engagement_service_) - engagement_service_->RecordTimeOnPage(foreground_time_, + if (engagement_service_) { + engagement_service_->RecordTimeOnPage(foreground_time, HttpsEngagementService::HTTPS); + } UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpsEngagementHistogram, - foreground_time_); + foreground_time); } else if (extra_info.url.SchemeIs(url::kHttpScheme)) { - if (engagement_service_) - engagement_service_->RecordTimeOnPage(foreground_time_, + if (engagement_service_) { + engagement_service_->RecordTimeOnPage(foreground_time, HttpsEngagementService::HTTP); + } UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpEngagementHistogram, - foreground_time_); + foreground_time); } }
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h index 3c39f585..904a777 100644 --- a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_ #include "base/macros.h" -#include "base/time/time.h" #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "url/gurl.h" @@ -27,21 +26,11 @@ content::BrowserContext* context); // page_load_metrics::PageLoadMetricsObserver: - ObservePolicy OnStart(content::NavigationHandle* navigation_handle, - const GURL& currently_committed_url, - bool started_in_foreground) override; - ObservePolicy OnHidden( - const page_load_metrics::mojom::PageLoadTiming& timing, - const page_load_metrics::PageLoadExtraInfo& extra_info) override; - ObservePolicy OnShown() override; void OnComplete( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& extra_info) override; private: - bool currently_in_foreground_; - base::TimeDelta foreground_time_; - base::TimeTicks last_time_shown_; HttpsEngagementService* engagement_service_; DISALLOW_COPY_AND_ASSIGN(HttpsEngagementPageLoadMetricsObserver);
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h b/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h index a577ff8..18be6aa 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h
@@ -19,6 +19,10 @@ virtual content::WebContents* GetWebContents() const = 0; virtual base::TimeTicks GetNavigationStart() const = 0; virtual bool DidCommit() const = 0; + + // Get the amount of time the page has been in the foreground. + virtual base::TimeDelta GetForegroundDuration() const = 0; + // TODO(crbug/939403): Consider migrating PageLoadExtraInfo data to this API // and deprecating that struct. };
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc index 65b03af1..0d2a431 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.cc +++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h" @@ -174,6 +175,7 @@ navigation_start_(navigation_handle->NavigationStart()), url_(navigation_handle->GetURL()), start_url_(navigation_handle->GetURL()), + visibility_tracker_(base::DefaultTickClock::GetInstance(), in_foreground), did_commit_(false), page_end_reason_(END_NONE), page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), @@ -307,6 +309,7 @@ background_time_ = base::TimeTicks::Now(); ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); } + visibility_tracker_.OnHidden(); const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, metrics_update_dispatcher_.timing(), info); @@ -323,6 +326,7 @@ ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); } + visibility_tracker_.OnShown(); INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); } @@ -724,4 +728,8 @@ return did_commit_; } +base::TimeDelta PageLoadTracker::GetForegroundDuration() const { + return visibility_tracker_.GetForegroundDuration(); +} + } // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h index fe65252..1d2966d 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.h +++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -14,6 +14,7 @@ #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h" #include "chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h" +#include "chrome/browser/scoped_visibility_tracker.h" #include "chrome/common/page_load_metrics/page_load_timing.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/web_contents_observer.h" @@ -196,6 +197,7 @@ content::WebContents* GetWebContents() const override; base::TimeTicks GetNavigationStart() const override; bool DidCommit() const override; + base::TimeDelta GetForegroundDuration() const override; void Redirect(content::NavigationHandle* navigation_handle); void WillProcessNavigationResponse( @@ -342,6 +344,8 @@ // The start URL for this page load (before redirects). GURL start_url_; + ScopedVisibilityTracker visibility_tracker_; + // Whether this page load committed. bool did_commit_;
diff --git a/chrome/browser/performance_manager/browser_child_process_watcher.cc b/chrome/browser/performance_manager/browser_child_process_watcher.cc index c0a35bf..cb95e85 100644 --- a/chrome/browser/performance_manager/browser_child_process_watcher.cc +++ b/chrome/browser/performance_manager/browser_child_process_watcher.cc
@@ -7,10 +7,12 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "base/process/process.h" #include "base/stl_util.h" +#include "build/build_config.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/performance_manager.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" #include "content/public/browser/child_process_data.h" #include "content/public/browser/child_process_termination_info.h" #include "content/public/common/process_type.h" @@ -18,22 +20,27 @@ namespace performance_manager { BrowserChildProcessWatcher::BrowserChildProcessWatcher() - : browser_node_(PerformanceManager::GetInstance()) { - browser_node_.OnProcessLaunched(base::Process::Current()); + : browser_process_node_( + PerformanceManager::GetInstance()->CreateProcessNode()) { + OnProcessLaunched(base::Process::Current(), browser_process_node_.get()); BrowserChildProcessObserver::Add(this); } BrowserChildProcessWatcher::~BrowserChildProcessWatcher() { BrowserChildProcessObserver::Remove(this); + + PerformanceManager* performance_manager = PerformanceManager::GetInstance(); + performance_manager->DeleteNode(std::move(browser_process_node_)); + for (auto& node : gpu_process_nodes_) + performance_manager->DeleteNode(std::move(node.second)); } void BrowserChildProcessWatcher::BrowserChildProcessLaunchedAndConnected( const content::ChildProcessData& data) { if (data.process_type == content::PROCESS_TYPE_GPU) { - std::unique_ptr<performance_manager::ProcessResourceCoordinator> gpu_node = - std::make_unique<ProcessResourceCoordinator>( - PerformanceManager::GetInstance()); - gpu_node->OnProcessLaunched(data.GetProcess()); + std::unique_ptr<ProcessNodeImpl> gpu_node = + PerformanceManager::GetInstance()->CreateProcessNode(); + OnProcessLaunched(data.GetProcess(), gpu_node.get()); gpu_process_nodes_[data.id] = std::move(gpu_node); } } @@ -41,8 +48,10 @@ void BrowserChildProcessWatcher::BrowserChildProcessHostDisconnected( const content::ChildProcessData& data) { if (data.process_type == content::PROCESS_TYPE_GPU) { - size_t removed = gpu_process_nodes_.erase(data.id); - DCHECK_EQ(1u, removed); + auto it = gpu_process_nodes_.find(data.id); + DCHECK(it != gpu_process_nodes_.end()); + PerformanceManager::GetInstance()->DeleteNode(std::move(it->second)); + gpu_process_nodes_.erase(it); } } @@ -66,8 +75,37 @@ // specifically on crash. if (base::ContainsKey(gpu_process_nodes_, id)) { auto* process_node = gpu_process_nodes_[id].get(); - process_node->SetProcessExitStatus(exit_code); + PerformanceManager* performance_manager = PerformanceManager::GetInstance(); + + performance_manager->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetProcessExitStatus, + base::Unretained(process_node), exit_code)); } } +// static +void BrowserChildProcessWatcher::OnProcessLaunched( + const base::Process& process, + ProcessNodeImpl* process_node) { + // TODO(siggi): Change this to pass the process into the graph node. + const base::ProcessId pid = process.Pid(); + const base::Time launch_time = +#if defined(OS_ANDROID) + // Process::CreationTime() is not available on Android. Since this method + // is called immediately after the process is launched, the process launch + // time can be approximated with the current time. + base::Time::Now(); +#else + process.CreationTime(); +#endif + + PerformanceManager* performance_manager = PerformanceManager::GetInstance(); + performance_manager->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetPID, + base::Unretained(process_node), pid)); + performance_manager->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetLaunchTime, + base::Unretained(process_node), launch_time)); +} + } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/browser_child_process_watcher.h b/chrome/browser/performance_manager/browser_child_process_watcher.h index cdb6a6d..d264315 100644 --- a/chrome/browser/performance_manager/browser_child_process_watcher.h +++ b/chrome/browser/performance_manager/browser_child_process_watcher.h
@@ -10,12 +10,14 @@ #include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/macros.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" +#include "base/process/process.h" #include "content/public/browser/browser_child_process_observer.h" #include "content/public/common/service_manager_connection.h" namespace performance_manager { +class ProcessNodeImpl; + // Responsible for maintaining the process nodes for the browser and the GPU // process. class BrowserChildProcessWatcher : public content::BrowserChildProcessObserver { @@ -38,15 +40,15 @@ void GPUProcessExited(int id, int exit_code); - performance_manager::ProcessResourceCoordinator browser_node_; + static void OnProcessLaunched(const base::Process& process, + ProcessNodeImpl* process_node); + + std::unique_ptr<ProcessNodeImpl> browser_process_node_; // Apparently more than one GPU process can be existent at a time, though // secondaries are very transient. This map keeps track of all GPU processes // by their unique ID from |content::ChildProcessData|. - base::flat_map< - int, - std::unique_ptr<performance_manager::ProcessResourceCoordinator>> - gpu_process_nodes_; + base::flat_map<int, std::unique_ptr<ProcessNodeImpl>> gpu_process_nodes_; DISALLOW_COPY_AND_ASSIGN(BrowserChildProcessWatcher); };
diff --git a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc index 67d78edc..a452293 100644 --- a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc +++ b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc
@@ -7,19 +7,31 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" +#include "chrome/browser/performance_manager/performance_manager.h" #include "chrome/browser/performance_manager/render_process_user_data.h" +#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" namespace { -void BindProcessPerformanceManager( +void BindProcessNode( content::RenderProcessHost* render_process_host, resource_coordinator::mojom::ProcessCoordinationUnitRequest request) { performance_manager::RenderProcessUserData* user_data = performance_manager::RenderProcessUserData::GetForRenderProcessHost( render_process_host); - user_data->process_resource_coordinator()->AddBinding(std::move(request)); + performance_manager::PerformanceManager* performance_manager = + performance_manager::PerformanceManager::GetInstance(); + DCHECK(performance_manager); + + performance_manager->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&performance_manager::ProcessNodeImpl::AddBinding, + base::Unretained(user_data->process_node()), + std::move(request))); } } // namespace @@ -35,7 +47,7 @@ blink::AssociatedInterfaceRegistry* associated_registry, content::RenderProcessHost* render_process_host) { registry->AddInterface( - base::BindRepeating(&BindProcessPerformanceManager, + base::BindRepeating(&BindProcessNode, base::Unretained(render_process_host)), base::SequencedTaskRunnerHandle::Get());
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc index ed3c874d4..89e4ff9 100644 --- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc +++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc
@@ -36,17 +36,6 @@ NOTREACHED(); } -void PageAlmostIdleDecorator::OnFramePropertyChanged( - FrameNodeImpl* frame_node, - resource_coordinator::mojom::PropertyType property_type, - int64_t value) { - // Only the network idle state of a frame is of interest. - if (property_type == - resource_coordinator::mojom::PropertyType::kNetworkAlmostIdle) { - UpdateLoadIdleStateFrame(frame_node); - } -} - void PageAlmostIdleDecorator::OnProcessPropertyChanged( ProcessNodeImpl* process_node, resource_coordinator::mojom::PropertyType property_type, @@ -72,6 +61,11 @@ UpdateLoadIdleStatePage(page_node); } +void PageAlmostIdleDecorator::OnNetworkAlmostIdleChanged( + FrameNodeImpl* frame_node) { + UpdateLoadIdleStateFrame(frame_node); +} + void PageAlmostIdleDecorator::OnIsLoadingChanged(PageNodeImpl* page_node) { UpdateLoadIdleStatePage(page_node); } @@ -227,9 +221,7 @@ // associated with this page's main frame actually being low. In the case // of session restore this is mitigated by having a timeout while waiting for // this signal. - return main_frame_node->GetPropertyOrDefault( - resource_coordinator::mojom::PropertyType::kNetworkAlmostIdle, - 0u) && + return main_frame_node->network_almost_idle() && process_node->GetPropertyOrDefault( resource_coordinator::mojom::PropertyType:: kMainThreadTaskLoadIsLow,
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h index b3213a7..5429d51 100644 --- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h +++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h
@@ -31,16 +31,13 @@ // GraphObserver implementation: bool ShouldObserve(const NodeBase* coordination_unit) override; - void OnFramePropertyChanged( - FrameNodeImpl* frame_node, - resource_coordinator::mojom::PropertyType property_type, - int64_t value) override; void OnProcessPropertyChanged( ProcessNodeImpl* process_node, resource_coordinator::mojom::PropertyType property_type, int64_t value) override; void OnPageEventReceived(PageNodeImpl* page_node, resource_coordinator::mojom::Event event) override; + void OnNetworkAlmostIdleChanged(FrameNodeImpl* frame_node) override; void OnIsLoadingChanged(PageNodeImpl* page_node) override; protected:
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_test_utils.cc b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_test_utils.cc index 4d7c2f7..bcbfe7b 100644 --- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_test_utils.cc +++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_test_utils.cc
@@ -82,10 +82,8 @@ page_node->SetIsLoading(false); FALLTHROUGH; case PageAlmostIdleData::LoadIdleState::kLoadedNotIdling: - if (!frame_node->GetPropertyOrDefault(PropertyType::kNetworkAlmostIdle, - 0)) { + if (!frame_node->network_almost_idle()) frame_node->SetNetworkAlmostIdle(true); - } if (!process_node->GetPropertyOrDefault( PropertyType::kMainThreadTaskLoadIsLow, 0)) { process_node->SetMainThreadTaskLoadIsLow(true);
diff --git a/chrome/browser/performance_manager/frame_resource_coordinator.cc b/chrome/browser/performance_manager/frame_resource_coordinator.cc deleted file mode 100644 index a9d6caea..0000000 --- a/chrome/browser/performance_manager/frame_resource_coordinator.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// 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/performance_manager/frame_resource_coordinator.h" - -#include "base/bind.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" - -namespace performance_manager { - -FrameResourceCoordinator::FrameResourceCoordinator( - PerformanceManager* performance_manager) - : ResourceCoordinatorInterface(), weak_ptr_factory_(this) { - resource_coordinator::CoordinationUnitID new_cu_id( - resource_coordinator::CoordinationUnitType::kFrame, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - ResourceCoordinatorInterface::ConnectToService(performance_manager, - new_cu_id); -} - -FrameResourceCoordinator::~FrameResourceCoordinator() = default; - -void FrameResourceCoordinator::SetProcess( - const ProcessResourceCoordinator& process) { - if (!service_ || !process.service()) - return; - process.service()->GetID( - base::BindOnce(&FrameResourceCoordinator::SetProcessByID, - weak_ptr_factory_.GetWeakPtr())); -} - -void FrameResourceCoordinator::AddChildFrame( - const FrameResourceCoordinator& child) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!service_ || !child.service()) - return; - // We could keep the ID around ourselves, but this hop ensures that the child - // has been created on the service-side. - child.service()->GetID( - base::BindOnce(&FrameResourceCoordinator::AddChildFrameByID, - weak_ptr_factory_.GetWeakPtr())); -} - -void FrameResourceCoordinator::RemoveChildFrame( - const FrameResourceCoordinator& child) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!service_ || !child.service()) - return; - child.service()->GetID( - base::BindOnce(&FrameResourceCoordinator::RemoveChildFrameByID, - weak_ptr_factory_.GetWeakPtr())); -} - -void FrameResourceCoordinator::ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) { - provider->CreateFrameCoordinationUnit(mojo::MakeRequest(&service_), cu_id); -} - -void FrameResourceCoordinator::SetProcessByID( - const resource_coordinator::CoordinationUnitID& process_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (service_) - service_->SetProcess(process_id); -} - -void FrameResourceCoordinator::AddChildFrameByID( - const resource_coordinator::CoordinationUnitID& child_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (service_) - service_->AddChildFrame(child_id); -} - -void FrameResourceCoordinator::RemoveChildFrameByID( - const resource_coordinator::CoordinationUnitID& child_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (service_) - service_->RemoveChildFrame(child_id); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/frame_resource_coordinator.h b/chrome/browser/performance_manager/frame_resource_coordinator.h deleted file mode 100644 index 3176f7d..0000000 --- a/chrome/browser/performance_manager/frame_resource_coordinator.h +++ /dev/null
@@ -1,55 +0,0 @@ -// 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_PERFORMANCE_MANAGER_FRAME_RESOURCE_COORDINATOR_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_FRAME_RESOURCE_COORDINATOR_H_ - -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "chrome/browser/performance_manager/resource_coordinator_interface.h" -#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" - -namespace performance_manager { - -class ProcessResourceCoordinator; - -class FrameResourceCoordinator - : public ResourceCoordinatorInterface< - resource_coordinator::mojom::FrameCoordinationUnitPtr, - resource_coordinator::mojom::FrameCoordinationUnitRequest> { - public: - explicit FrameResourceCoordinator(PerformanceManager* performance_manager); - ~FrameResourceCoordinator() override; - - void SetProcess(const ProcessResourceCoordinator& process); - void AddChildFrame(const FrameResourceCoordinator& child); - void RemoveChildFrame(const FrameResourceCoordinator& child); - - // Closes the connection to the service. - void reset() { service_.reset(); } - - private: - void ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) override; - - void SetProcessByID( - const resource_coordinator::CoordinationUnitID& process_id); - void AddChildFrameByID( - const resource_coordinator::CoordinationUnitID& child_id); - void RemoveChildFrameByID( - const resource_coordinator::CoordinationUnitID& child_id); - - THREAD_CHECKER(thread_checker_); - - // The WeakPtrFactory should come last so the weak ptrs are invalidated - // before the rest of the member variables. - base::WeakPtrFactory<FrameResourceCoordinator> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(FrameResourceCoordinator); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_FRAME_RESOURCE_COORDINATOR_H_
diff --git a/chrome/browser/performance_manager/graph/README.md b/chrome/browser/performance_manager/graph/README.md new file mode 100644 index 0000000..774c9fc --- /dev/null +++ b/chrome/browser/performance_manager/graph/README.md
@@ -0,0 +1,17 @@ +# Threading Model + +The [graph](graph.h) can only be accessed from a single sequence. + +Nodes can be created on any sequence, but as soon as they're added to a graph, +they can only be used on the graph's sequence, with the exception of the id +accessor. + +# Node Lifetime + +With the exception of the system node, which is a singleton, the Graph does not +own nodes. The user of the graph is responsible for maintaining node ownership. +Any node that has been added to the graph, must be removed from the graph +with Graph::DestroyNode (TODO(siggi): rename to RemoveNode) before it's +deleted. +All nodes must be removed from the graph before the graph is destroyed. +
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.cc b/chrome/browser/performance_manager/graph/frame_node_impl.cc index 1134a08..c71308d 100644 --- a/chrome/browser/performance_manager/graph/frame_node_impl.cc +++ b/chrome/browser/performance_manager/graph/frame_node_impl.cc
@@ -20,13 +20,16 @@ for (size_t i = 0; i < base::size(intervention_policy_); ++i) intervention_policy_[i] = resource_coordinator::mojom::InterventionPolicy::kUnknown; + + DETACH_FROM_SEQUENCE(sequence_checker_); } FrameNodeImpl::~FrameNodeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (parent_frame_coordination_unit_) parent_frame_coordination_unit_->RemoveChildFrame(this); if (page_coordination_unit_) - page_coordination_unit_->RemoveFrame(this); + page_coordination_unit_->RemoveFrameImpl(this); if (process_coordination_unit_) process_coordination_unit_->RemoveFrame(this); for (auto* child_frame : child_frame_coordination_units_) @@ -56,7 +59,7 @@ DCHECK(false) << "Cyclic reference in frame coordination units detected!"; return; } - if (AddChildFrame(frame_cu)) { + if (AddChildFrameImpl(frame_cu)) { frame_cu->AddParentFrame(this); } } @@ -73,9 +76,10 @@ } } -void FrameNodeImpl::SetNetworkAlmostIdle(bool idle) { - SetProperty(resource_coordinator::mojom::PropertyType::kNetworkAlmostIdle, - idle); +void FrameNodeImpl::SetNetworkAlmostIdle(bool network_almost_idle) { + SetPropertyAndNotifyObservers(&GraphObserver::OnNetworkAlmostIdleChanged, + network_almost_idle, this, + &network_almost_idle_); } void FrameNodeImpl::SetLifecycleState( @@ -228,7 +232,7 @@ parent_frame_coordination_unit_ = parent_frame_cu; } -bool FrameNodeImpl::AddChildFrame(FrameNodeImpl* child_frame_cu) { +bool FrameNodeImpl::AddChildFrameImpl(FrameNodeImpl* child_frame_cu) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return child_frame_coordination_units_.count(child_frame_cu) ? false
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.h b/chrome/browser/performance_manager/graph/frame_node_impl.h index 28c1add2..2fb4a432 100644 --- a/chrome/browser/performance_manager/graph/frame_node_impl.h +++ b/chrome/browser/performance_manager/graph/frame_node_impl.h
@@ -58,6 +58,7 @@ return lifecycle_state_; } bool has_nonempty_beforeunload() const { return has_nonempty_beforeunload_; } + bool network_almost_idle() const { return network_almost_idle_; } // Returns true if all intervention policies have been set for this frame. bool AreAllInterventionPoliciesSet() const; @@ -89,7 +90,7 @@ // PageNodeImpl and ProcessNodeImpl respectively to // manipulate their relationship. void AddParentFrame(FrameNodeImpl* parent_frame_cu); - bool AddChildFrame(FrameNodeImpl* child_frame_cu); + bool AddChildFrameImpl(FrameNodeImpl* child_frame_cu); void RemoveParentFrame(FrameNodeImpl* parent_frame_cu); bool RemoveChildFrame(FrameNodeImpl* child_frame_cu); void AddPageNode(PageNodeImpl* page_cu); @@ -105,6 +106,9 @@ resource_coordinator::mojom::LifecycleState lifecycle_state_ = resource_coordinator::mojom::LifecycleState::kRunning; bool has_nonempty_beforeunload_ = false; + // Network is considered almost idle when there are no more than 2 network + // connections. + bool network_almost_idle_ = false; // Intervention policy for this frame. These are communicated from the // renderer process and are controlled by origin trials.
diff --git a/chrome/browser/performance_manager/graph/graph.cc b/chrome/browser/performance_manager/graph/graph.cc index 3af6b38b..cbc90ad 100644 --- a/chrome/browser/performance_manager/graph/graph.cc +++ b/chrome/browser/performance_manager/graph/graph.cc
@@ -10,15 +10,12 @@ #include "base/bind_helpers.h" #include "base/macros.h" #include "chrome/browser/performance_manager/graph/frame_node_impl.h" -#include "chrome/browser/performance_manager/graph/graph_node_provider_impl.h" #include "chrome/browser/performance_manager/graph/node_base.h" #include "chrome/browser/performance_manager/graph/page_node_impl.h" #include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/graph/system_node_impl.h" #include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h" #include "services/resource_coordinator/public/cpp/coordination_unit_types.h" -#include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" namespace ukm { class UkmEntryBuilder; @@ -26,10 +23,7 @@ namespace performance_manager { -Graph::Graph() - : system_coordination_unit_id_( - resource_coordinator::CoordinationUnitType::kSystem, - resource_coordinator::CoordinationUnitID::RANDOM_ID) {} +Graph::Graph() = default; Graph::~Graph() { // Because the graph has ownership of the CUs, and because the process CUs @@ -47,14 +41,6 @@ DCHECK_EQ(0u, processes_by_pid_.size()); } -void Graph::OnStart(service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&>* registry) { - // Create the singleton CoordinationUnitProvider. - provider_ = std::make_unique<GraphNodeProviderImpl>(this); - registry->AddInterface(base::BindRepeating( - &GraphNodeProviderImpl::Bind, base::Unretained(provider_.get()))); -} - void Graph::RegisterObserver(std::unique_ptr<GraphObserver> observer) { observer->set_coordination_unit_graph(this); observers_.push_back(std::move(observer)); @@ -73,28 +59,17 @@ coordination_unit->BeforeDestroyed(); } -FrameNodeImpl* Graph::CreateFrameNode( - const resource_coordinator::CoordinationUnitID& id) { - return FrameNodeImpl::Create(id, this); -} - -PageNodeImpl* Graph::CreatePageNode( - const resource_coordinator::CoordinationUnitID& id) { - return PageNodeImpl::Create(id, this); -} - -ProcessNodeImpl* Graph::CreateProcessNode( - const resource_coordinator::CoordinationUnitID& id) { - return ProcessNodeImpl::Create(id, this); -} - SystemNodeImpl* Graph::FindOrCreateSystemNode() { - NodeBase* system_cu = GetNodeByID(system_coordination_unit_id_); - if (system_cu) - return SystemNodeImpl::FromNodeBase(system_cu); + if (!system_node_) { + // Create the singleton SystemCU instance. Ownership is taken by the graph. + resource_coordinator::CoordinationUnitID id( + resource_coordinator::CoordinationUnitType::kSystem, + resource_coordinator::CoordinationUnitID::RANDOM_ID); + system_node_ = std::make_unique<SystemNodeImpl>(id, this); + AddNewNode(system_node_.get()); + } - // Create the singleton SystemCU instance. Ownership is taken by the graph. - return SystemNodeImpl::Create(system_coordination_unit_id_, this); + return system_node_.get(); } NodeBase* Graph::GetNodeByID( @@ -102,7 +77,7 @@ const auto& it = coordination_units_.find(cu_id); if (it == coordination_units_.end()) return nullptr; - return it->second.get(); + return it->second; } ProcessNodeImpl* Graph::GetProcessNodeByPid(base::ProcessId pid) { @@ -142,14 +117,12 @@ return count; } -NodeBase* Graph::AddNewNode(std::unique_ptr<NodeBase> new_cu) { - auto it = coordination_units_.emplace(new_cu->id(), std::move(new_cu)); +void Graph::AddNewNode(NodeBase* new_cu) { + auto it = coordination_units_.emplace(new_cu->id(), new_cu); DCHECK(it.second); // Inserted successfully - NodeBase* added_cu = it.first->second.get(); + NodeBase* added_cu = it.first->second; OnNodeCreated(added_cu); - - return added_cu; } void Graph::DestroyNode(NodeBase* cu) { @@ -188,7 +161,7 @@ std::vector<CUType*> ret; for (const auto& el : coordination_units_) { if (el.first.type == type) - ret.push_back(CUType::FromNodeBase(el.second.get())); + ret.push_back(CUType::FromNodeBase(el.second)); } return ret; }
diff --git a/chrome/browser/performance_manager/graph/graph.h b/chrome/browser/performance_manager/graph/graph.h index 4cacb7d7..18f315ba 100644 --- a/chrome/browser/performance_manager/graph/graph.h +++ b/chrome/browser/performance_manager/graph/graph.h
@@ -21,17 +21,10 @@ #include "services/resource_coordinator/public/cpp/coordination_unit_id.h" #include "services/resource_coordinator/public/cpp/coordination_unit_types.h" -namespace service_manager { -template <typename... BinderArgs> -class BinderRegistryWithArgs; -struct BindSourceInfo; -} // namespace service_manager - namespace performance_manager { class NodeBase; class GraphObserver; -class GraphNodeProviderImpl; class FrameNodeImpl; class PageNodeImpl; class ProcessNodeImpl; @@ -51,20 +44,11 @@ } ukm::UkmRecorder* ukm_recorder() const { return ukm_recorder_; } - void OnStart(service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&>* registry); void RegisterObserver(std::unique_ptr<GraphObserver> observer); void OnNodeCreated(NodeBase* coordination_unit); void OnBeforeNodeDestroyed(NodeBase* coordination_unit); - FrameNodeImpl* CreateFrameNode( - const resource_coordinator::CoordinationUnitID& id); - PageNodeImpl* CreatePageNode( - const resource_coordinator::CoordinationUnitID& id); - ProcessNodeImpl* CreateProcessNode( - const resource_coordinator::CoordinationUnitID& id); SystemNodeImpl* FindOrCreateSystemNode(); - std::vector<ProcessNodeImpl*> GetAllProcessNodes(); std::vector<FrameNodeImpl*> GetAllFrameNodes(); std::vector<PageNodeImpl*> GetAllPageNodes(); @@ -77,6 +61,10 @@ return observers_; } + // Lifetime management functions for node owners. + void AddNewNode(NodeBase* new_cu); + void DestroyNode(NodeBase* cu); + // A |key| of nullptr counts all instances associated with the |node|. A // |node| of null counts all instances associated with the |key|. If both are // null then the entire map size is provided. @@ -84,15 +72,10 @@ const void* key) const; private: - using CUIDMap = std::unordered_map<resource_coordinator::CoordinationUnitID, - std::unique_ptr<NodeBase>>; + using CUIDMap = + std::unordered_map<resource_coordinator::CoordinationUnitID, NodeBase*>; using ProcessByPidMap = std::unordered_map<base::ProcessId, ProcessNodeImpl*>; - // Lifetime management functions for NodeBase. - friend class NodeBase; - NodeBase* AddNewNode(std::unique_ptr<NodeBase> new_cu); - void DestroyNode(NodeBase* cu); - // Process PID map for use by ProcessNodeImpl. friend class ProcessNodeImpl; void BeforeProcessPidChange(ProcessNodeImpl* process, @@ -101,12 +84,11 @@ template <typename CUType> std::vector<CUType*> GetAllNodesOfType(); - resource_coordinator::CoordinationUnitID system_coordination_unit_id_; + std::unique_ptr<SystemNodeImpl> system_node_; CUIDMap coordination_units_; ProcessByPidMap processes_by_pid_; std::vector<std::unique_ptr<GraphObserver>> observers_; ukm::UkmRecorder* ukm_recorder_ = nullptr; - std::unique_ptr<GraphNodeProviderImpl> provider_; // User data storage for the graph. friend class NodeAttachedData;
diff --git a/chrome/browser/performance_manager/graph/graph_node_provider_impl.cc b/chrome/browser/performance_manager/graph/graph_node_provider_impl.cc deleted file mode 100644 index b408024..0000000 --- a/chrome/browser/performance_manager/graph/graph_node_provider_impl.cc +++ /dev/null
@@ -1,81 +0,0 @@ -// 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/performance_manager/graph/graph_node_provider_impl.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/macros.h" -#include "chrome/browser/performance_manager/graph/frame_node_impl.h" -#include "chrome/browser/performance_manager/graph/page_node_impl.h" -#include "chrome/browser/performance_manager/graph/process_node_impl.h" -#include "chrome/browser/performance_manager/graph/system_node_impl.h" -#include "services/service_manager/public/cpp/bind_source_info.h" - -namespace performance_manager { - -GraphNodeProviderImpl::GraphNodeProviderImpl(Graph* coordination_unit_graph) - : coordination_unit_graph_(coordination_unit_graph) {} - -GraphNodeProviderImpl::~GraphNodeProviderImpl() = default; - -void GraphNodeProviderImpl::OnConnectionError(NodeBase* coordination_unit) { - coordination_unit->Destruct(); -} - -void GraphNodeProviderImpl::CreateFrameCoordinationUnit( - resource_coordinator::mojom::FrameCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) { - FrameNodeImpl* frame_cu = coordination_unit_graph_->CreateFrameNode(id); - - frame_cu->Bind(std::move(request)); - auto& frame_cu_binding = frame_cu->binding(); - - frame_cu_binding.set_connection_error_handler( - base::BindOnce(&GraphNodeProviderImpl::OnConnectionError, - base::Unretained(this), frame_cu)); -} - -void GraphNodeProviderImpl::CreatePageCoordinationUnit( - resource_coordinator::mojom::PageCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) { - PageNodeImpl* page_cu = coordination_unit_graph_->CreatePageNode(id); - - page_cu->Bind(std::move(request)); - auto& page_cu_binding = page_cu->binding(); - - page_cu_binding.set_connection_error_handler( - base::BindOnce(&GraphNodeProviderImpl::OnConnectionError, - base::Unretained(this), page_cu)); -} - -void GraphNodeProviderImpl::CreateProcessCoordinationUnit( - resource_coordinator::mojom::ProcessCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) { - ProcessNodeImpl* process_cu = coordination_unit_graph_->CreateProcessNode(id); - - process_cu->Bind(std::move(request)); - auto& process_cu_binding = process_cu->binding(); - - process_cu_binding.set_connection_error_handler( - base::BindOnce(&GraphNodeProviderImpl::OnConnectionError, - base::Unretained(this), process_cu)); -} - -void GraphNodeProviderImpl::GetSystemCoordinationUnit( - resource_coordinator::mojom::SystemCoordinationUnitRequest request) { - // Simply fetch the existing SystemCU and add an additional binding to it. - coordination_unit_graph_->FindOrCreateSystemNode()->AddBinding( - std::move(request)); -} - -void GraphNodeProviderImpl::Bind( - resource_coordinator::mojom::CoordinationUnitProviderRequest request, - const service_manager::BindSourceInfo& source_info) { - bindings_.AddBinding(this, std::move(request)); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/graph_node_provider_impl.h b/chrome/browser/performance_manager/graph/graph_node_provider_impl.h deleted file mode 100644 index 19739ea..0000000 --- a/chrome/browser/performance_manager/graph/graph_node_provider_impl.h +++ /dev/null
@@ -1,58 +0,0 @@ -// 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_PERFORMANCE_MANAGER_GRAPH_GRAPH_NODE_PROVIDER_IMPL_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_NODE_PROVIDER_IMPL_H_ - -#include <memory> -#include <vector> - -#include "chrome/browser/performance_manager/graph/graph.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h" - -namespace service_manager { -struct BindSourceInfo; -} // namespace service_manager - -namespace performance_manager { - -class GraphNodeProviderImpl - : public resource_coordinator::mojom::CoordinationUnitProvider { - public: - explicit GraphNodeProviderImpl(Graph* coordination_unit_graph); - ~GraphNodeProviderImpl() override; - - void Bind( - resource_coordinator::mojom::CoordinationUnitProviderRequest request, - const service_manager::BindSourceInfo& source_info); - - void OnConnectionError(NodeBase* coordination_unit); - - // Overridden from resource_coordinator::mojom::CoordinationUnitProvider: - void CreateFrameCoordinationUnit( - resource_coordinator::mojom::FrameCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) override; - void CreatePageCoordinationUnit( - resource_coordinator::mojom::PageCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) override; - void CreateProcessCoordinationUnit( - resource_coordinator::mojom::ProcessCoordinationUnitRequest request, - const resource_coordinator::CoordinationUnitID& id) override; - void GetSystemCoordinationUnit( - resource_coordinator::mojom::SystemCoordinationUnitRequest request) - override; - - private: - Graph* coordination_unit_graph_; - mojo::BindingSet<resource_coordinator::mojom::CoordinationUnitProvider> - bindings_; - - DISALLOW_COPY_AND_ASSIGN(GraphNodeProviderImpl); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_NODE_PROVIDER_IMPL_H_
diff --git a/chrome/browser/performance_manager/graph/graph_test_harness.cc b/chrome/browser/performance_manager/graph/graph_test_harness.cc index 830260c3..3161af5 100644 --- a/chrome/browser/performance_manager/graph/graph_test_harness.cc +++ b/chrome/browser/performance_manager/graph/graph_test_harness.cc
@@ -11,8 +11,7 @@ GraphTestHarness::GraphTestHarness() : task_env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME, - base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED), - provider_(&coordination_unit_graph_) {} + base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {} GraphTestHarness::~GraphTestHarness() = default;
diff --git a/chrome/browser/performance_manager/graph/graph_test_harness.h b/chrome/browser/performance_manager/graph/graph_test_harness.h index 24cd621..a1b11e8 100644 --- a/chrome/browser/performance_manager/graph/graph_test_harness.h +++ b/chrome/browser/performance_manager/graph/graph_test_harness.h
@@ -6,12 +6,16 @@ #define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_GRAPH_TEST_HARNESS_H_ #include <stdint.h> +#include <memory> #include <string> +#include <utility> #include "base/test/scoped_task_environment.h" +#include "chrome/browser/performance_manager/graph/frame_node_impl.h" #include "chrome/browser/performance_manager/graph/graph.h" -#include "chrome/browser/performance_manager/graph/graph_node_provider_impl.h" #include "chrome/browser/performance_manager/graph/node_base.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/graph/system_node_impl.h" #include "testing/gtest/include/gtest/gtest.h" @@ -26,30 +30,65 @@ template <class NodeClass> class TestNodeWrapper { public: + static TestNodeWrapper<NodeClass> Create( + const resource_coordinator::CoordinationUnitID& cu_id, + Graph* graph) { + std::unique_ptr<NodeClass> node = std::make_unique<NodeClass>(cu_id, graph); + graph->AddNewNode(node.get()); + return TestNodeWrapper<NodeClass>(std::move(node)); + } static TestNodeWrapper<NodeClass> Create(Graph* graph) { resource_coordinator::CoordinationUnitID cu_id( NodeClass::Type(), resource_coordinator::CoordinationUnitID::RANDOM_ID); - return TestNodeWrapper<NodeClass>(NodeClass::Create(cu_id, graph)); + return Create(cu_id, graph); } - explicit TestNodeWrapper(NodeClass* impl) : impl_(impl) { DCHECK(impl); } + explicit TestNodeWrapper(std::unique_ptr<NodeClass> impl) + : impl_(std::move(impl)) { + DCHECK(impl_.get()); + } ~TestNodeWrapper() { reset(); } - NodeClass* operator->() const { return impl_; } + NodeClass* operator->() const { return impl_.get(); } - TestNodeWrapper(TestNodeWrapper&& other) : impl_(other.impl_) {} + TestNodeWrapper(TestNodeWrapper&& other) : impl_(std::move(other.impl_)) {} - NodeClass* get() const { return impl_; } + NodeClass* get() const { return impl_.get(); } void reset() { if (impl_) { - impl_->Destruct(); - impl_ = nullptr; + impl_->graph()->DestroyNode(impl_.get()); + impl_.reset(); } } private: - NodeClass* impl_; + std::unique_ptr<NodeClass> impl_; + + DISALLOW_COPY_AND_ASSIGN(TestNodeWrapper); +}; + +// This specialization is necessary because the graph has ownership of the +// system node as it's a singleton. For the other node types the test wrapper +// manages the node lifetime. +template <> +class TestNodeWrapper<SystemNodeImpl> { + public: + static TestNodeWrapper<SystemNodeImpl> Create(Graph* graph) { + return TestNodeWrapper<SystemNodeImpl>(graph->FindOrCreateSystemNode()); + } + + explicit TestNodeWrapper(SystemNodeImpl* impl) : impl_(impl) {} + TestNodeWrapper(TestNodeWrapper&& other) : impl_(other.impl_) {} + ~TestNodeWrapper() { reset(); } + + SystemNodeImpl* operator->() const { return impl_; } + SystemNodeImpl* get() const { return impl_; } + + void reset() { impl_ = nullptr; } + + private: + SystemNodeImpl* impl_; DISALLOW_COPY_AND_ASSIGN(TestNodeWrapper); }; @@ -62,8 +101,7 @@ template <class NodeClass> TestNodeWrapper<NodeClass> CreateCoordinationUnit( resource_coordinator::CoordinationUnitID cu_id) { - return TestNodeWrapper<NodeClass>( - NodeClass::Create(cu_id, coordination_unit_graph())); + return TestNodeWrapper<NodeClass>::Create(cu_id, coordination_unit_graph()); } template <class NodeClass> @@ -84,12 +122,10 @@ protected: base::test::ScopedTaskEnvironment& task_env() { return task_env_; } Graph* coordination_unit_graph() { return &coordination_unit_graph_; } - GraphNodeProviderImpl* provider() { return &provider_; } private: base::test::ScopedTaskEnvironment task_env_; Graph coordination_unit_graph_; - GraphNodeProviderImpl provider_; }; } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/graph_unittest.cc b/chrome/browser/performance_manager/graph/graph_unittest.cc index 4d40133..0eee4bf 100644 --- a/chrome/browser/performance_manager/graph/graph_unittest.cc +++ b/chrome/browser/performance_manager/graph/graph_unittest.cc
@@ -5,37 +5,13 @@ #include "chrome/browser/performance_manager/graph/graph.h" #include "chrome/browser/performance_manager/graph/frame_node_impl.h" +#include "chrome/browser/performance_manager/graph/graph_test_harness.h" #include "chrome/browser/performance_manager/graph/mock_graphs.h" #include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/graph/system_node_impl.h" #include "testing/gtest/include/gtest/gtest.h" namespace performance_manager { -namespace { - -ProcessNodeImpl* CreateProcessNode(Graph* graph) { - return graph->CreateProcessNode(resource_coordinator::CoordinationUnitID( - resource_coordinator::CoordinationUnitType::kProcess, - resource_coordinator::CoordinationUnitID::RANDOM_ID)); -} - -} // namespace - -TEST(GraphTest, DestructionWhileCUSOutstanding) { - std::unique_ptr<Graph> graph(new Graph()); - - for (size_t i = 0; i < 10; ++i) { - ProcessNodeImpl* process = CreateProcessNode(graph.get()); - EXPECT_NE(nullptr, process); - - process->SetPID(i + 100); - } - - EXPECT_NE(nullptr, graph->FindOrCreateSystemNode()); - - // This should destroy all the CUs without incident. - graph.reset(); -} TEST(GraphTest, FindOrCreateSystemNode) { Graph graph; @@ -44,27 +20,22 @@ // A second request should return the same instance. EXPECT_EQ(system_cu, graph.FindOrCreateSystemNode()); - - // Destructing the system CU should be allowed. - system_cu->Destruct(); - - system_cu = graph.FindOrCreateSystemNode(); - EXPECT_NE(nullptr, system_cu); } TEST(GraphTest, GetProcessNodeByPid) { Graph graph; - ProcessNodeImpl* process = CreateProcessNode(&graph); + TestNodeWrapper<ProcessNodeImpl> process = + TestNodeWrapper<ProcessNodeImpl>::Create(&graph); EXPECT_EQ(base::kNullProcessId, process->process_id()); static constexpr base::ProcessId kPid = 10; EXPECT_EQ(nullptr, graph.GetProcessNodeByPid(kPid)); process->SetPID(kPid); - EXPECT_EQ(process, graph.GetProcessNodeByPid(kPid)); + EXPECT_EQ(process.get(), graph.GetProcessNodeByPid(kPid)); - process->Destruct(); + process.reset(); EXPECT_EQ(nullptr, graph.GetProcessNodeByPid(12)); } @@ -77,20 +48,22 @@ static constexpr base::ProcessId kPid = 10; - ProcessNodeImpl* process1 = CreateProcessNode(&graph); - ProcessNodeImpl* process2 = CreateProcessNode(&graph); + TestNodeWrapper<ProcessNodeImpl> process1 = + TestNodeWrapper<ProcessNodeImpl>::Create(&graph); + TestNodeWrapper<ProcessNodeImpl> process2 = + TestNodeWrapper<ProcessNodeImpl>::Create(&graph); process1->SetPID(kPid); - EXPECT_EQ(process1, graph.GetProcessNodeByPid(kPid)); + EXPECT_EQ(process1.get(), graph.GetProcessNodeByPid(kPid)); // The second registration for the same PID should override the first one. process2->SetPID(kPid); - EXPECT_EQ(process2, graph.GetProcessNodeByPid(kPid)); + EXPECT_EQ(process2.get(), graph.GetProcessNodeByPid(kPid)); // The destruction of the first process CU shouldn't clear the PID // registration. - process1->Destruct(); - EXPECT_EQ(process2, graph.GetProcessNodeByPid(kPid)); + process1.reset(); + EXPECT_EQ(process2.get(), graph.GetProcessNodeByPid(kPid)); } TEST(GraphTest, GetAllCUsByType) {
diff --git a/chrome/browser/performance_manager/graph/node_base.cc b/chrome/browser/performance_manager/graph/node_base.cc index a6ad917..f8a69662f 100644 --- a/chrome/browser/performance_manager/graph/node_base.cc +++ b/chrome/browser/performance_manager/graph/node_base.cc
@@ -15,20 +15,12 @@ NodeBase::NodeBase(const resource_coordinator::CoordinationUnitID& id, Graph* graph) : graph_(graph), id_(id.type, id.id) { - // TODO(siggi): The constructor needs to detach from the sequence once the - // lifetime changes are done. - // DETACH_FROM_SEQUENCE(sequence_checker_); } NodeBase::~NodeBase() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -void NodeBase::Destruct() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - graph_->DestroyNode(this); -} - void NodeBase::BeforeDestroyed() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto& observer : observers_) @@ -98,10 +90,4 @@ OnPropertyChanged(property_type, value); } -// static -NodeBase* NodeBase::PassOwnershipToGraph(std::unique_ptr<NodeBase> new_cu) { - auto *graph = new_cu->graph(); - return graph->AddNewNode(std::move(new_cu)); -} - } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/node_base.h b/chrome/browser/performance_manager/graph/node_base.h index 65ba5ccd..819c97d 100644 --- a/chrome/browser/performance_manager/graph/node_base.h +++ b/chrome/browser/performance_manager/graph/node_base.h
@@ -33,7 +33,6 @@ NodeBase(const resource_coordinator::CoordinationUnitID& id, Graph* graph); virtual ~NodeBase(); - void Destruct(); void BeforeDestroyed(); void AddObserver(GraphObserver* observer); void RemoveObserver(GraphObserver* observer); @@ -44,6 +43,7 @@ const resource_coordinator::mojom::PropertyType property_type, int64_t default_value) const; + // May be called on any thread. const resource_coordinator::CoordinationUnitID& id() const { return id_; } Graph* graph() const { return graph_; } @@ -61,6 +61,22 @@ } protected: + // Helper function for setting a property, and notifying observers if the + // value has changed. + template <typename NodeType, + typename PropertyType, + typename NotifyFunctionPtr> + void SetPropertyAndNotifyObservers(NotifyFunctionPtr notify_function_ptr, + const PropertyType& value, + NodeType* node, + PropertyType* property) { + if (*property == value) + return; + *property = value; + for (auto& observer : observers_) + ((observer).*(notify_function_ptr))(node); + } + virtual void OnEventReceived(resource_coordinator::mojom::Event event); virtual void OnPropertyChanged( resource_coordinator::mojom::PropertyType property_type, @@ -70,9 +86,6 @@ void SetProperty(resource_coordinator::mojom::PropertyType property_type, int64_t value); - // Passes the ownership of the newly created |new_cu| to its graph. - static NodeBase* PassOwnershipToGraph(std::unique_ptr<NodeBase> new_cu); - Graph* const graph_; const resource_coordinator::CoordinationUnitID id_; @@ -90,15 +103,6 @@ class MojoRequestClass> class CoordinationUnitInterface : public NodeBase, public MojoInterfaceClass { public: - static CoordinationUnitClass* Create( - const resource_coordinator::CoordinationUnitID& id, - Graph* graph) { - std::unique_ptr<CoordinationUnitClass> new_cu = - std::make_unique<CoordinationUnitClass>(id, graph); - return static_cast<CoordinationUnitClass*>( - PassOwnershipToGraph(std::move(new_cu))); - } - static const CoordinationUnitClass* FromNodeBase(const NodeBase* cu) { DCHECK(cu->id().type == CoordinationUnitClass::Type()); return static_cast<const CoordinationUnitClass*>(cu);
diff --git a/chrome/browser/performance_manager/graph/node_base_unittest.cc b/chrome/browser/performance_manager/graph/node_base_unittest.cc index 851b797e..555bcca 100644 --- a/chrome/browser/performance_manager/graph/node_base_unittest.cc +++ b/chrome/browser/performance_manager/graph/node_base_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "chrome/browser/performance_manager/graph/node_base.h" -#include "chrome/browser/performance_manager/graph/graph_node_provider_impl.h" #include "chrome/browser/performance_manager/graph/graph_test_harness.h" #include "chrome/browser/performance_manager/graph/mock_graphs.h" #include "chrome/browser/performance_manager/graph/page_node_impl.h"
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.cc b/chrome/browser/performance_manager/graph/page_node_impl.cc index e569af4..4110968 100644 --- a/chrome/browser/performance_manager/graph/page_node_impl.cc +++ b/chrome/browser/performance_manager/graph/page_node_impl.cc
@@ -35,9 +35,12 @@ : CoordinationUnitInterface(id, graph), visibility_change_time_(ResourceCoordinatorClock::NowTicks()) { InvalidateAllInterventionPolicies(); + + DETACH_FROM_SEQUENCE(sequence_checker_); } PageNodeImpl::~PageNodeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto* child_frame : frame_coordination_units_) child_frame->RemovePageNode(this); } @@ -49,7 +52,7 @@ FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id); if (!frame_cu) return; - if (AddFrame(frame_cu)) + if (AddFrameImpl(frame_cu)) frame_cu->AddPageNode(this); } @@ -60,24 +63,18 @@ FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id); if (!frame_cu) return; - if (RemoveFrame(frame_cu)) + if (RemoveFrameImpl(frame_cu)) frame_cu->RemovePageNode(this); } void PageNodeImpl::SetIsLoading(bool is_loading) { - if (is_loading_ == is_loading) - return; - is_loading_ = is_loading; - for (auto& observer : observers()) - observer.OnIsLoadingChanged(this); + SetPropertyAndNotifyObservers(&GraphObserver::OnIsLoadingChanged, is_loading, + this, &is_loading_); } void PageNodeImpl::SetVisibility(bool is_visible) { - if (is_visible_ == is_visible) - return; - is_visible_ = is_visible; - for (auto& observer : observers()) - observer.OnIsVisibleChanged(this); + SetPropertyAndNotifyObservers(&GraphObserver::OnIsVisibleChanged, is_visible, + this, &is_visible_); // The change time needs to be updated after observers are notified, as they // use this to determine time passed since the *previous* visibility state // change. They can infer the current state change time themselves via @@ -267,7 +264,7 @@ observer.OnPagePropertyChanged(this, property_type, value); } -bool PageNodeImpl::AddFrame(FrameNodeImpl* frame_cu) { +bool PageNodeImpl::AddFrameImpl(FrameNodeImpl* frame_cu) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const bool inserted = frame_coordination_units_.insert(frame_cu).second; if (inserted) { @@ -281,7 +278,7 @@ return inserted; } -bool PageNodeImpl::RemoveFrame(FrameNodeImpl* frame_cu) { +bool PageNodeImpl::RemoveFrameImpl(FrameNodeImpl* frame_cu) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); bool removed = frame_coordination_units_.erase(frame_cu) > 0; if (removed) {
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.h b/chrome/browser/performance_manager/graph/page_node_impl.h index 7a3075a7..0963a1d3 100644 --- a/chrome/browser/performance_manager/graph/page_node_impl.h +++ b/chrome/browser/performance_manager/graph/page_node_impl.h
@@ -143,8 +143,8 @@ resource_coordinator::mojom::PropertyType property_type, int64_t value) override; - bool AddFrame(FrameNodeImpl* frame_cu); - bool RemoveFrame(FrameNodeImpl* frame_cu); + bool AddFrameImpl(FrameNodeImpl* frame_cu); + bool RemoveFrameImpl(FrameNodeImpl* frame_cu); // This is called whenever |num_frozen_frames_| changes, or whenever // |frame_coordination_units_.size()| changes. It is used to synthesize the
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.cc b/chrome/browser/performance_manager/graph/process_node_impl.cc index 30626ca66..b6b75d6 100644 --- a/chrome/browser/performance_manager/graph/process_node_impl.cc +++ b/chrome/browser/performance_manager/graph/process_node_impl.cc
@@ -13,9 +13,12 @@ ProcessNodeImpl::ProcessNodeImpl( const resource_coordinator::CoordinationUnitID& id, Graph* graph) - : CoordinationUnitInterface(id, graph) {} + : CoordinationUnitInterface(id, graph) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} ProcessNodeImpl::~ProcessNodeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Make as if we're transitioning to the null PID before we die to clear this // instance from the PID map. if (process_id_ != base::kNullProcessId)
diff --git a/chrome/browser/performance_manager/graph/system_node_impl.cc b/chrome/browser/performance_manager/graph/system_node_impl.cc index cf23570..3496179 100644 --- a/chrome/browser/performance_manager/graph/system_node_impl.cc +++ b/chrome/browser/performance_manager/graph/system_node_impl.cc
@@ -21,7 +21,9 @@ Graph* graph) : CoordinationUnitInterface(id, graph) {} -SystemNodeImpl::~SystemNodeImpl() = default; +SystemNodeImpl::~SystemNodeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} void SystemNodeImpl::OnProcessCPUUsageReady() { SendEvent(resource_coordinator::mojom::Event::kProcessCPUUsageReady);
diff --git a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h b/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h index 02d573f..17e00c3 100644 --- a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h +++ b/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h
@@ -95,6 +95,10 @@ resource_coordinator::mojom::Event event) { } + // FrameNodeImpl notifications. + virtual void OnNetworkAlmostIdleChanged(FrameNodeImpl* frame_node) {} + + // PageNodeImpl notifications. virtual void OnIsVisibleChanged(PageNodeImpl* page_node) {} virtual void OnIsLoadingChanged(PageNodeImpl* page_node) {}
diff --git a/chrome/browser/performance_manager/page_resource_coordinator.cc b/chrome/browser/performance_manager/page_resource_coordinator.cc deleted file mode 100644 index ed014e39..0000000 --- a/chrome/browser/performance_manager/page_resource_coordinator.cc +++ /dev/null
@@ -1,100 +0,0 @@ -// 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/performance_manager/page_resource_coordinator.h" -#include "base/bind.h" - -namespace performance_manager { - -PageResourceCoordinator::PageResourceCoordinator( - PerformanceManager* performance_manager) - : ResourceCoordinatorInterface(), weak_ptr_factory_(this) { - resource_coordinator::CoordinationUnitID new_cu_id( - resource_coordinator::CoordinationUnitType::kPage, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - ResourceCoordinatorInterface::ConnectToService(performance_manager, - new_cu_id); -} - -PageResourceCoordinator::~PageResourceCoordinator() = default; - -void PageResourceCoordinator::SetIsLoading(bool is_loading) { - if (!service_) - return; - service_->SetIsLoading(is_loading); -} - -void PageResourceCoordinator::SetVisibility(bool visible) { - if (!service_) - return; - service_->SetVisibility(visible); -} - -void PageResourceCoordinator::SetUKMSourceId(int64_t ukm_source_id) { - if (!service_) - return; - service_->SetUKMSourceId(ukm_source_id); -} - -void PageResourceCoordinator::OnFaviconUpdated() { - if (!service_) - return; - service_->OnFaviconUpdated(); -} - -void PageResourceCoordinator::OnTitleUpdated() { - if (!service_) - return; - service_->OnTitleUpdated(); -} - -void PageResourceCoordinator::OnMainFrameNavigationCommitted( - base::TimeTicks navigation_committed_time, - uint64_t navigation_id, - const std::string& url) { - if (!service_) - return; - service_->OnMainFrameNavigationCommitted(navigation_committed_time, - navigation_id, url); -} - -void PageResourceCoordinator::AddFrame(const FrameResourceCoordinator& frame) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!service_ || !frame.service()) - return; - // We could keep the ID around ourselves, but this hop ensures that the child - // has been created on the service-side. - frame.service()->GetID(base::BindOnce(&PageResourceCoordinator::AddFrameByID, - weak_ptr_factory_.GetWeakPtr())); -} - -void PageResourceCoordinator::RemoveFrame( - const FrameResourceCoordinator& frame) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!service_ || !frame.service()) - return; - frame.service()->GetID( - base::BindOnce(&PageResourceCoordinator::RemoveFrameByID, - weak_ptr_factory_.GetWeakPtr())); -} - -void PageResourceCoordinator::ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) { - provider->CreatePageCoordinationUnit(mojo::MakeRequest(&service_), cu_id); -} - -void PageResourceCoordinator::AddFrameByID( - const resource_coordinator::CoordinationUnitID& cu_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - service_->AddFrame(cu_id); -} - -void PageResourceCoordinator::RemoveFrameByID( - const resource_coordinator::CoordinationUnitID& cu_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - service_->RemoveFrame(cu_id); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/page_resource_coordinator.h b/chrome/browser/performance_manager/page_resource_coordinator.h deleted file mode 100644 index fd82255..0000000 --- a/chrome/browser/performance_manager/page_resource_coordinator.h +++ /dev/null
@@ -1,56 +0,0 @@ -// 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_PERFORMANCE_MANAGER_PAGE_RESOURCE_COORDINATOR_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_PAGE_RESOURCE_COORDINATOR_H_ - -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "chrome/browser/performance_manager/frame_resource_coordinator.h" -#include "chrome/browser/performance_manager/resource_coordinator_interface.h" -#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" - -namespace performance_manager { - -class PageResourceCoordinator - : public ResourceCoordinatorInterface< - resource_coordinator::mojom::PageCoordinationUnitPtr, - resource_coordinator::mojom::PageCoordinationUnitRequest> { - public: - explicit PageResourceCoordinator(PerformanceManager* performance_manager); - ~PageResourceCoordinator() override; - - void SetIsLoading(bool is_loading); - void SetVisibility(bool visible); - void SetUKMSourceId(int64_t ukm_source_id); - void OnFaviconUpdated(); - void OnTitleUpdated(); - void OnMainFrameNavigationCommitted(base::TimeTicks navigation_committed_time, - uint64_t navigation_id, - const std::string& url); - - void AddFrame(const FrameResourceCoordinator& frame); - void RemoveFrame(const FrameResourceCoordinator& frame); - - private: - void ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) override; - - void AddFrameByID(const resource_coordinator::CoordinationUnitID& cu_id); - void RemoveFrameByID(const resource_coordinator::CoordinationUnitID& cu_id); - - THREAD_CHECKER(thread_checker_); - - // The WeakPtrFactory should come last so the weak ptrs are invalidated - // before the rest of the member variables. - base::WeakPtrFactory<PageResourceCoordinator> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(PageResourceCoordinator); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_PAGE_RESOURCE_COORDINATOR_H_
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc index 7460c46..e1523e4 100644 --- a/chrome/browser/performance_manager/performance_manager.cc +++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -14,6 +14,7 @@ #include "base/task/task_traits.h" #include "build/build_config.h" #include "chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" #include "chrome/browser/performance_manager/graph/system_node_impl.h" #include "chrome/browser/performance_manager/observers/metrics_collector.h" #include "chrome/browser/performance_manager/observers/page_signal_generator_impl.h" @@ -75,7 +76,19 @@ base::Unretained(this), std::move(batch))); } -void PerformanceManager::BindInterface( +std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode() { + return CreateNodeImpl<FrameNodeImpl>(); +} + +std::unique_ptr<PageNodeImpl> PerformanceManager::CreatePageNode() { + return CreateNodeImpl<PageNodeImpl>(); +} + +std::unique_ptr<ProcessNodeImpl> PerformanceManager::CreateProcessNode() { + return CreateNodeImpl<ProcessNodeImpl>(); +} + +void PerformanceManager::PostBindInterface( const std::string& interface_name, mojo::ScopedMessagePipeHandle message_pipe) { task_runner_->PostTask(FROM_HERE, @@ -84,6 +97,30 @@ std::move(message_pipe))); } +template <typename NodeType> +std::unique_ptr<NodeType> PerformanceManager::CreateNodeImpl() { + resource_coordinator::CoordinationUnitID id( + NodeType::Type(), resource_coordinator::CoordinationUnitID::RANDOM_ID); + std::unique_ptr<NodeType> new_node = std::make_unique<NodeType>(id, &graph_); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&Graph::AddNewNode, base::Unretained(&graph_), + base::Unretained(new_node.get()))); + + return new_node; +} + +void PerformanceManager::PostDeleteNode(std::unique_ptr<NodeBase> node) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&PerformanceManager::DeleteNodeImpl, + base::Unretained(this), std::move(node))); +} + +void PerformanceManager::DeleteNodeImpl(std::unique_ptr<NodeBase> node) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + graph_.DestroyNode(node.get()); +} + void PerformanceManager::OnStart() { // Some tests don't initialize the service manager connection, so this class // tolerates its absence for tests. @@ -125,8 +162,6 @@ ukm_recorder_ = ukm::MojoUkmRecorder::Create(connector.get()); graph_.set_ukm_recorder(ukm_recorder_.get()); } - - graph_.OnStart(&interface_registry_); } void PerformanceManager::BindInterfaceImpl(
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h index ea4063c..709cf40 100644 --- a/chrome/browser/performance_manager/performance_manager.h +++ b/chrome/browser/performance_manager/performance_manager.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <utility> #include <vector> #include "base/sequence_checker.h" @@ -27,6 +28,8 @@ namespace performance_manager { +class PageNodeImpl; + // The performance manager is a rendezvous point for binding to performance // manager interfaces. // TODO(https://crbug.com/910288): Refactor this along with the @@ -59,14 +62,36 @@ void DistributeMeasurementBatch( resource_coordinator::mojom::ProcessResourceMeasurementBatchPtr batch); + // Creates a new node of the requested type and adds it to the graph. + // May be called from any sequence. + std::unique_ptr<FrameNodeImpl> CreateFrameNode(); + std::unique_ptr<PageNodeImpl> CreatePageNode(); + std::unique_ptr<ProcessNodeImpl> CreateProcessNode(); + + // Destroys a node returned from the creation functions above. + // May be called from any sequence. + template <typename NodeType> + void DeleteNode(std::unique_ptr<NodeType> node); + + // TODO(siggi): Can this be hidden away? + scoped_refptr<base::SequencedTaskRunner> task_runner() const { + return task_runner_; + } + private: using InterfaceRegistry = service_manager::BinderRegistryWithArgs< const service_manager::BindSourceInfo&>; PerformanceManager(); - void BindInterface(const std::string& interface_name, - mojo::ScopedMessagePipeHandle message_pipe); + void PostBindInterface(const std::string& interface_name, + mojo::ScopedMessagePipeHandle message_pipe); + + template <typename NodeType> + std::unique_ptr<NodeType> CreateNodeImpl(); + + void PostDeleteNode(std::unique_ptr<NodeBase> node); + void DeleteNodeImpl(std::unique_ptr<NodeBase> node); void OnStart(); void OnStartImpl(std::unique_ptr<service_manager::Connector> connector); @@ -102,7 +127,12 @@ template <typename Interface> void PerformanceManager::BindInterface( mojo::InterfaceRequest<Interface> request) { - BindInterface(Interface::Name_, request.PassMessagePipe()); + PostBindInterface(Interface::Name_, request.PassMessagePipe()); +} + +template <typename NodeType> +void PerformanceManager::DeleteNode(std::unique_ptr<NodeType> node) { + PostDeleteNode(std::move(node)); } } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.cc b/chrome/browser/performance_manager/performance_manager_tab_helper.cc index c98fb4a..debc45d2 100644 --- a/chrome/browser/performance_manager/performance_manager_tab_helper.cc +++ b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
@@ -7,8 +7,11 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/stl_util.h" -#include "chrome/browser/performance_manager/frame_resource_coordinator.h" +#include "chrome/browser/performance_manager/graph/frame_node_impl.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/performance_manager.h" #include "chrome/browser/performance_manager/render_process_user_data.h" #include "content/public/browser/navigation_handle.h" @@ -26,7 +29,7 @@ PerformanceManagerTabHelper* helper = FromWebContents(web_contents); if (!helper) return false; - *id = helper->page_resource_coordinator_.id(); + *id = helper->page_node_->id(); return true; } @@ -41,7 +44,7 @@ content::WebContents* web_contents) : content::WebContentsObserver(web_contents), performance_manager_(PerformanceManager::GetInstance()), - page_resource_coordinator_(PerformanceManager::GetInstance()) { + page_node_(performance_manager_->CreatePageNode()) { // Make sure to set the visibility property when we create // |page_resource_coordinator_|. UpdatePageNodeVisibility(web_contents->GetVisibility()); @@ -68,6 +71,10 @@ } PerformanceManagerTabHelper::~PerformanceManagerTabHelper() { + performance_manager_->DeleteNode(std::move(page_node_)); + for (auto& kv : frames_) + performance_manager_->DeleteNode(std::move(kv.second)); + if (first_ == this) first_ = next_; @@ -87,13 +94,16 @@ // This must not exist in the map yet. DCHECK(!base::ContainsKey(frames_, render_frame_host)); - std::unique_ptr<FrameResourceCoordinator> frame = - std::make_unique<FrameResourceCoordinator>(performance_manager_); + std::unique_ptr<FrameNodeImpl> frame = + performance_manager_->CreateFrameNode(); content::RenderFrameHost* parent = render_frame_host->GetParent(); if (parent) { DCHECK(base::ContainsKey(frames_, parent)); auto& parent_frame_node = frames_[parent]; - parent_frame_node->AddChildFrame(*frame.get()); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&FrameNodeImpl::AddChildFrame, + base::Unretained(parent_frame_node.get()), frame->id())); } RenderProcessUserData* user_data = @@ -103,24 +113,35 @@ // is not in play. // TODO(siggi): Figure out how to assert on this when the main parts are // registered with the content browser client. - if (user_data) - frame->SetProcess(*user_data->process_resource_coordinator()); + if (user_data) { + performance_manager_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FrameNodeImpl::SetProcess, + base::Unretained(frame.get()), + user_data->process_node()->id())); + } frames_[render_frame_host] = std::move(frame); } void PerformanceManagerTabHelper::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { - DCHECK(base::ContainsKey(frames_, render_frame_host)); - frames_.erase(render_frame_host); + auto it = frames_.find(render_frame_host); + DCHECK(it != frames_.end()); + + performance_manager_->DeleteNode(std::move(it->second)); + frames_.erase(it); } void PerformanceManagerTabHelper::DidStartLoading() { - page_resource_coordinator_.SetIsLoading(true); + performance_manager_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&PageNodeImpl::SetIsLoading, + base::Unretained(page_node_.get()), true)); } void PerformanceManagerTabHelper::DidStopLoading() { - page_resource_coordinator_.SetIsLoading(false); + performance_manager_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&PageNodeImpl::SetIsLoading, + base::Unretained(page_node_.get()), false)); } void PerformanceManagerTabHelper::OnVisibilityChanged( @@ -149,13 +170,20 @@ auto it = frames_.find(render_frame_host); if (it != frames_.end()) { // TODO(siggi): See whether this can be done in RenderFrameCreated. - page_resource_coordinator_.AddFrame(*(it->second)); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&PageNodeImpl::AddFrame, + base::Unretained(page_node_.get()), it->second->id())); if (navigation_handle->IsInMainFrame()) { OnMainFrameNavigation(navigation_handle->GetNavigationId()); - page_resource_coordinator_.OnMainFrameNavigationCommitted( - navigation_committed_time, navigation_handle->GetNavigationId(), - navigation_handle->GetURL().spec()); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&PageNodeImpl::OnMainFrameNavigationCommitted, + base::Unretained(page_node_.get()), + navigation_committed_time, + navigation_handle->GetNavigationId(), + navigation_handle->GetURL().spec())); } } } @@ -166,7 +194,9 @@ first_time_title_set_ = true; return; } - page_resource_coordinator_.OnTitleUpdated(); + performance_manager_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&PageNodeImpl::OnTitleUpdated, + base::Unretained(page_node_.get()))); } void PerformanceManagerTabHelper::DidUpdateFaviconURL( @@ -176,7 +206,9 @@ first_time_favicon_set_ = true; return; } - page_resource_coordinator_.OnFaviconUpdated(); + performance_manager_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&PageNodeImpl::OnFaviconUpdated, + base::Unretained(page_node_.get()))); } void PerformanceManagerTabHelper::OnInterfaceRequestFromFrame( @@ -189,15 +221,21 @@ auto it = frames_.find(render_frame_host); DCHECK(it != frames_.end()); - it->second->AddBinding( - resource_coordinator::mojom::FrameCoordinationUnitRequest( - std::move(*interface_pipe))); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&FrameNodeImpl::AddBinding, + base::Unretained(it->second.get()), + resource_coordinator::mojom::FrameCoordinationUnitRequest( + std::move(*interface_pipe)))); } void PerformanceManagerTabHelper::OnMainFrameNavigation(int64_t navigation_id) { ukm_source_id_ = ukm::ConvertToSourceId(navigation_id, ukm::SourceIdType::NAVIGATION_ID); - page_resource_coordinator_.SetUKMSourceId(ukm_source_id_); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&PageNodeImpl::SetUKMSourceId, + base::Unretained(page_node_.get()), ukm_source_id_)); first_time_title_set_ = false; first_time_favicon_set_ = false; @@ -207,7 +245,10 @@ content::Visibility visibility) { // TODO(fdoray): An OCCLUDED tab should not be considered visible. const bool is_visible = visibility != content::Visibility::HIDDEN; - page_resource_coordinator_.SetVisibility(is_visible); + performance_manager_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&PageNodeImpl::SetVisibility, + base::Unretained(page_node_.get()), is_visible)); } WEB_CONTENTS_USER_DATA_KEY_IMPL(PerformanceManagerTabHelper)
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.h b/chrome/browser/performance_manager/performance_manager_tab_helper.h index 1833612..b4d2861 100644 --- a/chrome/browser/performance_manager/performance_manager_tab_helper.h +++ b/chrome/browser/performance_manager/performance_manager_tab_helper.h
@@ -11,7 +11,6 @@ #include <vector> #include "base/macros.h" -#include "chrome/browser/performance_manager/page_resource_coordinator.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -19,8 +18,8 @@ namespace performance_manager { -class FrameResourceCoordinator; -class PageResourceCoordinator; +class FrameNodeImpl; +class PageNodeImpl; class PerformanceManager; // This tab helper maintains a page node, and its associated tree of frame nodes @@ -42,9 +41,7 @@ ~PerformanceManagerTabHelper() override; - PageResourceCoordinator* page_resource_coordinator() { - return &page_resource_coordinator_; - } + PageNodeImpl* page_node() { return page_node_.get(); } // WebContentsObserver overrides. void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; @@ -74,8 +71,7 @@ // The performance manager for this process, if any. PerformanceManager* const performance_manager_; - - PageResourceCoordinator page_resource_coordinator_; + std::unique_ptr<PageNodeImpl> page_node_; ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId; // Favicon and title are set when a page is loaded, we only want to send @@ -85,9 +81,8 @@ bool first_time_favicon_set_ = false; bool first_time_title_set_ = false; - // Maps from RenderFrameHost to the associated RC node. - std::map<content::RenderFrameHost*, std::unique_ptr<FrameResourceCoordinator>> - frames_; + // Maps from RenderFrameHost to the associated PM node. + std::map<content::RenderFrameHost*, std::unique_ptr<FrameNodeImpl>> frames_; // All instances are linked together in a doubly linked list to allow orderly // destruction at browser shutdown time.
diff --git a/chrome/browser/performance_manager/performance_manager_unittest.cc b/chrome/browser/performance_manager/performance_manager_unittest.cc index adca71e..57c5870 100644 --- a/chrome/browser/performance_manager/performance_manager_unittest.cc +++ b/chrome/browser/performance_manager/performance_manager_unittest.cc
@@ -8,13 +8,9 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_task_environment.h" -#include "chrome/browser/performance_manager/frame_resource_coordinator.h" -#include "chrome/browser/performance_manager/page_resource_coordinator.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" -#include "chrome/browser/performance_manager/system_resource_coordinator.h" -#include "services/resource_coordinator/public/cpp/coordination_unit_id.h" -#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" -#include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h" +#include "chrome/browser/performance_manager/graph/frame_node_impl.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "testing/gtest/include/gtest/gtest.h" namespace performance_manager { @@ -42,31 +38,6 @@ task_environment_.RunUntilIdle(); } - // Given a CU, tests that it works by invoking GetID and waiting for the - // response. This test will hang (and eventually fail) if the response does - // not come back from the remote endpoint. - template <typename CoordinationUnitPtrType> - void TestCUImpl(CoordinationUnitPtrType cu) { - base::RunLoop loop; - cu->GetID(base::BindLambdaForTesting( - [&loop](const resource_coordinator::CoordinationUnitID& cu_id) { - loop.Quit(); - })); - loop.Run(); - } - - // Variant that works with mojo interface pointers. - template <typename CoordinationUnitPtrType> - void TestCU(CoordinationUnitPtrType& cu) { - TestCUImpl<CoordinationUnitPtrType&>(cu); - } - - // Variant that works with pointers to FooResourceCoordinator wrappers. - template <typename CoordinationUnitPtrType> - void TestCU(CoordinationUnitPtrType* cu) { - TestCUImpl<CoordinationUnitPtrType*>(cu); - } - protected: PerformanceManager* performance_manager() { return performance_manager_.get(); @@ -79,50 +50,27 @@ DISALLOW_COPY_AND_ASSIGN(PerformanceManagerTest); }; -TEST_F(PerformanceManagerTest, ResourceCoordinatorInstantiate) { - // Get the CU provider interface. - resource_coordinator::mojom::CoordinationUnitProviderPtr provider; - performance_manager()->BindInterface(mojo::MakeRequest(&provider)); +TEST_F(PerformanceManagerTest, InstantiateNodes) { + // Create a node of each type. + std::unique_ptr<FrameNodeImpl> frame_node = + performance_manager()->CreateFrameNode(); + EXPECT_NE(nullptr, frame_node.get()); - // Create and test a dummy FrameCU. - resource_coordinator::CoordinationUnitID frame_id( - resource_coordinator::CoordinationUnitType::kFrame, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - resource_coordinator::mojom::FrameCoordinationUnitPtr frame_cu; - provider->CreateFrameCoordinationUnit(mojo::MakeRequest(&frame_cu), frame_id); - TestCU(frame_cu); + std::unique_ptr<PageNodeImpl> page_node = + performance_manager()->CreatePageNode(); + EXPECT_NE(nullptr, page_node.get()); - // Create and test a dummy PageCU. - resource_coordinator::CoordinationUnitID page_id( - resource_coordinator::CoordinationUnitType::kPage, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - resource_coordinator::mojom::PageCoordinationUnitPtr page_cu; - provider->CreatePageCoordinationUnit(mojo::MakeRequest(&page_cu), page_id); - TestCU(page_cu); + std::unique_ptr<ProcessNodeImpl> process_node = + performance_manager()->CreateProcessNode(); + EXPECT_NE(nullptr, process_node.get()); - // Create and test a dummy SystemCU. - resource_coordinator::mojom::SystemCoordinationUnitPtr system_cu; - provider->GetSystemCoordinationUnit(mojo::MakeRequest(&system_cu)); - TestCU(system_cu); - - // Create and test a dummy ProcessCU. - resource_coordinator::CoordinationUnitID process_id( - resource_coordinator::CoordinationUnitType::kProcess, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - resource_coordinator::mojom::ProcessCoordinationUnitPtr process_cu; - provider->CreateProcessCoordinationUnit(mojo::MakeRequest(&process_cu), - process_id); - TestCU(process_cu); - - // Also test the convenience headers for creating and communicating with CUs. - FrameResourceCoordinator frame_rc(performance_manager()); - TestCU(&frame_rc); - PageResourceCoordinator page_rc(performance_manager()); - TestCU(&page_rc); - ProcessResourceCoordinator process_rc(performance_manager()); - TestCU(&process_rc); - SystemResourceCoordinator system_rc(performance_manager()); - TestCU(&system_rc); + performance_manager()->DeleteNode(std::move(process_node)); + performance_manager()->DeleteNode(std::move(page_node)); + performance_manager()->DeleteNode(std::move(frame_node)); } +// TODO(siggi): More tests! +// - Test the WebUI interface. +// - Test the graph introspector interface. + } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/process_resource_coordinator.cc b/chrome/browser/performance_manager/process_resource_coordinator.cc deleted file mode 100644 index f213837..0000000 --- a/chrome/browser/performance_manager/process_resource_coordinator.cc +++ /dev/null
@@ -1,63 +0,0 @@ -// 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/performance_manager/process_resource_coordinator.h" - -#include "base/time/time.h" -#include "build/build_config.h" - -namespace performance_manager { - -ProcessResourceCoordinator::ProcessResourceCoordinator( - PerformanceManager* performance_manager) - : ResourceCoordinatorInterface(), weak_ptr_factory_(this) { - resource_coordinator::CoordinationUnitID new_cu_id( - resource_coordinator::CoordinationUnitType::kProcess, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - ResourceCoordinatorInterface::ConnectToService(performance_manager, - new_cu_id); -} - -ProcessResourceCoordinator::~ProcessResourceCoordinator() = default; - -void ProcessResourceCoordinator::OnProcessLaunched( - const base::Process& process) { - if (!service_) - return; - - // TODO(fdoray): Merge ProcessCoordinationUnit::SetPID/SetLaunchTime(). - service_->SetPID(process.Pid()); - service_->SetLaunchTime( -#if defined(OS_ANDROID) - // Process::CreationTime() is not available on Android. Since this method - // is called immediately after the process is launched, the process launch - // time can be approximated with the current time. - base::Time::Now() -#else - process.CreationTime() -#endif - ); -} - -void ProcessResourceCoordinator::SetCPUUsage(double cpu_usage) { - if (!service_) - return; - - service_->SetCPUUsage(cpu_usage); -} - -void ProcessResourceCoordinator::SetProcessExitStatus(int32_t exit_status) { - if (!service_) - return; - - service_->SetProcessExitStatus(exit_status); -} - -void ProcessResourceCoordinator::ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) { - provider->CreateProcessCoordinationUnit(mojo::MakeRequest(&service_), cu_id); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/process_resource_coordinator.h b/chrome/browser/performance_manager/process_resource_coordinator.h deleted file mode 100644 index fe5475c..0000000 --- a/chrome/browser/performance_manager/process_resource_coordinator.h +++ /dev/null
@@ -1,47 +0,0 @@ -// 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_PERFORMANCE_MANAGER_PROCESS_RESOURCE_COORDINATOR_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_PROCESS_RESOURCE_COORDINATOR_H_ - -#include "base/memory/weak_ptr.h" -#include "base/process/process.h" -#include "base/threading/thread_checker.h" -#include "chrome/browser/performance_manager/frame_resource_coordinator.h" -#include "chrome/browser/performance_manager/resource_coordinator_interface.h" -#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" - -namespace performance_manager { - -class ProcessResourceCoordinator - : public ResourceCoordinatorInterface< - resource_coordinator::mojom::ProcessCoordinationUnitPtr, - resource_coordinator::mojom::ProcessCoordinationUnitRequest> { - public: - explicit ProcessResourceCoordinator(PerformanceManager* performance_manager); - ~ProcessResourceCoordinator() override; - - // Must be called immediately after the process is launched. - void OnProcessLaunched(const base::Process& process); - - void SetCPUUsage(double usage); - void SetProcessExitStatus(int32_t exit_status); - - private: - void ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) override; - - THREAD_CHECKER(thread_checker_); - - // The WeakPtrFactory should come last so the weak ptrs are invalidated - // before the rest of the member variables. - base::WeakPtrFactory<ProcessResourceCoordinator> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProcessResourceCoordinator); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_PROCESS_RESOURCE_COORDINATOR_H_
diff --git a/chrome/browser/performance_manager/render_process_user_data.cc b/chrome/browser/performance_manager/render_process_user_data.cc index 1ec7eaf4..cb10c81 100644 --- a/chrome/browser/performance_manager/render_process_user_data.cc +++ b/chrome/browser/performance_manager/render_process_user_data.cc
@@ -7,8 +7,12 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "base/command_line.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" +#include "build/build_config.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/performance_manager/performance_manager.h" #include "content/public/browser/child_process_termination_info.h" #include "content/public/browser/render_process_host.h" @@ -27,8 +31,7 @@ RenderProcessUserData::RenderProcessUserData( content::RenderProcessHost* render_process_host) : host_(render_process_host), - process_resource_coordinator_( - performance_manager::PerformanceManager::GetInstance()) { + process_node_(PerformanceManager::GetInstance()->CreateProcessNode()) { // The process itself shouldn't have been created at this point. DCHECK(!host_->GetProcess().IsValid() || base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -44,6 +47,7 @@ } RenderProcessUserData::~RenderProcessUserData() { + PerformanceManager::GetInstance()->DeleteNode(std::move(process_node_)); host_->RemoveObserver(this); if (first_ == this) @@ -81,14 +85,38 @@ void RenderProcessUserData::RenderProcessReady( content::RenderProcessHost* host) { - // TODO(siggi): Rename OnProcessLaunched->OnProcessReady. - process_resource_coordinator_.OnProcessLaunched(host->GetProcess()); + PerformanceManager* performance_manager = PerformanceManager::GetInstance(); + + // TODO(siggi): Change this to pass the process into the graph node. + const base::ProcessId pid = host->GetProcess().Pid(); + const base::Time launch_time = +#if defined(OS_ANDROID) + // Process::CreationTime() is not available on Android. Since this + // method is called immediately after the process is launched, the + // process launch time can be approximated with the current time. + base::Time::Now(); +#else + host->GetProcess().CreationTime(); +#endif + + performance_manager->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetPID, + base::Unretained(process_node_.get()), pid)); + performance_manager->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&ProcessNodeImpl::SetLaunchTime, + base::Unretained(process_node_.get()), launch_time)); } void RenderProcessUserData::RenderProcessExited( content::RenderProcessHost* host, const content::ChildProcessTerminationInfo& info) { - process_resource_coordinator_.SetProcessExitStatus(info.exit_code); + PerformanceManager* performance_manager = PerformanceManager::GetInstance(); + + performance_manager->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&ProcessNodeImpl::SetProcessExitStatus, + base::Unretained(process_node_.get()), info.exit_code)); } } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/render_process_user_data.h b/chrome/browser/performance_manager/render_process_user_data.h index 5152dcc..18a2554 100644 --- a/chrome/browser/performance_manager/render_process_user_data.h +++ b/chrome/browser/performance_manager/render_process_user_data.h
@@ -5,9 +5,10 @@ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_RENDER_PROCESS_USER_DATA_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_RENDER_PROCESS_USER_DATA_H_ +#include <memory> + #include "base/macros.h" #include "base/supports_user_data.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" #include "content/public/browser/render_process_host_observer.h" namespace content { @@ -18,6 +19,8 @@ namespace performance_manager { +class ProcessNodeImpl; + // Attached to RenderProcessHost as user data, associates the RenderProcessHost // with the Resource Coordinator process node. class RenderProcessUserData : public base::SupportsUserData::Data, @@ -32,10 +35,7 @@ // Detaches all instances from their RenderProcessHosts and destroys them. static void DetachAndDestroyAll(); - performance_manager::ProcessResourceCoordinator* - process_resource_coordinator() { - return &process_resource_coordinator_; - } + ProcessNodeImpl* process_node() { return process_node_.get(); } private: explicit RenderProcessUserData( @@ -56,7 +56,7 @@ content::RenderProcessHost* const host_; - performance_manager::ProcessResourceCoordinator process_resource_coordinator_; + std::unique_ptr<ProcessNodeImpl> process_node_; DISALLOW_COPY_AND_ASSIGN(RenderProcessUserData); };
diff --git a/chrome/browser/performance_manager/resource_coordinator_interface.h b/chrome/browser/performance_manager/resource_coordinator_interface.h deleted file mode 100644 index 0a182bb..0000000 --- a/chrome/browser/performance_manager/resource_coordinator_interface.h +++ /dev/null
@@ -1,70 +0,0 @@ -// 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_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_INTERFACE_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_INTERFACE_H_ - -#include <stdint.h> - -#include "base/component_export.h" -#include "base/macros.h" -#include "chrome/browser/performance_manager/performance_manager.h" -#include "services/resource_coordinator/public/cpp/coordination_unit_id.h" -#include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h" -#include "services/resource_coordinator/public/mojom/service_constants.mojom.h" - -namespace performance_manager { - -template <class CoordinationUnitMojoPtr, class CoordinationUnitMojoRequest> -class ResourceCoordinatorInterface { - public: - ResourceCoordinatorInterface() = default; - virtual ~ResourceCoordinatorInterface() = default; - - void AddBinding(CoordinationUnitMojoRequest request) { - if (!service_) - return; - service_->AddBinding(std::move(request)); - } - - // Returns the ID. Note that this is meaningless for a singleton CU. - resource_coordinator::CoordinationUnitID id() const { return cu_id_; } - - // Returns the remote endpoint interface. - const CoordinationUnitMojoPtr& service() const { return service_; } - - // Expose the GetID function for testing. - using CoordinationUnitMojo = typename CoordinationUnitMojoPtr::InterfaceType; - using GetIDCallback = typename CoordinationUnitMojo::GetIDCallback; - void GetID(GetIDCallback callback) { - if (!service_) - std::move(callback).Run(cu_id_); - service_->GetID(std::move(callback)); - } - - protected: - virtual void ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) = 0; - - void ConnectToService(PerformanceManager* performance_manager, - const resource_coordinator::CoordinationUnitID& cu_id) { - if (!performance_manager) - return; - cu_id_ = cu_id; - resource_coordinator::mojom::CoordinationUnitProviderPtr provider; - performance_manager->BindInterface(mojo::MakeRequest(&provider)); - ConnectToService(provider, cu_id); - } - - CoordinationUnitMojoPtr service_; - resource_coordinator::CoordinationUnitID cu_id_; - - private: - DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorInterface); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_INTERFACE_H_
diff --git a/chrome/browser/performance_manager/system_resource_coordinator.cc b/chrome/browser/performance_manager/system_resource_coordinator.cc deleted file mode 100644 index eb92375..0000000 --- a/chrome/browser/performance_manager/system_resource_coordinator.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2018 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/performance_manager/system_resource_coordinator.h" - -namespace performance_manager { - -SystemResourceCoordinator::SystemResourceCoordinator( - PerformanceManager* performance_manager) - : ResourceCoordinatorInterface() { - resource_coordinator::CoordinationUnitID new_cu_id( - resource_coordinator::CoordinationUnitType::kSystem, - resource_coordinator::CoordinationUnitID::RANDOM_ID); - ResourceCoordinatorInterface::ConnectToService(performance_manager, - new_cu_id); -} - -SystemResourceCoordinator::~SystemResourceCoordinator() = default; - -void SystemResourceCoordinator::DistributeMeasurementBatch( - resource_coordinator::mojom::ProcessResourceMeasurementBatchPtr batch) { - if (!service_) - return; - service_->DistributeMeasurementBatch(std::move(batch)); -} - -void SystemResourceCoordinator::ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) { - provider->GetSystemCoordinationUnit(mojo::MakeRequest(&service_)); -} - -} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/system_resource_coordinator.h b/chrome/browser/performance_manager/system_resource_coordinator.h deleted file mode 100644 index 672ce8b..0000000 --- a/chrome/browser/performance_manager/system_resource_coordinator.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2018 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_PERFORMANCE_MANAGER_SYSTEM_RESOURCE_COORDINATOR_H_ -#define CHROME_BROWSER_PERFORMANCE_MANAGER_SYSTEM_RESOURCE_COORDINATOR_H_ - -#include "chrome/browser/performance_manager/resource_coordinator_interface.h" -#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h" - -namespace performance_manager { - -class SystemResourceCoordinator - : public ResourceCoordinatorInterface< - resource_coordinator::mojom::SystemCoordinationUnitPtr, - resource_coordinator::mojom::SystemCoordinationUnitRequest> { - public: - explicit SystemResourceCoordinator(PerformanceManager* performance_manager); - ~SystemResourceCoordinator() override; - - void DistributeMeasurementBatch( - resource_coordinator::mojom::ProcessResourceMeasurementBatchPtr batch); - - private: - void ConnectToService( - resource_coordinator::mojom::CoordinationUnitProviderPtr& provider, - const resource_coordinator::CoordinationUnitID& cu_id) override; - - DISALLOW_COPY_AND_ASSIGN(SystemResourceCoordinator); -}; - -} // namespace performance_manager - -#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_SYSTEM_RESOURCE_COORDINATOR_H_
diff --git a/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc b/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc index 0205b75..d05f4764 100644 --- a/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc +++ b/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/performance_manager/browser_child_process_watcher.h" #include "chrome/browser/performance_manager/performance_manager.h" #include "chrome/browser/performance_manager/performance_manager_tab_helper.h" -#include "chrome/browser/performance_manager/process_resource_coordinator.h" #include "chrome/browser/performance_manager/render_process_user_data.h" #include "chrome/browser/resource_coordinator/page_signal_receiver.h" #include "chrome/browser/resource_coordinator/render_process_probe.h"
diff --git a/chrome/browser/resources/app_management/app.html b/chrome/browser/resources/app_management/app.html index 3b99164..81dbfb2 100644 --- a/chrome/browser/resources/app_management/app.html +++ b/chrome/browser/resources/app_management/app.html
@@ -28,11 +28,6 @@ overflow: hidden; } - cr-toolbar { - background: var(--md-toolbar-color); - min-height: var(--toolbar-height); - } - #main-container { flex: 1; overflow: auto;
diff --git a/chrome/browser/resources/app_management/shared_vars.html b/chrome/browser/resources/app_management/shared_vars.html index 1d62aba..860c609 100644 --- a/chrome/browser/resources/app_management/shared_vars.html +++ b/chrome/browser/resources/app_management/shared_vars.html
@@ -20,7 +20,6 @@ --primary-text-color: rgba(0, 0, 0, 0.87); --secondary-font-weight: 400; --secondary-text-color: rgba(0, 0, 0, 0.54); - --toolbar-height: 56px; } </style> </custom-style>
diff --git a/chrome/browser/resources/bookmarks/bookmarks.html b/chrome/browser/resources/bookmarks/bookmarks.html index 6b7581da..b91e6202 100644 --- a/chrome/browser/resources/bookmarks/bookmarks.html +++ b/chrome/browser/resources/bookmarks/bookmarks.html
@@ -19,8 +19,13 @@ overflow: hidden; } - html.loading { - border-top: 56px solid var(--md-toolbar-color); + html.loading::before { + background-color: var(--md-toolbar-color); + border-bottom: var(--md-toolbar-border); + box-sizing: border-box; + content: ''; + display: block; + height: var(--md-toolbar-height); } </style> </head>
diff --git a/chrome/browser/resources/bookmarks/toolbar.html b/chrome/browser/resources/bookmarks/toolbar.html index 715f1e9..d6579e9 100644 --- a/chrome/browser/resources/bookmarks/toolbar.html +++ b/chrome/browser/resources/bookmarks/toolbar.html
@@ -11,7 +11,6 @@ <template> <style include="shared-style"> :host { - background: var(--md-toolbar-color); position: relative; }
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css index 59a7eeac..0502cb7 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css
@@ -28,6 +28,11 @@ margin: 0 0 4px 0; } +.arc-events-inner-band-last-buffer { + display: block; + margin: 0 0 12px 0; +} + .arc-events-top-band { display: block; margin: 0 0 8px 0;
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js index 17c80a4..d66ab314 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
@@ -12,65 +12,98 @@ // Background color for the band with events. var bandColor = '#d3d3d3'; +// Color that should never appear on UI. +var unusedColor = '#ff0000'; + /** * Keep in sync with ArcTracingGraphicsModel::BufferEventType * See chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h. * Describes how events should be rendered. |color| specifies color of the - * event, |idle| indicates if this is the last event in the sequence of - * events. In case |idle| is true this means that sequence of events is - * done and relevant component is idle. |name| is used in tooltips. + * event, |name| is used in tooltips. */ var eventAttributes = { // kBufferQueueDequeueStart - 100: {color: '#99cc00', idle: false, name: 'app requests buffer'}, + 100: {color: '#99cc00', name: 'app requests buffer'}, // kBufferQueueDequeueDone - 101: {color: '#669999', idle: false, name: 'app fills buffer'}, + 101: {color: '#669999', name: 'app fills buffer'}, // kBufferQueueQueueStart - 102: {color: '#cccc00', idle: false, name: 'app queues buffer'}, + 102: {color: '#cccc00', name: 'app queues buffer'}, // kBufferQueueQueueDone - 103: {color: bandColor, idle: true, name: 'buffer is queued'}, + 103: {color: unusedColor, name: 'buffer is queued'}, // kBufferQueueAcquire - 104: {color: '#66ffcc', idle: false, name: 'use buffer'}, + 104: {color: '#66ffcc', name: 'use buffer'}, // kBufferQueueReleased - 105: {color: bandColor, idle: true, name: 'buffer released'}, + 105: {color: unusedColor, name: 'buffer released'}, // kExoSurfaceAttach. - 200: {color: '#99ccff', idle: false, name: 'surface attach'}, + 200: {color: '#99ccff', name: 'surface attach'}, // kExoProduceResource - 201: {color: '#cc66ff', idle: false, name: 'produce resource'}, + 201: {color: '#cc66ff', name: 'produce resource'}, // kExoBound - 202: {color: '#66ffff', idle: false, name: 'buffer bound'}, + 202: {color: '#66ffff', name: 'buffer bound'}, // kExoPendingQuery - 203: {color: '#00ff99', idle: false, name: 'pending query'}, + 203: {color: '#00ff99', name: 'pending query'}, // kExoReleased - 204: {color: bandColor, idle: true, name: 'released'}, + 204: {color: unusedColor, name: 'released'}, // kChromeBarrierOrder. - 300: {color: '#ff9933', idle: false, name: 'barrier order'}, + 300: {color: '#ff9933', name: 'barrier order'}, // kChromeBarrierFlush - 301: {color: bandColor, idle: true, name: 'barrier flush'}, + 301: {color: unusedColor, name: 'barrier flush'}, // kVsync - 400: {color: '#ff3300', idle: false, name: 'vsync'}, + 400: {color: '#ff3300', name: 'vsync'}, // kSurfaceFlingerInvalidationStart - 401: {color: '#ff9933', idle: false, name: 'invalidation start'}, + 401: {color: '#ff9933', name: 'invalidation start'}, // kSurfaceFlingerInvalidationDone - 402: {color: bandColor, idle: true, name: 'invalidation done'}, + 402: {color: unusedColor, name: 'invalidation done'}, // kSurfaceFlingerCompositionStart - 403: {color: '#3399ff', idle: false, name: 'composition start'}, + 403: {color: '#3399ff', name: 'composition start'}, // kSurfaceFlingerCompositionDone - 404: {color: bandColor, idle: true, name: 'composition done'}, + 404: {color: unusedColor, name: 'composition done'}, // kChromeOSDraw - 500: {color: '#3399ff', idle: false, name: 'draw'}, + 500: {color: '#3399ff', name: 'draw'}, // kChromeOSSwap - 501: {color: '#cc9900', idle: false, name: 'swap'}, + 501: {color: '#cc9900', name: 'swap'}, // kChromeOSWaitForAck - 502: {color: '#ccffff', idle: false, name: 'wait for ack'}, - // kChromeOSWaitForPresentation - 503: {color: '#65f441', idle: false, name: 'wait for presentation'}, - // kChromeOSDrawFinished - 504: {color: bandColor, idle: true, name: 'done'}, + 502: {color: '#ccffff', name: 'wait for ack'}, + // kChromeOSPresentationDone + 503: {color: '#ffbf00', name: 'presentation done'}, + // kChromeOSSwapDone + 504: {color: '#65f441', name: 'swap done'}, +}; + +/** + * Defines the map of events that can be treated as the end of event sequence. + * Time after such events is considered as idle time until the next event + * starts. Key of |endSequenceEvents| is event type as defined in + * ArcTracingGraphicsModel::BufferEventType and value is the list of event + * types that should follow after the tested event to consider it as end of + * sequence. Empty list means that tested event is certainly end of the + * sequence. + */ +var endSequenceEvents = { + // kBufferQueueQueueDone + 103: [], + // kBufferQueueReleased + 105: [], + // kExoReleased + 204: [], + // kChromeBarrierFlush + 301: [], + // kSurfaceFlingerInvalidationDone + 402: [], + // kSurfaceFlingerCompositionDone + 404: [], + // kChromeOSPresentationDone. Chrome does not define exactly which event + // is the last. Different + // pipelines may produce different sequences. Both event type may indicate + // the end of the + /// sequence. + 503: [500 /* kChromeOSDraw */], + // kChromeOSSwapDone + 504: [500 /* kChromeOSDraw */], }; /** @@ -238,7 +271,11 @@ } var nextX = timestampToOffset(event[1]); SVG.addRect(this.svg, x, 0, nextX - x, this.height, currentColor); - currentColor = eventAttributes[event[0]].color; + if (this.isEndOfSequence_(i)) { + currentColor = bandColor; + } else { + currentColor = eventAttributes[event[0]].color; + } x = nextX; } SVG.addRect(this.svg, x, 0, this.width - x, this.height, currentColor); @@ -288,6 +325,27 @@ } /** + * Returns true if the tested event denotes end of event sequence. + * + * @param {number} index element index in |this.events|. + */ + isEndOfSequence_(index) { + var nextEventTypes = endSequenceEvents[this.events[index][0]]; + if (!nextEventTypes) { + return false; + } + if (nextEventTypes.length == 0) { + return true; + } + var nextIndex = this.getNextEvent_(index, 1 /* direction */); + if (nextIndex < 0) { + // No more events after and it is listed as possible end of sequence. + return true; + } + return nextEventTypes.includes(this.events[nextIndex][0]); + } + + /** * Updates tool tip based on event under the current cursor. * * @param {Object} event mouse event. @@ -325,7 +383,7 @@ // In case cursor points to idle event, show its interval. Otherwise // show the sequence of non-idle events. - if (index < 0 || this.getEventAttributes_(index).idle) { + if (index < 0 || this.isEndOfSequence_(index)) { var startIdle = index < 0 ? 0 : this.events[index][1]; var endIdle = index < 0 ? this.duration : this.events[nextIndex][1]; SVG.addText( @@ -337,7 +395,7 @@ // Find the start of the non-idle sequence. while (true) { var prevIndex = this.getNextEvent_(index, -1 /* direction */); - if (prevIndex < 0 || this.getEventAttributes_(prevIndex).idle) { + if (prevIndex < 0 || this.isEndOfSequence_(prevIndex)) { break; } index = prevIndex; @@ -368,12 +426,17 @@ ' [' + timestempToMsText(eventTimestamp - lastTimestamp) + ' ms]'; } entriesToShow.push(entryToShow); - if (attributes.idle) { + if (this.isEndOfSequence_(index)) { break; } lastTimestamp = eventTimestamp; index = this.getNextEvent_(index, 1 /* direction */); } + + // Last element is end of sequence, use bandColor for the icon. + if (entriesToShow.length > 0) { + entriesToShow[entriesToShow.length - 1].color = bandColor; + } for (var i = 0; i < entriesToShow.length; ++i) { var entryToShow = entriesToShow[i]; SVG.addText( @@ -425,7 +488,7 @@ var view = model.views[i]; var activityTitleText; var icon; - if (view.task_id in model.tasks) { + if (model.tasks && view.task_id in model.tasks) { activityTitleText = model.tasks[view.task_id].title + ' - ' + view.activity; icon = model.tasks[view.task_id].icon; @@ -441,7 +504,8 @@ activityTitle, 'arc-events-inner-band', model.duration, 14); exoBand.setEvents(view.buffers[j], 200, 204); var chromeBand = new EventBand( - activityTitle, 'arc-events-inner-band', model.duration, 14); + activityTitle, 'arc-events-inner-band-last-buffer', model.duration, + 14); chromeBand.setEvents(view.buffers[j], 300, 301); } }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs index 3f09d04..9394937e 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs
@@ -257,7 +257,8 @@ }); }); -TEST_F('ChromeVoxEditingTest', 'RichTextMoveByCharacterAllAttributes', function() { +// Flakily times out. crbug.com/942241 +TEST_F('ChromeVoxEditingTest', 'DISABLED_RichTextMoveByCharacterAllAttributes', function() { var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function() {/*! <div role="textbox" contenteditable>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.js b/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.js index c12e79f0c..8dd1d49e 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_hid_detection.js
@@ -23,7 +23,7 @@ 'setKeyboardState', 'setMouseState', 'setKeyboardPinCode', - 'setKeyboardEnteredExpected', + 'setNumKeysEnteredExpected', 'setNumKeysEnteredPincode', 'setMouseDeviceName', 'setKeyboardDeviceName', @@ -79,7 +79,7 @@ this.updatePincodeKeysState_(); }, - setKeyboardEnteredExpected: function(value) { + setNumKeysEnteredExpected: function(value) { this.keyboardEnteredExpected_ = value; this.updatePincodeKeysState_(); },
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js index 63402bf..ed988a2 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
@@ -9,99 +9,128 @@ login.createScreen('ResetScreen', 'reset', function() { var USER_ACTION_CANCEL_RESET = 'cancel-reset'; var USER_ACTION_RESET_CONFIRM_DISMISSED = 'reset-confirm-dismissed'; - var CONTEXT_KEY_ROLLBACK_AVAILABLE = 'rollback-available'; - var CONTEXT_KEY_ROLLBACK_CHECKED = 'rollback-checked'; - var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE = - 'tpm-firmware-update-available'; - var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED = 'tpm-firmware-update-checked'; - var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE = 'tpm-firmware-update-editable'; - var CONTEXT_KEY_IS_OFFICIAL_BUILD = 'is-official-build'; - var CONTEXT_KEY_IS_CONFIRMATIONAL_VIEW = 'is-confirmational-view'; - var CONTEXT_KEY_SCREEN_STATE = 'screen-state'; + + /* Possible UI states of the reset screen. */ + const RESET_SCREEN_UI_STATE = { + REVERT_PROMISE: 'ui-state-revert-promise', + RESTART_REQUIRED: 'ui-state-restart-required', + POWERWASH_PROPOSAL: 'ui-state-powerwash-proposal', + ROLLBACK_PROPOSAL: 'ui-state-rollback-proposal', + ERROR: 'ui-state-error', + }; + + const RESET_SCREEN_STATE = { + RESTART_REQUIRED: 0, + REVERT_PROMISE: 1, + POWERWASH_PROPOSAL: 2, // supports 2 ui-states + ERROR: 3, + }; return { + EXTERNAL_API: [ + 'setIsRollbackAvailable', + 'setIsRollbackChecked', + 'setIsTpmFirmwareUpdateAvailable', + 'setIsTpmFirmwareUpdateChecked', + 'setIsTpmFirmwareUpdateEditable', + 'setTpmFirmwareUpdateMode', + 'setIsConfirmational', + 'setIsOfficialBuild', + 'setScreenState', + ], - /* Possible UI states of the reset screen. */ - RESET_SCREEN_UI_STATE: { - REVERT_PROMISE: 'ui-state-revert-promise', - RESTART_REQUIRED: 'ui-state-restart-required', - POWERWASH_PROPOSAL: 'ui-state-powerwash-proposal', - ROLLBACK_PROPOSAL: 'ui-state-rollback-proposal', - ERROR: 'ui-state-error', + /** @type {boolean} */ + isRollbackAvailable_: false, + /** @type {boolean} */ + isRollbackChecked_: false, + /** @type {boolean} */ + isTpmFirmwareUpdateAvailable_: false, + /** @type {boolean} */ + isTpmFirmwareUpdateChecked_: false, + /** @type {boolean} */ + isTpmFirmwareUpdateEditable_: false, + /** @type {RESET_SCREEN_UI_STATE} */ + tpmFirmwareUpdateMode_: RESET_SCREEN_UI_STATE.REVERT_PROMISE, + /** @type {boolean} */ + isConfirmational_: false, + /** @type {boolean} */ + isOfficialBuild_: false, + /** @type {RESET_SCREEN_STATE} */ + screenState_: RESET_SCREEN_STATE.RESTART_REQUIRED, + + setIsRollbackAvailable: function(rollbackAvailable) { + this.isRollbackAvailable_ = rollbackAvailable; + this.setRollbackOptionView(); }, - RESET_SCREEN_STATE: { - RESTART_REQUIRED: 0, - REVERT_PROMISE: 1, - POWERWASH_PROPOSAL: 2, // supports 2 ui-states - ERROR: 3, + setIsRollbackChecked: function(rollbackChecked) { + this.isRollbackChecked_ = rollbackChecked; + this.setRollbackOptionView(); }, + setIsTpmFirmwareUpdateAvailable: function(value) { + this.isTpmFirmwareUpdateAvailable_ = value; + this.setTPMFirmwareUpdateView_(); + }, + + setIsTpmFirmwareUpdateChecked: function(value) { + this.isTpmFirmwareUpdateChecked_ = value; + this.setTPMFirmwareUpdateView_(); + }, + + setIsTpmFirmwareUpdateEditable: function(value) { + this.isTpmFirmwareUpdateEditable_ = value; + this.setTPMFirmwareUpdateView_(); + }, + + setTpmFirmwareUpdateMode: function(value) { + this.tpmFirmwareUpdateMode_ = value; + }, + + setIsConfirmational: function(isConfirmational) { + this.isConfirmational_ = isConfirmational; + if (isConfirmational) { + if (this.screenState_ != RESET_SCREEN_STATE.POWERWASH_PROPOSAL) + return; + $('overlay-reset').removeAttribute('hidden'); + $('reset-confirm-overlay-md').open(); + } else { + $('overlay-reset').setAttribute('hidden', true); + $('reset-confirm-overlay-md').close(); + } + }, + + setIsOfficialBuild: function(isOfficial) { + this.isOfficialBuild_ = isOfficial; + + $('oobe-reset-md').isOfficial_ = isOfficial; + }, + + setScreenState: function(state) { + this.screenState_ = state; + + if (Oobe.getInstance().currentScreen != this) { + setTimeout(function() { + Oobe.resetSigninUI(false); + Oobe.showScreen({id: SCREEN_OOBE_RESET}); + }, 0); + } + if (state == RESET_SCREEN_STATE.RESTART_REQUIRED) + this.ui_state = RESET_SCREEN_UI_STATE.RESTART_REQUIRED; + if (state == RESET_SCREEN_STATE.REVERT_PROMISE) + this.ui_state = RESET_SCREEN_UI_STATE.REVERT_PROMISE; + else if (state == RESET_SCREEN_STATE.POWERWASH_PROPOSAL) + this.ui_state = RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL; + this.setDialogView_(); + if (state == RESET_SCREEN_STATE.REVERT_PROMISE) { + announceAccessibleMessage( + loadTimeData.getString('resetRevertSpinnerMessage')); + } + this.setTPMFirmwareUpdateView_(); + }, /** @override */ decorate: function() { - var self = this; - - this.context.addObserver(CONTEXT_KEY_SCREEN_STATE, function(state) { - if (Oobe.getInstance().currentScreen != this) { - setTimeout(function() { - Oobe.resetSigninUI(false); - Oobe.showScreen({id: SCREEN_OOBE_RESET}); - }, 0); - } - if (state == self.RESET_SCREEN_STATE.RESTART_REQUIRED) - self.ui_state = self.RESET_SCREEN_UI_STATE.RESTART_REQUIRED; - if (state == self.RESET_SCREEN_STATE.REVERT_PROMISE) - self.ui_state = self.RESET_SCREEN_UI_STATE.REVERT_PROMISE; - else if (state == self.RESET_SCREEN_STATE.POWERWASH_PROPOSAL) - self.ui_state = self.RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL; - self.setDialogView_(); - if (state == self.RESET_SCREEN_STATE.REVERT_PROMISE) { - announceAccessibleMessage( - loadTimeData.getString('resetRevertSpinnerMessage')); - } - self.setTPMFirmwareUpdateView_(); - }); - - this.context.addObserver( - CONTEXT_KEY_IS_OFFICIAL_BUILD, function(isOfficial) { - $('oobe-reset-md').isOfficial_ = isOfficial; - }); - this.context.addObserver( - CONTEXT_KEY_ROLLBACK_CHECKED, function(rollbackChecked) { - self.setRollbackOptionView(); - }); - this.context.addObserver( - CONTEXT_KEY_ROLLBACK_AVAILABLE, function(rollbackAvailable) { - self.setRollbackOptionView(); - }); - this.context.addObserver( - CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED, function() { - self.setTPMFirmwareUpdateView_(); - }); - this.context.addObserver( - CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE, function() { - self.setTPMFirmwareUpdateView_(); - }); - this.context.addObserver( - CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE, function() { - self.setTPMFirmwareUpdateView_(); - }); - this.context.addObserver( - CONTEXT_KEY_IS_CONFIRMATIONAL_VIEW, function(is_confirmational) { - if (is_confirmational) { - if (self.context.get(CONTEXT_KEY_SCREEN_STATE, 0) != - self.RESET_SCREEN_STATE.POWERWASH_PROPOSAL) { - return; - } - $('overlay-reset').removeAttribute('hidden'); - $('reset-confirm-overlay-md').open(); - } else { - $('overlay-reset').setAttribute('hidden', true); - $('reset-confirm-overlay-md').close(); - } - }); - $('oobe-reset-md').screen = this; }, @@ -124,7 +153,7 @@ * Cancels the reset and drops the user back to the login screen. */ cancel: function() { - if (this.context.get(CONTEXT_KEY_IS_CONFIRMATIONAL_VIEW, false)) { + if (this.isConfirmational_) { $('reset').send( login.Screen.CALLBACK_USER_ACTED, USER_ACTION_RESET_CONFIRM_DISMISSED); @@ -146,47 +175,44 @@ setDialogView_: function(state) { state = this.ui_state; this.classList.toggle( - 'revert-promise-view', - state == this.RESET_SCREEN_UI_STATE.REVERT_PROMISE); + 'revert-promise-view', state == RESET_SCREEN_UI_STATE.REVERT_PROMISE); this.classList.toggle( 'restart-required-view', - state == this.RESET_SCREEN_UI_STATE.RESTART_REQUIRED); + state == RESET_SCREEN_UI_STATE.RESTART_REQUIRED); this.classList.toggle( 'powerwash-proposal-view', - state == this.RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL); + state == RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL); this.classList.toggle( 'rollback-proposal-view', - state == this.RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL); + state == RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL); var resetMd = $('oobe-reset-md'); var resetOverlayMd = $('reset-confirm-overlay-md'); - if (state == this.RESET_SCREEN_UI_STATE.RESTART_REQUIRED) { + if (state == RESET_SCREEN_UI_STATE.RESTART_REQUIRED) { resetMd.uiState_ = 'restart-required-view'; } - if (state == this.RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL) { + if (state == RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL) { resetMd.uiState_ = 'powerwash-proposal-view'; resetOverlayMd.isPowerwashView_ = true; } - if (state == this.RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL) { + if (state == RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL) { resetMd.uiState_ = 'rollback-proposal-view'; resetOverlayMd.isPowerwashView_ = false; } - if (state == this.RESET_SCREEN_UI_STATE.REVERT_PROMISE) { + if (state == RESET_SCREEN_UI_STATE.REVERT_PROMISE) { resetMd.uiState_ = 'revert-promise-view'; } }, setRollbackOptionView: function() { - if (this.context.get(CONTEXT_KEY_IS_CONFIRMATIONAL_VIEW, false)) + if (this.isConfirmational_) return; - if (this.context.get(CONTEXT_KEY_SCREEN_STATE) != - this.RESET_SCREEN_STATE.POWERWASH_PROPOSAL) + if (this.screenState_ != RESET_SCREEN_STATE.POWERWASH_PROPOSAL) return; - if (this.context.get(CONTEXT_KEY_ROLLBACK_AVAILABLE, false) && - this.context.get(CONTEXT_KEY_ROLLBACK_CHECKED, false)) { - this.ui_state = this.RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL; + if (this.isRollbackAvailable_ && this.isRollbackChecked_) { + this.ui_state = RESET_SCREEN_UI_STATE.ROLLBACK_PROPOSAL; } else { - this.ui_state = this.RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL; + this.ui_state = RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL; } this.setDialogView_(); this.setTPMFirmwareUpdateView_(); @@ -194,17 +220,16 @@ setTPMFirmwareUpdateView_: function() { $('oobe-reset-md').tpmFirmwareUpdateAvailable_ = - this.ui_state == this.RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL && - this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE); + this.ui_state == RESET_SCREEN_UI_STATE.POWERWASH_PROPOSAL && + this.isTpmFirmwareUpdateAvailable_; $('oobe-reset-md').tpmFirmwareUpdateChecked_ = - this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED); + this.isTpmFirmwareUpdateChecked_; $('oobe-reset-md').tpmFirmwareUpdateEditable_ = - this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE); + this.isTpmFirmwareUpdateEditable_; }, onTPMFirmwareUpdateChanged_: function(value) { - this.context.set(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED, value); - this.commitContextChanges(); + chrome.send('ResetScreen.setTpmFirmwareUpdateChecked', [value]); } }; });
diff --git a/chrome/browser/resources/downloads/downloads.html b/chrome/browser/resources/downloads/downloads.html index 2397587..dcb81ef 100644 --- a/chrome/browser/resources/downloads/downloads.html +++ b/chrome/browser/resources/downloads/downloads.html
@@ -12,8 +12,13 @@ touch-action: manipulation; } - html.loading { - border-top: 56px solid var(--md-toolbar-color); + html.loading::before { + background-color: var(--md-toolbar-color); + border-bottom: var(--md-toolbar-border); + box-sizing: border-box; + content: ''; + display: block; + height: var(--md-toolbar-height); } html:not(.loading),
diff --git a/chrome/browser/resources/downloads/toolbar.html b/chrome/browser/resources/downloads/toolbar.html index f9b804f..80fc546b 100644 --- a/chrome/browser/resources/downloads/toolbar.html +++ b/chrome/browser/resources/downloads/toolbar.html
@@ -19,7 +19,6 @@ <style include="cr-hidden-style"> :host { align-items: center; - background: var(--md-toolbar-color); display: flex; min-height: 56px; }
diff --git a/chrome/browser/resources/history/app.html b/chrome/browser/resources/history/app.html index 8579929..736edaf 100644 --- a/chrome/browser/resources/history/app.html +++ b/chrome/browser/resources/history/app.html
@@ -28,10 +28,6 @@ overflow: hidden; } - history-toolbar { - background: var(--md-toolbar-color); - } - /* Sizing this with flex causes slow load performance, see * crbug.com/618153. TODO(dbeam): is this still an issue? */ #main-container {
diff --git a/chrome/browser/resources/history/history.html b/chrome/browser/resources/history/history.html index ae99c88..18214b51 100644 --- a/chrome/browser/resources/history/history.html +++ b/chrome/browser/resources/history/history.html
@@ -55,8 +55,10 @@ #loading-toolbar { align-items: center; background: var(--md-toolbar-color); + border-bottom: var(--md-toolbar-border); + box-sizing: border-box; color: #fff; - height: 56px; + height: var(--md-toolbar-height); letter-spacing: .25px; padding-inline-start: 24px; }
diff --git a/chrome/browser/resources/management/management.html b/chrome/browser/resources/management/management.html index bec6e5cb..b682e7d 100644 --- a/chrome/browser/resources/management/management.html +++ b/chrome/browser/resources/management/management.html
@@ -10,14 +10,18 @@ <link rel="import" href="chrome://resources/html/cr.html"> <style> html { - --toolbar-height: 56px; background: var(--md-background-color); height: 100%; overflow: hidden; } - html.loading { - border-top: var(--toolbar-height) solid var(--md-toolbar-color); + html.loading::before { + background-color: var(--md-toolbar-color); + border-bottom: var(--md-toolbar-border); + box-sizing: border-box; + content: ''; + display: block; + height: var(--md-toolbar-height); } body {
diff --git a/chrome/browser/resources/management/management_ui.html b/chrome/browser/resources/management/management_ui.html index f80437b..3403e31d 100644 --- a/chrome/browser/resources/management/management_ui.html +++ b/chrome/browser/resources/management/management_ui.html
@@ -26,7 +26,6 @@ } cr-toolbar { - background-color: var(--md-toolbar-color); flex-shrink: 0; }
diff --git a/chrome/browser/resources/md_extensions/extensions.html b/chrome/browser/resources/md_extensions/extensions.html index 42461d4e4..088cee5c 100644 --- a/chrome/browser/resources/md_extensions/extensions.html +++ b/chrome/browser/resources/md_extensions/extensions.html
@@ -24,7 +24,7 @@ html.loading::before { background: var(--md-toolbar-color); - height: 56px; + height: var(--md-toolbar-height); } /* Mimics the developer mode toolbar until the real one loads. Note: @@ -39,9 +39,9 @@ background: none; } - html[dark].loading.in-dev-mode::before, + html[dark].loading::before, html[dark].loading.in-dev-mode body::before { - border-bottom: 1px solid rgba(255, 255, 255, .1); + border-bottom: var(--md-toolbar-border); } html,
diff --git a/chrome/browser/resources/md_extensions/toolbar.html b/chrome/browser/resources/md_extensions/toolbar.html index 5e3eec9f..6f3b663 100644 --- a/chrome/browser/resources/md_extensions/toolbar.html +++ b/chrome/browser/resources/md_extensions/toolbar.html
@@ -27,17 +27,6 @@ --padding-top-bottom: 10px; } - cr-toolbar { - background: var(--md-toolbar-color); - border-bottom: var(--border-bottom-height) solid transparent; - box-sizing: border-box; - transition: border-bottom-color var(--drawer-transition); - } - - :host-context([dark]):host([in-dev-mode]) cr-toolbar { - border-bottom-color: var(--cr-separator-color); - } - /* This toggle needs special styling because it's on blue background. */ :host-context(html:not([dark])) cr-toolbar cr-toggle { --cr-toggle-checked-bar-color: var(--google-grey-refresh-100);
diff --git a/chrome/browser/resources/ntp4/guest_tab.html b/chrome/browser/resources/ntp4/guest_tab.html index a89226c..1807bfc1 100644 --- a/chrome/browser/resources/ntp4/guest_tab.html +++ b/chrome/browser/resources/ntp4/guest_tab.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{dark}> <head> <meta charset="utf-8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/ntp4/incognito_and_guest_tab.css b/chrome/browser/resources/ntp4/incognito_and_guest_tab.css index ef6f279..d6d9d77 100644 --- a/chrome/browser/resources/ntp4/incognito_and_guest_tab.css +++ b/chrome/browser/resources/ntp4/incognito_and_guest_tab.css
@@ -9,6 +9,11 @@ font-size: 85%; } +[dark] { + background: rgb(50, 54, 57); + color: rgb(232, 234, 237); /* --google-grey-200 */ +} + h1 { font-size: 200%; font-weight: 400; @@ -29,8 +34,6 @@ text-decoration: underline; } -/* 'Learn More' button styled like a Material Design text button. - * TODO(edwardjung): Switch styled links to actual text buttons. */ .learn-more-button { color: rgb(66, 133, 244); display: inline-block; @@ -39,7 +42,10 @@ margin-top: 1.98em; padding: 10.5px 12px; text-decoration: none; - text-transform: uppercase; +} + +[dark] :-webkit-any(a, .learn-more-button) { + color: rgb(138, 180, 248); /* --google-blue-refresh-300 */ } .content {
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index e9893ba..be818a8 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -4,6 +4,19 @@ cr.exportPath('print_preview'); +/** @enum {number} */ +print_preview.DestinationState = { + INIT: 0, + SELECTED: 1, + SET: 2, + UPDATED: 3, + INVALID: 4, + UNSUPPORTED: 5, + // <if expr="chromeos"> + NO_DESTINATIONS: 6, + // </if> +}; + /** * Enumeration of the types of destinations. * @enum {string}
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index b71dfafb..b4aebff 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -14,6 +14,18 @@ DONE: 'done' }; +/** + * Enumeration of possible destination errors. + * @enum {number} + */ +print_preview.DestinationErrorType = { + INVALID: 0, + UNSUPPORTED: 1, + // <if expr="chromeos"> + NO_DESTINATIONS: 2, + // </if> +}; + cr.define('print_preview', function() { 'use strict'; /** @@ -1042,15 +1054,19 @@ /** * Sends SELECTED_DESTINATION_CAPABILITIES_READY event if the destination - * is supported, or SELECTED_DESTINATION_UNSUPPORTED otherwise. + * is supported, or ERROR otherwise of with error type UNSUPPORTED. * @private */ sendSelectedDestinationUpdateEvent_() { - this.dispatchEvent(new CustomEvent( - this.selectedDestination_.shouldShowInvalidCertificateError ? - DestinationStore.EventType.SELECTED_DESTINATION_UNSUPPORTED : - DestinationStore.EventType - .SELECTED_DESTINATION_CAPABILITIES_READY)); + if (this.selectedDestination_.shouldShowInvalidCertificateError) { + this.dispatchEvent(new CustomEvent( + DestinationStore.EventType.ERROR, + {detail: print_preview.DestinationErrorType.UNSUPPORTED})); + } else { + this.dispatchEvent( + new CustomEvent(DestinationStore.EventType + .SELECTED_DESTINATION_CAPABILITIES_READY)); + } } /** @@ -1243,7 +1259,8 @@ if (this.selectedDestination_ && this.selectedDestination_.id == destinationId) { this.dispatchEvent(new CustomEvent( - DestinationStore.EventType.SELECTED_DESTINATION_INVALID)); + DestinationStore.EventType.ERROR, + {detail: print_preview.DestinationErrorType.INVALID})); } if (this.autoSelectMatchingDestination_ && this.autoSelectMatchingDestination_.matchIdAndOrigin( @@ -1282,7 +1299,7 @@ /** * Checks if the search is done and no printers are found. If so, fires a - * DestinationStore.EventType.NO_DESTINATIONS_FOUND event. + * DestinationStore.EventType.ERROR event with error type NO_DESTINATIONS. * @private */ sendNoPrinterEventIfNeeded_() { @@ -1296,10 +1313,12 @@ !this.selectFirstDestination_) { return; } - + // <if expr="chromeos"> this.selectFirstDestination_ = false; - this.dispatchEvent( - new CustomEvent(DestinationStore.EventType.NO_DESTINATIONS_FOUND)); + this.dispatchEvent(new CustomEvent( + DestinationStore.EventType.ERROR, + {detail: print_preview.DestinationErrorType.NO_DESTINATIONS})); + // </if> } /** @@ -1398,14 +1417,9 @@ DESTINATIONS_INSERTED: 'print_preview.DestinationStore.DESTINATIONS_INSERTED', DESTINATIONS_RESET: 'print_preview.DestinationStore.DESTINATIONS_RESET', - NO_DESTINATIONS_FOUND: - 'print_preview.DestinationStore.NO_DESTINATIONS_FOUND', + ERROR: 'print_preview.DestinationStore.ERROR', SELECTED_DESTINATION_CAPABILITIES_READY: 'print_preview.DestinationStore' + '.SELECTED_DESTINATION_CAPABILITIES_READY', - SELECTED_DESTINATION_INVALID: - 'print_preview.DestinationStore.SELECTED_DESTINATION_INVALID', - SELECTED_DESTINATION_UNSUPPORTED: - 'print_preview.DestinationStore.SELECTED_DESTINATION_UNSUPPORTED', }; /**
diff --git a/chrome/browser/resources/print_preview/data/user_info.js b/chrome/browser/resources/print_preview/data/user_info.js index 14d9d8cf..9f454f53 100644 --- a/chrome/browser/resources/print_preview/data/user_info.js +++ b/chrome/browser/resources/print_preview/data/user_info.js
@@ -34,12 +34,6 @@ value: '', }, - /** @type {?cloudprint.CloudPrintInterface} */ - cloudPrintInterface: { - type: Object, - observer: 'onCloudPrintInterfaceSet_', - }, - /** @type {?print_preview.DestinationStore} */ destinationStore: Object, @@ -59,14 +53,10 @@ /** @private {!EventTracker} */ tracker_: new EventTracker(), - /** @private */ - onCloudPrintInterfaceSet_: function() { - if (!this.cloudPrintInterface) { - return; - } - + /** @param {!cloudprint.CloudPrintInterface} cloudPrintInterface */ + setCloudPrintInterface: function(cloudPrintInterface) { this.tracker_.add( - assert(this.cloudPrintInterface).getEventTarget(), + cloudPrintInterface.getEventTarget(), cloudprint.CloudPrintInterfaceEventType.UPDATE_USERS, this.updateUsers_.bind(this)); },
diff --git a/chrome/browser/resources/print_preview/new/BUILD.gn b/chrome/browser/resources/print_preview/new/BUILD.gn index 249d328..56c953d3 100644 --- a/chrome/browser/resources/print_preview/new/BUILD.gn +++ b/chrome/browser/resources/print_preview/new/BUILD.gn
@@ -68,11 +68,8 @@ "..:metrics", "..:native_layer", "../data:destination", - "../data:destination_store", "../data:document_info", - "../data:invitation_store", "../data:measurement_system", - "../data:user_info", "//ui/webui/resources/cr_elements:cr_container_shadow_behavior", "//ui/webui/resources/js:event_tracker", "//ui/webui/resources/js:util", @@ -96,13 +93,15 @@ deps = [ ":destination_dialog", ":destination_select", - ":state", + ":settings_behavior", + "..:cloud_print_interface", "../data:destination", "../data:destination_store", "../data:invitation_store", "../data:user_info", "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render", "//ui/webui/resources/js:i18n_behavior", + "//ui/webui/resources/js:web_ui_listener_behavior", ] }
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html index 9a705ce..63987328 100644 --- a/chrome/browser/resources/print_preview/new/app.html +++ b/chrome/browser/resources/print_preview/new/app.html
@@ -14,11 +14,8 @@ <link rel="import" href="../metrics.html"> <link rel="import" href="../native_layer.html"> <link rel="import" href="../data/destination.html"> -<link rel="import" href="../data/destination_store.html"> -<link rel="import" href="../data/invitation_store.html"> <link rel="import" href="../data/document_info.html"> <link rel="import" href="../data/measurement_system.html"> -<link rel="import" href="../data/user_info.html"> <link rel="import" href="print_preview_shared_css.html"> <link rel="import" href="strings.html"> <link rel="import" href="settings_behavior.html"> @@ -81,17 +78,11 @@ </style> <print-preview-state id="state" state="{{state}}"></print-preview-state> <print-preview-model id="model" settings="{{settings}}" - controls-managed="{{controlsManaged_}}" destination="{{destination_}}" + controls-managed="{{controlsManaged_}}" destination="[[destination_]]" document-settings="[[documentSettings_]]" margins="[[margins_]]" page-size="[[pageSize_]]" - recent-destinations="{{recentDestinations_}}" on-save-sticky-settings="onSaveStickySettings_"> </print-preview-model> - <print-preview-user-info id="userInfo" active-user="{{activeUser_}}" - users="{{users_}}" cloud-print-interface="[[cloudPrintInterface_]]" - destination-store="[[destinationStore_]]" - invitation-store="[[invitationStore_]]"> - </print-preview-user-info> <print-preview-document-info id="documentInfo" document-settings="{{documentSettings_}}" margins="{{margins_}}" page-size="{{pageSize_}}"> @@ -104,17 +95,11 @@ </print-preview-header> <div id="container"> <print-preview-destination-settings id="destinationSettings" - cloud-print-state="[[cloudPrintState_]]" - destination="[[destination_]]" - destination-store="[[destinationStore_]]" - invitation-store="[[invitationStore_]]" + destination="{{destination_}}" settings="{{settings}}" + destination-state="{{destinationState_}}" app-kiosk-mode="[[isInAppKioskMode_]]" - cloud-print-state="[[cloudPrintState_]]" - disabled="[[controlsDisabled_]]" state="[[state]]" - recent-destinations="[[recentDestinations_]]" - active-user="[[activeUser_]]" users="[[users_]]" - available class="settings-section" - on-account-change="onAccountChange_"> + disabled="[[controlsDisabled_]]" + available class="settings-section"> </print-preview-destination-settings> <print-preview-pages-settings settings="{{settings}}" page-count="[[documentSettings_.pageCount]]"
diff --git a/chrome/browser/resources/print_preview/new/app.js b/chrome/browser/resources/print_preview/new/app.js index cc3f07e..d6f4d98b 100644 --- a/chrome/browser/resources/print_preview/new/app.js +++ b/chrome/browser/resources/print_preview/new/app.js
@@ -26,10 +26,7 @@ * controls. * @type {!Object} */ - settings: { - type: Object, - notify: true, - }, + settings: Object, /** @type {!print_preview_new.State} */ state: { @@ -37,22 +34,9 @@ observer: 'onStateChanged_', }, - /** @private {string} */ - activeUser_: { - type: String, - observer: 'onActiveUserChanged_', - }, - - /** @private {!print_preview.CloudPrintState} */ - cloudPrintState_: { - type: Number, - value: print_preview.CloudPrintState.DISABLED, - }, - /** @private {boolean} */ controlsDisabled_: { type: Boolean, - notify: true, computed: 'computeControlsDisabled_(state)', }, @@ -60,17 +44,12 @@ controlsManaged_: Boolean, /** @private {print_preview.Destination} */ - destination_: { - type: Object, - notify: true, - value: null, - }, + destination_: Object, - /** @private {?print_preview.DestinationStore} */ - destinationStore_: { - type: Object, - notify: true, - value: null, + /** @private {!print_preview.DestinationState} */ + destinationState_: { + type: Number, + observer: 'onDestinationStateChange_', }, /** @private {print_preview.DocumentSettings} */ @@ -88,28 +67,18 @@ /** @private {string} */ errorMessage_: { type: String, - notify: true, value: '', }, - /** @private {?print_preview.InvitationStore} */ - invitationStore_: { - type: Object, - notify: true, - value: null, - }, - /** @private {boolean} */ isInAppKioskMode_: { type: Boolean, - notify: true, value: false, }, /** @private {?print_preview.MeasurementSystem} */ measurementSystem_: { type: Object, - notify: true, value: null, }, @@ -119,23 +88,15 @@ observer: 'onPreviewAreaStateChanged_', }, - /** @private {!Array<print_preview.RecentDestination>} */ - recentDestinations_: { - type: Array, - notify: true, - }, - /** @private {boolean} */ settingsExpandedByUser_: { type: Boolean, - notify: true, value: false, }, /** @private {boolean} */ shouldShowMoreSettings_: { type: Boolean, - notify: true, computed: 'computeShouldShowMoreSettings_(settings.pages.available, ' + 'settings.copies.available, settings.layout.available, ' + 'settings.color.available, settings.mediaSize.available, ' + @@ -143,9 +104,6 @@ 'settings.pagesPerSheet.available, settings.scaling.available, ' + 'settings.otherOptions.available, settings.vendorItems.available)', }, - - /** @private {!Array<string>} */ - users_: Array, }, listeners: { @@ -166,6 +124,9 @@ cancelled_: false, /** @private {boolean} */ + printRequested_: false, + + /** @private {boolean} */ showSystemDialogBeforePrint_: false, /** @private {boolean} */ @@ -190,35 +151,8 @@ this.addWebUIListener('print-failed', this.onPrintFailed_.bind(this)); this.addWebUIListener( 'print-preset-options', this.onPrintPresetOptions_.bind(this)); - this.destinationStore_ = - new print_preview.DestinationStore(this.addWebUIListener.bind(this)); - this.invitationStore_ = new print_preview.InvitationStore(); this.tracker_.add(window, 'keydown', this.onKeyDown_.bind(this)); this.$.previewArea.setPluginKeyEventCallback(this.onKeyDown_.bind(this)); - this.tracker_.add( - this.destinationStore_, - print_preview.DestinationStore.EventType.DESTINATION_SELECT, - this.onDestinationSelect_.bind(this)); - // <if expr="chromeos"> - this.tracker_.add( - this.destinationStore_, - print_preview.DestinationStore.EventType.NO_DESTINATIONS_FOUND, - this.onNoDestinationsFound_.bind(this)); - // </if> - this.tracker_.add( - this.destinationStore_, - print_preview.DestinationStore.EventType - .SELECTED_DESTINATION_CAPABILITIES_READY, - this.onDestinationUpdated_.bind(this)); - this.tracker_.add( - this.destinationStore_, - print_preview.DestinationStore.EventType - .SELECTED_DESTINATION_UNSUPPORTED, - this.onInvalidPrinter_.bind(this)); - this.tracker_.add( - this.destinationStore_, - print_preview.DestinationStore.EventType.SELECTED_DESTINATION_INVALID, - this.onInvalidPrinter_.bind(this)); this.nativeLayer_.getInitialSettings().then( this.onInitialSettingsSet_.bind(this)); }, @@ -352,11 +286,10 @@ settings.thousandsDelimeter, settings.decimalDelimeter, settings.unitType); this.setSetting('selectionOnly', settings.shouldPrintSelectionOnly); - this.destinationStore_.init( - settings.isInAppKioskMode, settings.printerName, - settings.serializedDefaultDestinationSelectionRulesStr, - this.recentDestinations_); this.isInAppKioskMode_ = settings.isInAppKioskMode; + this.$.destinationSettings.initDestinationStore( + settings.printerName, + settings.serializedDefaultDestinationSelectionRulesStr); this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode; // This is only visible in the task manager. @@ -385,59 +318,58 @@ assert(this.cloudPrintInterface_).getEventTarget(), cloudprint.CloudPrintInterfaceEventType.SUBMIT_DONE, this.close_.bind(this)); - - [cloudprint.CloudPrintInterfaceEventType.SEARCH_FAILED, - cloudprint.CloudPrintInterfaceEventType.PRINTER_FAILED, - ].forEach(eventType => { - this.tracker_.add( - assert(this.cloudPrintInterface_).getEventTarget(), eventType, - this.checkCloudPrintStatus_.bind(this)); - }); this.tracker_.add( assert(this.cloudPrintInterface_).getEventTarget(), cloudprint.CloudPrintInterfaceEventType.SUBMIT_FAILED, this.onCloudPrintError_.bind(this)); - - this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_); - this.invitationStore_.setCloudPrintInterface(this.cloudPrintInterface_); - assert(this.cloudPrintState_ === print_preview.CloudPrintState.DISABLED); - this.cloudPrintState_ = print_preview.CloudPrintState.ENABLED; + this.$.destinationSettings.setCloudPrintInterface( + this.cloudPrintInterface_); }, /** @private */ - onDestinationSelect_: function() { - // If the plugin does not exist do not attempt to load the preview. - if (this.state == print_preview_new.State.FATAL_ERROR) { - return; - } + onDestinationStateChange_: function(e) { + switch (this.destinationState_) { + case print_preview.DestinationState.SELECTED: + // If the plugin does not exist do not attempt to load the preview. + if (this.state !== print_preview_new.State.FATAL_ERROR) { + this.$.state.transitTo(print_preview_new.State.NOT_READY); + } + break; + case print_preview.DestinationState.UPDATED: + if (!this.$.model.initialized()) { + this.$.model.applyStickySettings(); + } - this.$.state.transitTo(print_preview_new.State.NOT_READY); - this.destination_ = this.destinationStore_.selectedDestination; - }, + // <if expr="chromeos"> + this.$.model.applyDestinationSpecificPolicies(); + // </if> - /** @private */ - onDestinationUpdated_: function() { - // Notify observers, since destination_ == - // destinationStore_.selectedDestination and this event indicates - // destinationStore_.selectedDestination.capabilities has been updated. - this.notifyPath('destination_.capabilities'); - - if (!this.$.model.initialized()) { - this.$.model.applyStickySettings(); - } - - // <if expr="chromeos"> - if (this.destination_) { - this.$.model.applyDestinationSpecificPolicies(); - } - // </if> - - if (this.state == print_preview_new.State.NOT_READY || - this.state == print_preview_new.State.INVALID_PRINTER) { - this.$.state.transitTo(print_preview_new.State.READY); - if (this.isInKioskAutoPrintMode_) { - this.onPrintRequested_(); - } + if (this.state == print_preview_new.State.NOT_READY || + this.state == print_preview_new.State.INVALID_PRINTER) { + this.$.state.transitTo(print_preview_new.State.READY); + if (this.isInKioskAutoPrintMode_ || this.printRequested_) { + this.onPrintRequested_(); + // Reset in case printing fails. + this.printRequested_ = false; + } + } + break; + case print_preview.DestinationState.INVALID: + this.previewState_ = + print_preview_new.PreviewAreaState.INVALID_SETTINGS; + break; + case print_preview.DestinationState.UNSUPPORTED: + this.previewState_ = + print_preview_new.PreviewAreaState.UNSUPPORTED_CLOUD_PRINTER; + break; + // <if expr="chromeos"> + case print_preview.DestinationState.NO_DESTINATIONS: + this.$.state.transitTo(print_preview_new.State.INVALID_PRINTER); + this.$.previewArea.setNoDestinationsFound(); + break; + // </if> + default: + break; } }, @@ -471,7 +403,7 @@ print_preview.Metrics.PrintSettingsUiBucket .PRINT_WITH_SETTINGS_COLLAPSED); } - const destination = assert(this.destinationStore_.selectedDestination); + const destination = assert(this.destination_); const whenPrintDone = this.nativeLayer_.print(this.$.model.createPrintTicket( destination, this.openPdfInPreview_, @@ -494,6 +426,10 @@ /** @private */ onPrintRequested_: function() { + if (this.state === print_preview_new.State.NOT_READY) { + this.printRequested_ = true; + return; + } this.$.state.transitTo( this.$.previewArea.previewLoaded() ? print_preview_new.State.PRINTING : print_preview_new.State.HIDDEN); @@ -529,7 +465,7 @@ onPrintToCloud_: function(data) { assert( this.cloudPrintInterface_ != null, 'Google Cloud Print is not enabled'); - const destination = assert(this.destinationStore_.selectedDestination); + const destination = assert(this.destination_); this.cloudPrintInterface_.submit( destination, this.$.model.createCloudJobTicket(destination), this.documentSettings_.title, data); @@ -571,17 +507,6 @@ }, /** @private */ - onInvalidPrinter_: function() { - this.previewState_ = - print_preview_new.PreviewAreaState.UNSUPPORTED_CLOUD_PRINTER; - }, - - /** @private */ - onInvalidPrinterCapabilities_: function() { - this.previewState_ = print_preview_new.PreviewAreaState.INVALID_SETTINGS; - }, - - /** @private */ onPreviewAreaStateChanged_: function() { switch (this.previewState_) { case print_preview_new.PreviewAreaState.PREVIEW_FAILED: @@ -606,25 +531,6 @@ }, /** - * Updates the cloud print status to NOT_SIGNED_IN if there is an - * authentication error. - * @param {!CustomEvent<!cloudprint.CloudPrintInterfaceErrorEventDetail>} - * event Contains the error status - * @private - */ - checkCloudPrintStatus_: function(event) { - if (event.detail.status != 403 || this.isInAppKioskMode_) { - return; - } - - // Should not have sent a message to Cloud Print if cloud print is - // disabled. - assert(this.cloudPrintState_ !== print_preview.CloudPrintState.DISABLED); - this.cloudPrintState_ = print_preview.CloudPrintState.NOT_SIGNED_IN; - console.warn('Google Cloud Print Error: HTTP status 403'); - }, - - /** * Called when there was an error communicating with Google Cloud print. * Displays an error message in the print header. * @param {!CustomEvent<!cloudprint.CloudPrintInterfaceErrorEventDetail>} @@ -632,10 +538,9 @@ * @private */ onCloudPrintError_: function(event) { - this.checkCloudPrintStatus_(event); if (event.detail.status == 0 || (event.detail.status == 403 && !this.isInAppKioskMode_)) { - return; // No internet connectivity or handled by checkCloudPrintStatus_. + return; // No internet connectivity or not signed in. } this.errorMessage_ = event.detail.message; this.$.state.transitTo(print_preview_new.State.FATAL_ERROR); @@ -712,37 +617,9 @@ this.$.documentInfo.inFlightRequestId = e.detail; }, - // <if expr="chromeos"> - /** @private */ - onNoDestinationsFound_: function() { - this.$.state.transitTo(print_preview_new.State.INVALID_PRINTER); - this.$.previewArea.setNoDestinationsFound(); - this.$.destinationSettings.noDestinationsFound = true; - }, - // </if> - /** @private */ close_: function() { this.$.state.transitTo(print_preview_new.State.CLOSING); }, - - /** - * @param {!CustomEvent<string>} e Event containing the new active user - * account. - * @private - */ - onAccountChange_: function(e) { - this.$.userInfo.updateActiveUser(e.detail); - }, - - /** @private */ - onActiveUserChanged_: function() { - if (!this.activeUser_) { - return; - } - - assert(this.cloudPrintState_ !== print_preview.CloudPrintState.DISABLED); - this.cloudPrintState_ = print_preview.CloudPrintState.SIGNED_IN; - }, }); })();
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.js b/chrome/browser/resources/print_preview/new/destination_dialog.js index 2aae2bd2..db2ba5f 100644 --- a/chrome/browser/resources/print_preview/new/destination_dialog.js +++ b/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -177,7 +177,7 @@ .DESTINATION_CLOSED_UNCHANGED : print_preview.Metrics.DestinationSearchBucket .DESTINATION_CLOSED_CHANGED); - if (cancelled && this.currentDestinationAccount && + if (this.currentDestinationAccount && this.currentDestinationAccount !== this.activeUser) { this.fire('account-change', this.currentDestinationAccount); }
diff --git a/chrome/browser/resources/print_preview/new/destination_select.html b/chrome/browser/resources/print_preview/new/destination_select.html index 84fc622..a50baa6 100644 --- a/chrome/browser/resources/print_preview/new/destination_select.html +++ b/chrome/browser/resources/print_preview/new/destination_select.html
@@ -37,7 +37,7 @@ </style> <select class="md-select" aria-label$="[[i18n(destinationLabel)]]" style="background-image: - [[getIconImage_(destination.icon, noDestinationsFound)]], + [[getIconImage_(destination.icon, destinationState)]], url(chrome://resources/images/arrow_down.svg);" disabled$="[[disabled]]" value="{{selectedValue::change}}"> @@ -51,10 +51,13 @@ hidden$="[[!showGoogleDrive_]]"> $i18n{printToGoogleDrive} </option> - <option value="noDestinations" hidden$="[[!noDestinationsFound]]" - selected$="[[noDestinationsFound]]"> +<if expr="chromeos"> + <option value="noDestinations" + hidden$="[[!showNoDestinations_(destinationState)]]" + selected$="[[showNoDestinations_(destinationState)]]"> $i18n{noDestinationsMessage} </option> +</if> <option value="seeMore" aria-label$="[[i18n(seeMoreDestinationsLabel)]]"> $i18n{seeMore} </option>
diff --git a/chrome/browser/resources/print_preview/new/destination_select.js b/chrome/browser/resources/print_preview/new/destination_select.js index 5e02797e..8b81491 100644 --- a/chrome/browser/resources/print_preview/new/destination_select.js +++ b/chrome/browser/resources/print_preview/new/destination_select.js
@@ -18,9 +18,10 @@ /** @type {!print_preview.Destination} */ destination: Object, - disabled: Boolean, + /** @type {!print_preview.DestinationState} */ + destinationState: Number, - noDestinationsFound: Boolean, + disabled: Boolean, /** @type {!Array<!print_preview.Destination>} */ recentDestinationList: Array, @@ -81,8 +82,14 @@ return ''; } - const iconSetAndIcon = - this.noDestinationsFound ? ['cr', 'error'] : icon.split(':'); + let iconSetAndIcon = null; + // <if expr="chromeos"> + if (this.destinationState === + print_preview.DestinationState.NO_DESTINATIONS) { + iconSetAndIcon = ['cr', 'error']; + } + // </if> + iconSetAndIcon = iconSetAndIcon || icon.split(':'); const iconset = /** @type {Polymer.IronIconsetSvg} */ ( this.meta_.byKey(iconSetAndIcon[0])); const serializer = new XMLSerializer(); @@ -97,4 +104,12 @@ onProcessSelectChange: function(value) { this.fire('selected-option-change', value); }, + + // <if expr="chromeos"> + /** @private */ + showNoDestinations_: function() { + return this.destinationState === + print_preview.DestinationState.NO_DESTINATIONS; + }, + // </if> });
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.html b/chrome/browser/resources/print_preview/new/destination_settings.html index 9e1553a..a1133fb 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.html +++ b/chrome/browser/resources/print_preview/new/destination_settings.html
@@ -5,6 +5,8 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/event_tracker.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="../cloud_print_interface.html"> <link rel="import" href="../data/destination.html"> <link rel="import" href="../data/destination_store.html"> <link rel="import" href="../data/invitation_store.html"> @@ -13,8 +15,8 @@ <link rel="import" href="destination_select.html"> <link rel="import" href="print_preview_shared_css.html"> <link rel="import" href="throbber_css.html"> +<link rel="import" href="settings_behavior.html"> <link rel="import" href="settings_section.html"> -<link rel="import" href="state.html"> <link rel="import" href="strings.html"> <dom-module id="print-preview-destination-settings"> @@ -45,6 +47,10 @@ min-height: 0; } </style> + <print-preview-user-info id="userInfo" active-user="{{activeUser_}}" + users="{{users_}}" destination-store="[[destinationStore_]]" + invitation-store="[[invitationStore_]]"> + </print-preview-user-info> <print-preview-settings-section> <span slot="title">$i18n{destinationLabel}</span> <div slot="controls"> @@ -53,13 +59,12 @@ </div> <print-preview-destination-select id="destinationSelect" hidden$="[[!shouldHideSpinner_]]" - active-user="[[activeUser]]" + active-user="[[activeUser_]]" app-kiosk-mode="[[appKioskMode]]" - cloud-print-state="[[cloudPrintState]]" + cloud-print-state="[[cloudPrintState_]]" destination="[[destination]]" - disabled="[[shouldDisableDropdown_(destinationStore, disabled, - shouldHideSpinner_, state)]]" - no-destinations-found="[[noDestinationsFound]]" + destination-state="[[destinationState]]" + disabled="[[shouldDisableDropdown_(destinationState, disabled)]]" recent-destination-list="[[recentDestinationList_]]" on-selected-option-change="onSelectedDestinationOptionChange_"> </print-preview-destination-select> @@ -75,13 +80,13 @@ <cr-lazy-render id="destinationDialog"> <template> <print-preview-destination-dialog - cloud-print-state="[[cloudPrintState]]" - destination-store="[[destinationStore]]" - invitation-store="[[invitationStore]]" + cloud-print-state="[[cloudPrintState_]]" + destination-store="[[destinationStore_]]" + invitation-store="[[invitationStore_]]" recent-destination-list="[[recentDestinationList_]]" - active-user="[[activeUser]]" users="[[users]]" + active-user="[[activeUser_]]" users="[[users_]]" current-destination-account="[[destination.account]]" - on-close="onDialogClose_"> + on-account-change="onAccountChange_" on-close="onDialogClose_"> </print-preview-destination-dialog> </template> </cr-lazy-render>
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.js b/chrome/browser/resources/print_preview/new/destination_settings.js index 195bb8e..4a415a68 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.js +++ b/chrome/browser/resources/print_preview/new/destination_settings.js
@@ -2,52 +2,64 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +(function() { +'use strict'; + +/** @type {number} Number of recent destinations to save. */ +const NUM_PERSISTED_DESTINATIONS = 3; + Polymer({ is: 'print-preview-destination-settings', - behaviors: [I18nBehavior], + behaviors: [ + I18nBehavior, + SettingsBehavior, + WebUIListenerBehavior, + ], properties: { - activeUser: String, - appKioskMode: Boolean, - /** @type {!print_preview.CloudPrintState} */ - cloudPrintState: { - type: Number, - observer: 'onCloudPrintStateChanged_', - }, - - /** @type {!print_preview.Destination} */ + /** @type {?print_preview.Destination} */ destination: { type: Object, - observer: 'onDestinationSet_', + notify: true, + value: null, }, - /** @type {?print_preview.DestinationStore} */ - destinationStore: { - type: Object, - observer: 'onDestinationStoreSet_', + /** @type {!print_preview.DestinationState} */ + destinationState: { + type: Number, + notify: true, + value: print_preview.DestinationState.INIT, + observer: 'updateDestinationSelect_', }, disabled: Boolean, - /** @type {?print_preview.InvitationStore} */ - invitationStore: Object, - - noDestinationsFound: { - type: Boolean, - value: false, + /** @private {string} */ + activeUser_: { + type: String, + observer: 'onActiveUserChanged_', }, - /** @type {!Array<!print_preview.RecentDestination>} */ - recentDestinations: Array, + /** @private {!print_preview.CloudPrintState} */ + cloudPrintState_: { + type: Number, + value: print_preview.CloudPrintState.DISABLED, + }, - /** @type {!print_preview_new.State} */ - state: Number, + /** @private {?print_preview.DestinationStore} */ + destinationStore_: { + type: Object, + value: null, + }, - /** @type {!Array<string>} */ - users: Array, + /** @private {?print_preview.InvitationStore} */ + invitationStore_: { + type: Object, + value: null, + }, /** @private {!Array<!print_preview.Destination>} */ recentDestinationList_: Array, @@ -55,8 +67,7 @@ /** @private */ shouldHideSpinner_: { type: Boolean, - computed: 'computeShouldHideSpinner_(' + - 'destination, noDestinationsFound, cloudPrintState)', + computed: 'computeShouldHideSpinner_(destinationState)', }, /** @private {string} */ @@ -64,33 +75,172 @@ type: String, computed: 'computeStatusText_(destination)', }, - }, - observers: [ - 'updateRecentDestinationList_(' + - 'recentDestinations.*, activeUser, destinationStore)', - 'updateDestinationSelect_(' + - 'destination, noDestinationsFound, cloudPrintState)', - ], + /** @private {!Array<string>} */ + users_: Array, + }, /** @private {!EventTracker} */ tracker_: new EventTracker(), - /** @private */ - onDestinationStoreSet_: function() { - if (!this.destinationStore) { - return; - } - + /** @override */ + attached: function() { + this.destinationStore_ = + new print_preview.DestinationStore(this.addWebUIListener.bind(this)); + this.invitationStore_ = new print_preview.InvitationStore(); + this.tracker_.add( + this.destinationStore_, + print_preview.DestinationStore.EventType.DESTINATION_SELECT, + this.onDestinationSelect_.bind(this)); + this.tracker_.add( + this.destinationStore_, + print_preview.DestinationStore.EventType + .SELECTED_DESTINATION_CAPABILITIES_READY, + this.onDestinationCapabilitiesReady_.bind(this)); + this.tracker_.add( + this.destinationStore_, print_preview.DestinationStore.EventType.ERROR, + this.onDestinationError_.bind(this)); // Need to update the recent list when the destination store inserts // destinations, in case any recent destinations have been added to the // store. At startup, recent destinations can be in the sticky settings, // but they should not be displayed in the dropdown until they have been // fetched by the DestinationStore, to ensure that they still exist. this.tracker_.add( - assert(this.destinationStore), + assert(this.destinationStore_), print_preview.DestinationStore.EventType.DESTINATIONS_INSERTED, - this.updateRecentDestinationList_.bind(this)); + this.updateDropdownDestinations_.bind(this)); + }, + + /** @param {!cloudprint.CloudPrintInterface} cloudPrintInterface */ + setCloudPrintInterface: function(cloudPrintInterface) { + [cloudprint.CloudPrintInterfaceEventType.SEARCH_FAILED, + cloudprint.CloudPrintInterfaceEventType.PRINTER_FAILED, + ].forEach(eventType => { + this.tracker_.add( + cloudPrintInterface.getEventTarget(), eventType, + this.checkCloudPrintStatus_.bind(this)); + }); + this.$.userInfo.setCloudPrintInterface(cloudPrintInterface); + this.destinationStore_.setCloudPrintInterface(cloudPrintInterface); + this.invitationStore_.setCloudPrintInterface(cloudPrintInterface); + assert(this.cloudPrintState_ === print_preview.CloudPrintState.DISABLED); + this.cloudPrintState_ = print_preview.CloudPrintState.ENABLED; + }, + + /** + * @param {string} defaultPrinter The system default printer ID. + * @param {string} serializedDefaultDestinationRulesStr String with rules for + * selecting a default destination. + */ + initDestinationStore: function( + defaultPrinter, serializedDefaultDestinationRulesStr) { + this.destinationStore_.init( + this.appKioskMode, defaultPrinter, serializedDefaultDestinationRulesStr, + /** @type {!Array<print_preview.RecentDestination>} */ + (this.getSettingValue('recentDestinations'))); + }, + + /** @private */ + onActiveUserChanged_: function() { + if (!this.activeUser_) { + return; + } + + assert(this.cloudPrintState_ !== print_preview.CloudPrintState.DISABLED); + this.cloudPrintState_ = print_preview.CloudPrintState.SIGNED_IN; + + // Load docs, in case the user was not signed in previously and signed in + // from the destinations dialog. + this.destinationStore_.startLoadCookieDestination( + print_preview.Destination.GooglePromotedId.DOCS); + + // Load any recent cloud destinations for the dropdown. + const recentDestinations = this.getSettingValue('recentDestinations'); + recentDestinations.forEach(destination => { + if (destination.origin === print_preview.DestinationOrigin.COOKIES && + (destination.account === this.activeUser_ || + destination.account === '')) { + this.destinationStore_.startLoadCookieDestination(destination.id); + } + }); + + if (this.destinationState === print_preview.DestinationState.SELECTED && + this.destination.origin === print_preview.DestinationOrigin.COOKIES) { + this.destinationState = this.destination.capabilities ? + print_preview.DestinationState.UPDATED : + print_preview.DestinationState.SET; + } + this.updateDropdownDestinations_(); + }, + + /** @private */ + onDestinationSelect_: function() { + this.destinationState = print_preview.DestinationState.SELECTED; + this.destination = this.destinationStore_.selectedDestination; + this.updateRecentDestinations_(); + if (this.cloudPrintState_ === print_preview.CloudPrintState.ENABLED) { + // Only try to load the docs destination for now. If this request + // succeeds, it will trigger a transition to SIGNED_IN, and we can + // load the remaining destinations. Otherwise, it will transition to + // NOT_SIGNED_IN, so we will not do this more than once. + this.destinationStore_.startLoadCookieDestination( + print_preview.Destination.GooglePromotedId.DOCS); + } + if (this.cloudPrintState_ === print_preview.CloudPrintState.SIGNED_IN || + this.destination.origin !== print_preview.DestinationOrigin.COOKIES) { + this.destinationState = print_preview.DestinationState.SET; + } + }, + + /** @private */ + onDestinationCapabilitiesReady_: function() { + this.notifyPath('destination.capabilities'); + if (this.destinationState === print_preview.DestinationState.SET) { + this.destinationState = print_preview.DestinationState.UPDATED; + } + this.updateRecentDestinations_(); + }, + + /** + * @param {!CustomEvent<!print_preview.DestinationErrorType>} e + * @private + */ + onDestinationError_: function(e) { + switch (e.detail) { + case print_preview.DestinationErrorType.INVALID: + this.destinationState = print_preview.DestinationState.INVALID; + break; + case print_preview.DestinationErrorType.UNSUPPORTED: + this.destinationState = print_preview.DestinationState.UNSUPPORTED; + break; + // <if expr="chromeos"> + case print_preview.DestinationErrorType.NO_DESTINATIONS: + this.noDestinationsFound_ = true; + this.destinationState = print_preview.DestinationState.NO_DESTINATIONS; + break; + // </if> + default: + break; + } + }, + + /** + * Updates the cloud print status to NOT_SIGNED_IN if there is an + * authentication error. + * @param {!CustomEvent<!cloudprint.CloudPrintInterfaceErrorEventDetail>} + * event Contains the error status + * @private + */ + checkCloudPrintStatus_: function(event) { + if (event.detail.status != 403 || this.appKioskMode) { + return; + } + + // Should not have sent a message to Cloud Print if cloud print is + // disabled. + assert(this.cloudPrintState_ !== print_preview.CloudPrintState.DISABLED); + this.cloudPrintState_ = print_preview.CloudPrintState.NOT_SIGNED_IN; + console.warn('Google Cloud Print Error: HTTP status 403'); }, /** @@ -104,32 +254,60 @@ }, /** @private */ - updateRecentDestinationList_: function() { - if (!this.recentDestinations || !this.destinationStore) { + updateRecentDestinations_: function() { + if (!this.destination) { return; } - const recentDestinations = []; - let update = false; - const existingKeys = this.recentDestinationList_ ? - this.recentDestinationList_.map(listItem => listItem.key) : - []; - this.recentDestinations.forEach(recentDestination => { + // Determine if this destination is already in the recent destinations, + // and where in the array it is located. + const newDestination = + print_preview.makeRecentDestination(assert(this.destination)); + const recentDestinations = this.getSettingValue('recentDestinations'); + let indexFound = recentDestinations.findIndex(function(recent) { + return ( + newDestination.id == recent.id && + newDestination.origin == recent.origin); + }); + + // No change + if (indexFound == 0 && + recentDestinations[0].capabilities == newDestination.capabilities) { + return; + } + const isNew = indexFound == -1; + + // Shift the array so that the nth most recent destination is located at + // index n. + if (isNew && recentDestinations.length == NUM_PERSISTED_DESTINATIONS) { + indexFound = NUM_PERSISTED_DESTINATIONS - 1; + } + if (indexFound != -1) { + this.setSettingSplice('recentDestinations', indexFound, 1, null); + } + + // Add the most recent destination + this.setSettingSplice('recentDestinations', 0, 0, newDestination); + if (!this.destinationIsDriveOrPdf_(newDestination) && isNew) { + this.updateDropdownDestinations_(); + } + }, + + /** @private */ + updateDropdownDestinations_: function() { + const recentDestinations = this.getSettingValue('recentDestinations'); + + const dropdownDestinations = []; + recentDestinations.forEach(recentDestination => { const key = print_preview.createRecentDestinationKey(recentDestination); - const destination = this.destinationStore.getDestinationByKey(key); + const destination = this.destinationStore_.getDestinationByKey(key); if (destination && !this.destinationIsDriveOrPdf_(recentDestination) && - (!destination.account || destination.account == this.activeUser)) { - recentDestinations.push(destination); - update = update || !existingKeys.includes(key); + (!destination.account || destination.account == this.activeUser_)) { + dropdownDestinations.push(destination); } }); - // Only update the list if new destinations have been added to it. - // Re-ordering the dropdown items every time the selected item changes is - // a bad experience for keyboard users. - if (update) { - this.recentDestinationList_ = recentDestinations; - } + this.recentDestinationList_ = dropdownDestinations; }, /** @@ -137,54 +315,24 @@ * @private */ shouldDisableDropdown_: function() { - return !this.destinationStore || this.noDestinationsFound || - !this.shouldHideSpinner_ || - (this.disabled && this.state != print_preview_new.State.NOT_READY && - this.state != print_preview_new.State.INVALID_PRINTER); - }, - - /** @private */ - onCloudPrintStateChanged_: function() { - if (this.cloudPrintState !== print_preview.CloudPrintState.SIGNED_IN) { - return; + // <if expr="chromeos"> + if (this.destinationState === + print_preview.DestinationState.NO_DESTINATIONS) { + return true; } + // </if> - // Load docs, in case the user was not signed in previously and signed in - // from the destinations dialog. - this.destinationStore.startLoadCookieDestination( - print_preview.Destination.GooglePromotedId.DOCS); - - // Load any recent cloud destinations for the dropdown. - this.recentDestinations.forEach(destination => { - if (destination.origin === print_preview.DestinationOrigin.COOKIES && - (destination.account === this.activeUser || - destination.account === '')) { - this.destinationStore.startLoadCookieDestination(destination.id); - } - }); - }, - - /** @private */ - onDestinationSet_: function() { - if (this.cloudPrintState === print_preview.CloudPrintState.ENABLED) { - // Only try to load the docs destination for now. If this request - // succeeds, it will trigger a transition to SIGNED_IN, and we can - // load the remaining destinations. Otherwise, it will transition to - // NOT_SIGNED_IN, so we will not do this more than once. - this.destinationStore.startLoadCookieDestination( - print_preview.Destination.GooglePromotedId.DOCS); - } + return this.destinationState === print_preview.DestinationState.INIT || + this.destinationState === print_preview.DestinationState.SELECTED || + (this.disabled && + (this.destinationState === print_preview.DestinationState.SET || + this.destinationState === print_preview.DestinationState.UPDATED)); }, /** @private */ computeShouldHideSpinner_: function() { - if (this.noDestinationsFound) { - return true; - } - - return !!this.destination && - (this.destination.origin !== print_preview.DestinationOrigin.COOKIES || - this.cloudPrintState === print_preview.CloudPrintState.SIGNED_IN); + return this.destinationState !== print_preview.DestinationState.INIT && + this.destinationState !== print_preview.DestinationState.SELECTED; }, /** @@ -209,16 +357,25 @@ onSelectedDestinationOptionChange_: function(e) { const value = e.detail; if (value === 'seeMore') { - this.destinationStore.startLoadAllDestinations(); - if (this.activeUser) { - this.invitationStore.startLoadingInvitations(this.activeUser); + this.destinationStore_.startLoadAllDestinations(); + if (this.activeUser_) { + this.invitationStore_.startLoadingInvitations(this.activeUser_); } this.$.destinationDialog.get().show(); } else { - this.destinationStore.selectDestinationByKey(value); + this.destinationStore_.selectDestinationByKey(value); } }, + /** + * @param {!CustomEvent<string>} e Event containing the new active user + * account. + * @private + */ + onAccountChange_: function(e) { + this.$.userInfo.updateActiveUser(e.detail); + }, + /** @private */ onDialogClose_: function() { // Reset the select value if the user dismissed the dialog without @@ -229,10 +386,15 @@ /** @private */ updateDestinationSelect_: function() { - if (!this.destination || - (this.destination.origin === print_preview.DestinationOrigin.COOKIES && - this.cloudPrintState !== print_preview.CloudPrintState.SIGNED_IN) || - this.noDestinationsFound) { + // <if expr="chromeos"> + if (this.destinationState === + print_preview.DestinationState.NO_DESTINATIONS) { + return; + } + // </if> + + if (this.destinationState === print_preview.DestinationState.INIT || + this.destinationState === print_preview.DestinationState.SELECTED) { return; } @@ -249,3 +411,4 @@ } }, }); +})();
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js index ecb1461..3dc1f34 100644 --- a/chrome/browser/resources/print_preview/new/model.js +++ b/chrome/browser/resources/print_preview/new/model.js
@@ -69,15 +69,13 @@ (function() { 'use strict'; -/** @type {number} Number of recent destinations to save. */ -const NUM_DESTINATIONS = 3; - /** * Sticky setting names. Alphabetical except for fitToPage, which must be set * after scaling in updateFromStickySettings(). * @type {!Array<string>} */ const STICKY_SETTING_NAMES = [ + 'recentDestinations', 'collate', 'color', 'cssBackground', @@ -300,6 +298,14 @@ setByPolicy: false, key: '', }, + recentDestinations: { + value: [], + unavailableValue: [], + valid: true, + available: true, + setByPolicy: false, + key: 'recentDestinations', + }, }; // <if expr="chromeos"> value.pin = { @@ -322,10 +328,7 @@ }, /** @type {print_preview.Destination} */ - destination: { - type: Object, - notify: true, - }, + destination: Object, /** @type {!print_preview.DocumentSettings} */ documentSettings: Object, @@ -335,15 +338,6 @@ /** @type {!print_preview.Size} */ pageSize: Object, - - /** @type {!Array<!print_preview.RecentDestination>} */ - recentDestinations: { - type: Array, - notify: true, - value: function() { - return []; - }, - }, }, observers: [ @@ -354,7 +348,6 @@ 'updateHeaderFooterAvailable_(' + 'margins, settings.margins.value, ' + 'settings.customMargins.value, settings.mediaSize.value)', - 'updateRecentDestinations_(destination, destination.capabilities)', 'stickySettingsChanged_(' + 'settings.collate.value, settings.layout.value, settings.color.value,' + 'settings.mediaSize.value, settings.margins.value, ' + @@ -362,7 +355,7 @@ 'settings.fitToPage.value, settings.customScaling.value, ' + 'settings.scaling.value, settings.duplex.value, ' + 'settings.headerFooter.value, settings.cssBackground.value, ' + - 'settings.vendorItems.value)', + 'settings.vendorItems.value, settings.recentDestinations.value.*)', 'stickySettingsChanged_(settings.pin.value)', ], @@ -678,53 +671,13 @@ } }, - /** @private */ - updateRecentDestinations_: function() { - if (!this.initialized_ || !this.destination) { - return; - } - - // Determine if this destination is already in the recent destinations, - // and where in the array it is located. - const newDestination = - print_preview.makeRecentDestination(assert(this.destination)); - let indexFound = this.recentDestinations.findIndex(function(recent) { - return ( - newDestination.id == recent.id && - newDestination.origin == recent.origin); - }); - - // No change - if (indexFound == 0 && - this.recentDestinations[0].capabilities == - newDestination.capabilities) { - return; - } - - // Shift the array so that the nth most recent destination is located at - // index n. - if (indexFound == -1 && - this.recentDestinations.length == NUM_DESTINATIONS) { - indexFound = NUM_DESTINATIONS - 1; - } - if (indexFound != -1) { - this.recentDestinations.splice(indexFound, 1); - } - - // Add the most recent destination - this.splice('recentDestinations', 0, 0, newDestination); - - // Persist sticky settings. - this.stickySettingsChanged_(); - }, - /** * Caches the sticky settings and sets up the recent destinations. Sticky * settings will be applied when destinaton capabilities have been retrieved. * @param {?string} savedSettingsStr The sticky settings from native layer */ setStickySettings: function(savedSettingsStr) { - assert(!this.stickySettings_ && this.recentDestinations.length == 0); + assert(!this.stickySettings_); if (!savedSettingsStr) { return; @@ -746,7 +699,9 @@ if (!Array.isArray(recentDestinations)) { recentDestinations = [recentDestinations]; } - this.recentDestinations = recentDestinations; + // Initialize recent destinations early so that the destination store can + // start trying to fetch them. + this.setSetting('recentDestinations', recentDestinations); this.stickySettings_ = savedSettings; }, @@ -797,7 +752,6 @@ this.initialized_ = true; this.updateManaged_(); this.stickySettings_ = null; - this.updateRecentDestinations_(); this.stickySettingsChanged_(); }, @@ -865,7 +819,6 @@ const serialization = { version: 2, - recentDestinations: this.recentDestinations, }; STICKY_SETTING_NAMES.forEach(settingName => {
diff --git a/chrome/browser/resources/print_preview/new/settings_behavior.js b/chrome/browser/resources/print_preview/new/settings_behavior.js index 7e1784e..791cab15 100644 --- a/chrome/browser/resources/print_preview/new/settings_behavior.js +++ b/chrome/browser/resources/print_preview/new/settings_behavior.js
@@ -88,6 +88,24 @@ /** * @param {string} settingName Name of the setting to set + * @param {number} start + * @param {number} end + * @param {*} newValue The value to add (if any). + */ + setSettingSplice: function(settingName, start, end, newValue) { + const setting = this.getSetting(settingName); + if (setting.setByPolicy) { + return; + } + if (newValue) { + this.splice(`settings.${settingName}.value`, start, end, newValue); + } else { + this.splice(`settings.${settingName}.value`, start, end); + } + }, + + /** + * @param {string} settingName Name of the setting to set * @param {boolean} valid Whether the setting value is currently valid. */ setSettingValid: function(settingName, valid) {
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd index 1f94fee1..ea4d5db 100644 --- a/chrome/browser/resources/print_preview/print_preview_resources.grd +++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -223,16 +223,19 @@ type="chrome_html" /> <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_SELECT_HTML" file="new/destination_select.html" - type="chrome_html" /> + type="chrome_html" + preprocess="true" /> <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_SELECT_JS" file="new/destination_select.js" - type="chrome_html" /> + type="chrome_html" + preprocess="true" /> <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_SETTINGS_HTML" file="new/destination_settings.html" type="chrome_html" /> <structure name="IDR_PRINT_PREVIEW_NEW_DESTINATION_SETTINGS_JS" file="new/destination_settings.js" - type="chrome_html" /> + type="chrome_html" + preprocess="true" /> <structure name="IDR_PRINT_PREVIEW_NEW_PAGES_SETTINGS_HTML" file="new/pages_settings.html" type="chrome_html" />
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html index 60fc7482..c99aed2 100644 --- a/chrome/browser/resources/settings/settings.html +++ b/chrome/browser/resources/settings/settings.html
@@ -16,8 +16,13 @@ touch-action: manipulation; } - html.loading { - border-top: 56px solid var(--md-toolbar-color); + html.loading::before { + background-color: var(--md-toolbar-color); + border-bottom: var(--md-toolbar-border); + box-sizing: border-box; + content: ''; + display: block; + height: var(--md-toolbar-height); } </style> </head>
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chrome/browser/resources/settings/settings_ui/settings_ui.html index 519cbc5..372b651 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.html +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -38,7 +38,6 @@ cr-toolbar { @apply --layout-center; - background-color: var(--md-toolbar-color); min-height: 56px; z-index: 2; }
diff --git a/chrome/browser/ui/blocked_content/scoped_visibility_tracker.cc b/chrome/browser/scoped_visibility_tracker.cc similarity index 85% rename from chrome/browser/ui/blocked_content/scoped_visibility_tracker.cc rename to chrome/browser/scoped_visibility_tracker.cc index 64ca553..91288767 100644 --- a/chrome/browser/ui/blocked_content/scoped_visibility_tracker.cc +++ b/chrome/browser/scoped_visibility_tracker.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/blocked_content/scoped_visibility_tracker.h" +#include "chrome/browser/scoped_visibility_tracker.h" #include <utility> @@ -27,8 +27,9 @@ Update(false /* in_foreground */); } -base::TimeDelta ScopedVisibilityTracker::GetForegroundDuration() { - Update(currently_in_foreground_); +base::TimeDelta ScopedVisibilityTracker::GetForegroundDuration() const { + if (currently_in_foreground_) + return foreground_duration_ + (tick_clock_->NowTicks() - last_time_shown_); return foreground_duration_; }
diff --git a/chrome/browser/ui/blocked_content/scoped_visibility_tracker.h b/chrome/browser/scoped_visibility_tracker.h similarity index 77% rename from chrome/browser/ui/blocked_content/scoped_visibility_tracker.h rename to chrome/browser/scoped_visibility_tracker.h index a84efac2..203222a 100644 --- a/chrome/browser/ui/blocked_content/scoped_visibility_tracker.h +++ b/chrome/browser/scoped_visibility_tracker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_SCOPED_VISIBILITY_TRACKER_H_ -#define CHROME_BROWSER_UI_BLOCKED_CONTENT_SCOPED_VISIBILITY_TRACKER_H_ +#ifndef CHROME_BROWSER_SCOPED_VISIBILITY_TRACKER_H_ +#define CHROME_BROWSER_SCOPED_VISIBILITY_TRACKER_H_ #include <memory> @@ -25,7 +25,7 @@ void OnShown(); void OnHidden(); - base::TimeDelta GetForegroundDuration(); + base::TimeDelta GetForegroundDuration() const; private: void Update(bool in_foreground); @@ -39,4 +39,4 @@ DISALLOW_COPY_AND_ASSIGN(ScopedVisibilityTracker); }; -#endif // CHROME_BROWSER_UI_BLOCKED_CONTENT_SCOPED_VISIBILITY_TRACKER_H_ +#endif // CHROME_BROWSER_SCOPED_VISIBILITY_TRACKER_H_
diff --git a/chrome/browser/ui/blocked_content/scoped_visibility_tracker_unittest.cc b/chrome/browser/scoped_visibility_tracker_unittest.cc similarity index 97% rename from chrome/browser/ui/blocked_content/scoped_visibility_tracker_unittest.cc rename to chrome/browser/scoped_visibility_tracker_unittest.cc index 4ca157cc..910b5b202 100644 --- a/chrome/browser/ui/blocked_content/scoped_visibility_tracker_unittest.cc +++ b/chrome/browser/scoped_visibility_tracker_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/blocked_content/scoped_visibility_tracker.h" +#include "chrome/browser/scoped_visibility_tracker.h" #include <utility>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 48db711..6d146e9f 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -85,8 +85,6 @@ "blocked_content/popup_tracker.h", "blocked_content/safe_browsing_triggered_popup_blocker.cc", "blocked_content/safe_browsing_triggered_popup_blocker.h", - "blocked_content/scoped_visibility_tracker.cc", - "blocked_content/scoped_visibility_tracker.h", "blocked_content/tab_under_navigation_throttle.cc", "blocked_content/tab_under_navigation_throttle.h", "blocked_content/url_list_manager.cc", @@ -1046,6 +1044,8 @@ "tabs/tab_strip_model_order_controller.h", "tabs/tab_strip_model_stats_recorder.cc", "tabs/tab_strip_model_stats_recorder.h", + "tabs/tab_style.cc", + "tabs/tab_style.h", "tabs/tab_switch_event_latency_recorder.cc", "tabs/tab_switch_event_latency_recorder.h", "tabs/tab_utils.cc", @@ -2828,8 +2828,8 @@ "views/tabs/tab_strip_controller.h", "views/tabs/tab_strip_layout.cc", "views/tabs/tab_strip_layout.h", - "views/tabs/tab_style.cc", - "views/tabs/tab_style.h", + "views/tabs/tab_style_views.cc", + "views/tabs/tab_style_views.h", "views/tabs/window_finder.h", "views/task_manager_view.cc", "views/task_manager_view.h",
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.cc b/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.cc index 3c4786b..facddb09 100644 --- a/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.cc +++ b/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.cc
@@ -10,8 +10,7 @@ InternalAppIconLoader::InternalAppIconLoader(Profile* profile, int resource_size_in_dip, AppIconLoaderDelegate* delegate) - : AppIconLoader(profile, resource_size_in_dip, delegate), - resource_size_in_dip_(resource_size_in_dip) {} + : AppIconLoader(profile, resource_size_in_dip, delegate) {} InternalAppIconLoader::~InternalAppIconLoader() = default; @@ -27,7 +26,7 @@ std::unique_ptr<gfx::ImageSkia> image_skia = std::make_unique<gfx::ImageSkia>(app_list::GetIconForResourceId( - app_list::GetIconResourceIdByAppId(app_id), resource_size_in_dip_)); + app_list::GetIconResourceIdByAppId(app_id), icon_size_in_dip())); image_skia->EnsureRepsForSupportedScales(); icon_map_[app_id] = std::move(image_skia); UpdateImage(app_id);
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.h b/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.h index 2974fbf..601ed07 100644 --- a/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.h +++ b/chrome/browser/ui/app_list/internal_app/internal_app_icon_loader.h
@@ -32,9 +32,6 @@ private: using AppIDToIconMap = std::map<std::string, std::unique_ptr<gfx::ImageSkia>>; - // The preferred icon size. - int resource_size_in_dip_; - // Maps from internal app id to icon. AppIDToIconMap icon_map_;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 6be929a..e2c8120 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -149,8 +149,7 @@ std::make_unique<SettingsShortcutProvider>(profile)); } - if (app_list_features::IsAppShortcutSearchEnabled() && - arc::IsArcAllowedForProfile(profile)) { + if (arc::IsArcAllowedForProfile(profile)) { size_t app_shortcut_group_id = controller->AddGroup(kMaxAppShortcutResults, 1.0, kBoostOfApps); controller->AddProvider(
diff --git a/chrome/browser/ui/ash/assistant/device_actions.cc b/chrome/browser/ui/ash/assistant/device_actions.cc index 388f037..b52eea7 100644 --- a/chrome/browser/ui/ash/assistant/device_actions.cc +++ b/chrome/browser/ui/ash/assistant/device_actions.cc
@@ -139,6 +139,9 @@ arc::mojom::ActivityNamePtr activity = arc::mojom::ActivityName::New(); activity->package_name = package_name; auto intent = arc::mojom::IntentInfo::New(); + if (!app_info->action.empty()) + intent->action = app_info->action; + if (!app_info->intent.empty()) { intent->data = app_info->intent; } else {
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc index 3f2f7c5..8441002 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -344,6 +344,10 @@ TabStripModel::CLOSE_USER_GESTURE); } } else { + // These extra checks should gather info for http://crbug.com/937088 + CHECK(browser); + CHECK(browser->window()); + CHECK(browser->window()->GetNativeWindow()); multi_user_util::MoveWindowToCurrentDesktop( browser->window()->GetNativeWindow()); if (tab_index != kNoTab && tab_strip->ContainsIndex(tab_index))
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl.cc index cab8688..cf57767c 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl.cc
@@ -397,17 +397,21 @@ it->second->set_show_for_user(account_id); const AccountId& owner = GetWindowOwner(window); - if (owner.is_valid()) { + // Browser windows don't use kAvatarIconKey. See + // BrowserNonClientFrameViewAsh::UpdateProfileIcons(). + if (owner.is_valid() && !chrome::FindBrowserWithWindow(window)) { const user_manager::User* const window_owner = user_manager::UserManager::IsInitialized() ? user_manager::UserManager::Get()->FindUser(owner) : nullptr; + aura::Window* property_window = + features::IsUsingWindowService() ? window->GetRootWindow() : window; if (window_owner && teleported) { - window->SetProperty( + property_window->SetProperty( aura::client::kAvatarIconKey, new gfx::ImageSkia(GetAvatarImageForUser(window_owner))); } else { - window->ClearProperty(aura::client::kAvatarIconKey); + property_window->ClearProperty(aura::client::kAvatarIconKey); } }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc index 2e49ff4..95db1711 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc
@@ -1458,17 +1458,24 @@ SwitchActiveUser(user1); - // Window #0 has no kAvatarIconKey property before teloporting. - EXPECT_FALSE(window(0)->GetProperty(aura::client::kAvatarIconKey)); + // This ternary doesn't make a lot of sense because the windows in this + // AshTest aren't created via the window service, but it's necessary to mirror + // the code in MultiUserWindowManagerClientImpl, where the content window's + // root window is the Ash host window. + aura::Window* property_window = + features::IsUsingWindowService() ? window(0)->GetRootWindow() : window(0); + + // Window #0 has no kAvatarIconKey property before teleporting. + EXPECT_FALSE(property_window->GetProperty(aura::client::kAvatarIconKey)); // Teleport window #0 to user2 and kAvatarIconKey property is present. multi_user_window_manager_client()->ShowWindowForUser(window(0), user2); - EXPECT_TRUE(window(0)->GetProperty(aura::client::kAvatarIconKey)); + EXPECT_TRUE(property_window->GetProperty(aura::client::kAvatarIconKey)); - // Teloport window #0 back to its owner (user1) and kAvatarIconKey property is + // Teleport window #0 back to its owner (user1) and kAvatarIconKey property is // gone. multi_user_window_manager_client()->ShowWindowForUser(window(0), user1); - EXPECT_FALSE(window(0)->GetProperty(aura::client::kAvatarIconKey)); + EXPECT_FALSE(property_window->GetProperty(aura::client::kAvatarIconKey)); } // Tests that the window order is preserved when switching between users. Also
diff --git a/chrome/browser/ui/ash/tab_scrubber.cc b/chrome/browser/ui/ash/tab_scrubber.cc index e094bc73..cd25197b 100644 --- a/chrome/browser/ui/ash/tab_scrubber.cc +++ b/chrome/browser/ui/ash/tab_scrubber.cc
@@ -19,7 +19,7 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/gesture_detection/gesture_configuration.h" @@ -239,7 +239,7 @@ TabStrip* tab_strip = browser_view->tabstrip(); if (activate && highlighted_tab_ != -1) { Tab* tab = tab_strip->tab_at(highlighted_tab_); - tab->tab_style()->HideHover(GlowHoverController::HideStyle::kImmediate); + tab->tab_style()->HideHover(TabStyle::HideHoverStyle::kImmediate); int distance = std::abs(highlighted_tab_ - browser_->tab_strip_model()->active_index()); UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.ScrubDistance", distance, 1, 20, 21); @@ -318,13 +318,12 @@ if (highlighted_tab_ != -1) { Tab* tab = tab_strip_->tab_at(highlighted_tab_); - tab->tab_style()->HideHover(GlowHoverController::HideStyle::kImmediate); + tab->tab_style()->HideHover(TabStyle::HideHoverStyle::kImmediate); } if (new_index != browser_->tab_strip_model()->active_index()) { highlighted_tab_ = new_index; - new_tab->tab_style()->ShowHover( - GlowHoverController::ShowStyle::kPronounced); + new_tab->tab_style()->ShowHover(TabStyle::ShowHoverStyle::kPronounced); } else { highlighted_tab_ = -1; }
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc index 7da001c..2732a5e 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper.cc
@@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/time/tick_clock.h" -#include "chrome/browser/ui/blocked_content/scoped_visibility_tracker.h" +#include "chrome/browser/scoped_visibility_tracker.h" #include "chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/blocked_content/popup_tracker.h b/chrome/browser/ui/blocked_content/popup_tracker.h index 34fb180..fe9d011 100644 --- a/chrome/browser/ui/blocked_content/popup_tracker.h +++ b/chrome/browser/ui/blocked_content/popup_tracker.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/optional.h" #include "base/time/time.h" -#include "chrome/browser/ui/blocked_content/scoped_visibility_tracker.h" +#include "chrome/browser/scoped_visibility_tracker.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 3356cc5..1956d260 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2544,39 +2544,25 @@ } namespace { -class JSBooleanResultGetter { - public: - JSBooleanResultGetter() = default; - void OnJsExecutionDone(base::Closure callback, base::Value value) { - js_result_.reset(value.DeepCopy()); - callback.Run(); - } - bool GetResult() const { - bool res; - CHECK(js_result_); - CHECK(js_result_->GetAsBoolean(&res)); - return res; - } - - private: - std::unique_ptr<base::Value> js_result_; - DISALLOW_COPY_AND_ASSIGN(JSBooleanResultGetter); -}; void CheckDisplayModeMQ(const base::string16& display_mode, content::WebContents* web_contents) { base::string16 function = ASCIIToUTF16("(function() {return window.matchMedia('(display-mode: ") + display_mode + ASCIIToUTF16(")').matches;})();"); - JSBooleanResultGetter js_result_getter; - // Execute the JS to run the tests, and wait until it has finished. + bool js_result = false; base::RunLoop run_loop; web_contents->GetMainFrame()->ExecuteJavaScriptForTests( - function, base::BindOnce(&JSBooleanResultGetter::OnJsExecutionDone, - base::Unretained(&js_result_getter), - run_loop.QuitClosure())); + function, base::BindOnce( + [](base::OnceClosure quit_closure, bool* out_result, + base::Value value) { + DCHECK(value.is_bool()); + *out_result = value.GetBool(); + std::move(quit_closure).Run(); + }, + run_loop.QuitClosure(), &js_result)); run_loop.Run(); - EXPECT_TRUE(js_result_getter.GetResult()); + EXPECT_TRUE(js_result); } } // namespace
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc index e1c55b8..8733e118 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.cc +++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -489,8 +489,8 @@ return native_theme_; } -void GtkUi::SetNativeThemeOverride(const NativeThemeGetter& callback) { - native_theme_overrider_ = callback; +void GtkUi::SetNativeThemeOverride(NativeThemeGetter callback) { + native_theme_overrider_ = std::move(callback); } bool GtkUi::GetDefaultUsesSystemTheme() const {
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.h b/chrome/browser/ui/libgtkui/gtk_ui.h index 6bdb8bc7..68797e82 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.h +++ b/chrome/browser/ui/libgtkui/gtk_ui.h
@@ -36,9 +36,6 @@ GtkUi(); ~GtkUi() override; - typedef base::Callback<ui::NativeTheme*(aura::Window* window)> - NativeThemeGetter; - // Setters used by SettingsProvider: void SetWindowButtonOrdering( const std::vector<views::FrameButton>& leading_buttons, @@ -82,7 +79,7 @@ SkColor GetInactiveSelectionFgColor() const override; base::TimeDelta GetCursorBlinkInterval() const override; ui::NativeTheme* GetNativeTheme(aura::Window* window) const override; - void SetNativeThemeOverride(const NativeThemeGetter& callback) override; + void SetNativeThemeOverride(NativeThemeGetter callback) override; bool GetDefaultUsesSystemTheme() const override; void SetDownloadCount(int count) const override; void SetProgressFraction(float percentage) const override;
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc index 1986b41..8360333 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc +++ b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc
@@ -17,6 +17,7 @@ #include <vector> #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -64,8 +65,9 @@ // Runs DesktopWindowTreeHostX11::EnableEventListening() when the file-picker // is closed. -void OnFilePickerDestroy(base::Closure* callback) { - callback->Run(); +void OnFilePickerDestroy(base::OnceClosure* callback_raw) { + std::unique_ptr<base::OnceClosure> callback = base::WrapUnique(callback_raw); + std::move(*callback).Run(); } } // namespace @@ -190,10 +192,11 @@ // been captured and by turning off event listening, it is never // released. So we manually ensure there is no current capture. host->ReleaseCapture(); - std::unique_ptr<base::Closure> callback = - views::DesktopWindowTreeHostX11::GetHostForXID( - host->GetAcceleratedWidget()) - ->DisableEventListening(); + std::unique_ptr<base::OnceClosure> callback = + std::make_unique<base::OnceClosure>( + views::DesktopWindowTreeHostX11::GetHostForXID( + host->GetAcceleratedWidget()) + ->DisableEventListening()); // OnFilePickerDestroy() is called when |dialog| destroyed, which allows // to invoke the callback function to re-enable event handling on the // owning window.
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 2b54235..e0259dc 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1614,8 +1614,17 @@ if (!triggered_by_other_operation && (selection.active_tab_changed() || selection.selection_changed())) { if (selection.active_tab_changed()) { - tab_switch_event_latency_recorder_.OnWillChangeActiveTab( - base::TimeTicks::Now()); + auto now = base::TimeTicks::Now(); + if (selection.new_contents && + selection.new_contents->GetRenderWidgetHostView()) { + auto input_event_timestamp = + tab_switch_event_latency_recorder_.input_event_timestamp(); + // input_event_timestamp may be null in some cases, e.g. in tests. + selection.new_contents->GetRenderWidgetHostView() + ->SetLastTabChangeStartTime( + !input_event_timestamp.is_null() ? input_event_timestamp : now); + } + tab_switch_event_latency_recorder_.OnWillChangeActiveTab(now); } TabStripModelChange change; auto visibility_tracker = InstallRenderWigetVisibilityTracker(selection);
diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc new file mode 100644 index 0000000..00e4e8a --- /dev/null +++ b/chrome/browser/ui/tabs/tab_style.cc
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/tabs/tab_style.h" + +#include "ui/base/material_design/material_design_controller.h" +#include "ui/views/layout/layout_provider.h" + +namespace { + +// Thickness in DIPs of the separator painted on the left and right edges of +// the tab. +constexpr int kSeparatorThickness = 1; + +// Returns the height of the separator between tabs. +int GetSeparatorHeight() { + return ui::MaterialDesignController::touch_ui() ? 24 : 20; +} + +} // namespace + +TabStyle::~TabStyle() = default; + +// static +int TabStyle::GetStandardWidth() { + // The standard tab width is 240 DIP including both separators. + constexpr int kTabWidth = 240; + // The overlap includes one separator, so subtract it here. + return kTabWidth + GetTabOverlap() - kSeparatorThickness; +} + +// static +int TabStyle::GetPinnedWidth() { + constexpr int kTabPinnedContentWidth = 23; + return kTabPinnedContentWidth + GetContentsHorizontalInsetSize() * 2; +} + +// static +int TabStyle::GetTabOverlap() { + return GetCornerRadius() * 2 + kSeparatorThickness; +} + +// static +int TabStyle::GetDragHandleExtension(int height) { + return (height - GetSeparatorHeight()) / 2 - 1; +} + +// static +gfx::Insets TabStyle::GetTabInternalPadding() { + return gfx::Insets(0, GetCornerRadius()); +} + +// static +gfx::Size TabStyle::GetSeparatorSize() { + return gfx::Size(kSeparatorThickness, GetSeparatorHeight()); +} + +// static +gfx::Size TabStyle::GetPreviewImageSize() { + constexpr float kTabHoverCardPreviewImageAspectRatio = 16.0f / 9.0f; + const int width = GetStandardWidth(); + return gfx::Size(width, width / kTabHoverCardPreviewImageAspectRatio); +} + +// static +int TabStyle::GetCornerRadius() { + return views::LayoutProvider::Get()->GetCornerRadiusMetric( + views::EMPHASIS_HIGH); +} + +// static +int TabStyle::GetContentsHorizontalInsetSize() { + return GetCornerRadius() * 2; +}
diff --git a/chrome/browser/ui/views/tabs/tab_style.h b/chrome/browser/ui/tabs/tab_style.h similarity index 76% rename from chrome/browser/ui/views/tabs/tab_style.h rename to chrome/browser/ui/tabs/tab_style.h index 7393cfd..ed9b943 100644 --- a/chrome/browser/ui/views/tabs/tab_style.h +++ b/chrome/browser/ui/tabs/tab_style.h
@@ -1,24 +1,23 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_H_ -#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_H_ - -#include <memory> +#ifndef CHROME_BROWSER_UI_TABS_TAB_STYLE_H_ +#define CHROME_BROWSER_UI_TABS_TAB_STYLE_H_ #include "base/macros.h" -#include "chrome/browser/ui/views/tabs/glow_hover_controller.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/geometry/size.h" namespace gfx { class Canvas; } class SkPath; -class Tab; -// Holds all of the logic for rendering tabs, including preferred sizes, paths, +// Holds the basic logic for rendering tabs, including preferred sizes, paths, // etc. class TabStyle { public: @@ -54,6 +53,13 @@ kDips }; + enum class ShowHoverStyle { kSubtle, kPronounced }; + + enum class HideHoverStyle { + kGradual, // The hover should fade out. + kImmediate, // The hover should cut off, with no fade out. + }; + // If we want to draw vertical separators between tabs, these are the leading // and trailing separator stroke rectangles. struct SeparatorBounds { @@ -79,15 +85,6 @@ SkColor button_background_pressed_color; }; - // Creates an appropriate TabStyle instance for a particular tab. - // Caller is responsibly for the TabStyle object's lifespan and should delete - // it when finished. - // - // We've implemented this as a factory function so that when we're playing - // with new variatons on tab shapes we can have a few possible implementations - // and switch them in one place. - static std::unique_ptr<TabStyle> CreateForTab(Tab* tab); - virtual ~TabStyle(); // Gets the specific |path_type| associated with the specific |tab|. @@ -117,18 +114,10 @@ virtual void SetHoverLocation(const gfx::Point& location) = 0; // Shows the hover animation. - virtual void ShowHover(GlowHoverController::ShowStyle style) = 0; + virtual void ShowHover(ShowHoverStyle style) = 0; // Hides the hover animation. - virtual void HideHover(GlowHoverController::HideStyle style) = 0; - - // Returns the minimum possible width of a selected Tab. Selected tabs must - // always show a close button, and thus have a larger minimum size than - // unselected tabs. - static int GetMinimumActiveWidth(); - - // Returns the minimum possible width of a single unselected Tab. - static int GetMinimumInactiveWidth(); + virtual void HideHover(HideHoverStyle style) = 0; // Returns the preferred width of a single Tab, assuming space is // available. @@ -140,26 +129,36 @@ // Returns the overlap between adjacent tabs. static int GetTabOverlap(); - // Returns, for a tab of height |height|, how far the window top drag handle - // can extend down into inactive tabs or the new tab button. This behavior - // is not used in all cases. - static int GetDragHandleExtension(int height); - // Get the space only partially occupied by a tab that we should // consider to be padding rather than part of the body of the tab for // interaction purposes. static gfx::Insets GetTabInternalPadding(); // Gets the size of the separator drawn between tabs, if any. - // TODO(dfried): Move any logic that needs this inside tab_style.cc. static gfx::Size GetSeparatorSize(); + // Returns, for a tab of height |height|, how far the window top drag handle + // can extend down into inactive tabs or the new tab button. This behavior + // is not used in all cases. + static int GetDragHandleExtension(int height); + + // Gets the preferred size for tab previews, which could be screencaps, hero + // or og:image images, etc. + static gfx::Size GetPreviewImageSize(); + protected: // Avoid implicitly-deleted constructor. TabStyle() = default; + // Returns the radius of the outer corners of the tab shape. + static int GetCornerRadius(); + + // Returns how far from the leading and trailing edges of a tab the contents + // should actually be laid out. + static int GetContentsHorizontalInsetSize(); + private: DISALLOW_COPY_AND_ASSIGN(TabStyle); }; -#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_H_ +#endif // CHROME_BROWSER_UI_TABS_TAB_STYLE_H_
diff --git a/chrome/browser/ui/tabs/tab_switch_event_latency_recorder.h b/chrome/browser/ui/tabs/tab_switch_event_latency_recorder.h index c60f9a8..483171a 100644 --- a/chrome/browser/ui/tabs/tab_switch_event_latency_recorder.h +++ b/chrome/browser/ui/tabs/tab_switch_event_latency_recorder.h
@@ -30,6 +30,10 @@ // this do nothing. void OnWillChangeActiveTab(const base::TimeTicks change_time); + base::TimeTicks input_event_timestamp() const { + return input_event_timestamp_; + } + private: base::TimeTicks input_event_timestamp_ = base::TimeTicks(); base::Optional<EventType> event_type_ = base::nullopt;
diff --git a/chrome/browser/ui/thumbnails/OWNERS b/chrome/browser/ui/thumbnails/OWNERS index 4c6e5bc..3a92f21 100644 --- a/chrome/browser/ui/thumbnails/OWNERS +++ b/chrome/browser/ui/thumbnails/OWNERS
@@ -1 +1,2 @@ +dfried@chromium.org pbos@chromium.org
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc index 36faa4d1..da2df27 100644 --- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc +++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
@@ -118,17 +118,28 @@ return !profile || !search::IsInstantNTPURL(url, profile); } -void ChromeLocationBarModelDelegate::GetSecurityInfo( - security_state::SecurityInfo* result) const { +security_state::SecurityLevel ChromeLocationBarModelDelegate::GetSecurityLevel() + const { content::WebContents* web_contents = GetActiveWebContents(); // If there is no active WebContents (which can happen during toolbar // initialization), assume no security style. if (!web_contents) { - *result = security_state::SecurityInfo(); - return; + return security_state::NONE; } auto* helper = SecurityStateTabHelper::FromWebContents(web_contents); - helper->GetSecurityInfo(result); + return helper->GetSecurityLevel(); +} + +std::unique_ptr<security_state::VisibleSecurityState> +ChromeLocationBarModelDelegate::GetVisibleSecurityState() const { + content::WebContents* web_contents = GetActiveWebContents(); + // If there is no active WebContents (which can happen during toolbar + // initialization), assume no security info. + if (!web_contents) { + return std::make_unique<security_state::VisibleSecurityState>(); + } + auto* helper = SecurityStateTabHelper::FromWebContents(web_contents); + return helper->GetVisibleSecurityState(); } scoped_refptr<net::X509Certificate>
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h index 26d74e9..cbe5562 100644 --- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h +++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h
@@ -41,7 +41,9 @@ const GURL& url, const base::string16& formatted_url) const override; bool GetURL(GURL* url) const override; - void GetSecurityInfo(security_state::SecurityInfo* result) const override; + security_state::SecurityLevel GetSecurityLevel() const override; + std::unique_ptr<security_state::VisibleSecurityState> + GetVisibleSecurityState() const override; scoped_refptr<net::X509Certificate> GetCertificate() const override; const gfx::VectorIcon* GetVectorIconOverride() const override; bool IsOfflinePage() const override;
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc index faae780..79c24d7 100644 --- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc +++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
@@ -69,7 +69,7 @@ void ChromeBrowserMainExtraPartsViewsLinux::PreEarlyInitialization() { views::LinuxUI* gtk_ui = BuildGtkUi(); - gtk_ui->SetNativeThemeOverride(base::Bind(&GetNativeThemeForWindow)); + gtk_ui->SetNativeThemeOverride(base::BindRepeating(&GetNativeThemeForWindow)); views::LinuxUI::SetInstance(gtk_ui); }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc index 54ff176..62770522 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
@@ -90,8 +90,6 @@ DesktopMediaSourceView* DesktopMediaListView::GetSelection() { for (int i = 0; i < child_count(); ++i) { DesktopMediaSourceView* source_view = GetChild(i); - DCHECK_EQ(source_view->GetClassName(), - DesktopMediaSourceView::kDesktopMediaSourceViewClassName); if (source_view->is_selected()) return source_view; } @@ -144,19 +142,18 @@ if (position_increment == 0) return false; - DesktopMediaSourceView* selected = GetSelection(); - DesktopMediaSourceView* new_selected = nullptr; + views::View* selected = GetSelection(); + views::View* new_selected = nullptr; if (selected) { int index = GetIndexOf(selected); int new_index = index + position_increment; new_index = std::min(new_index, child_count() - 1); new_index = std::max(new_index, 0); - if (index != new_index) { - new_selected = GetChild(new_index); - } + if (index != new_index) + new_selected = child_at(new_index); } else if (has_children()) { - new_selected = GetChild(0); + new_selected = child_at(0); } if (new_selected) @@ -214,8 +211,6 @@ void DesktopMediaListView::OnSourceRemoved(DesktopMediaList* list, int index) { DesktopMediaSourceView* view = GetChild(index); DCHECK(view); - DCHECK_EQ(view->GetClassName(), - DesktopMediaSourceView::kDesktopMediaSourceViewClassName); bool was_selected = view->is_selected(); RemoveChildView(view); @@ -237,7 +232,7 @@ void DesktopMediaListView::OnSourceMoved(DesktopMediaList* list, int old_index, int new_index) { - ReorderChildView(GetChild(old_index), new_index); + ReorderChildView(child_at(old_index), new_index); PreferredSizeChanged(); } @@ -272,7 +267,10 @@ } DesktopMediaSourceView* DesktopMediaListView::GetChild(int index) { - return static_cast<DesktopMediaSourceView*>(child_at(index)); + views::View* child = child_at(index); + DCHECK_EQ(DesktopMediaSourceView::kDesktopMediaSourceViewClassName, + child->GetClassName()); + return static_cast<DesktopMediaSourceView*>(child); } void DesktopMediaListView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc b/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc index fbfb896b..47d2295 100644 --- a/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc +++ b/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc
@@ -32,8 +32,8 @@ menu_runner_.reset(new views::MenuRunner( menu_model, views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU, - base::Bind(&DownloadShelfContextMenuView::OnMenuClosed, - base::Unretained(this), on_menu_closed_callback))); + base::BindRepeating(&DownloadShelfContextMenuView::OnMenuClosed, + base::Unretained(this), on_menu_closed_callback))); // The menu's alignment is determined based on the UI layout. views::MenuAnchorPosition position;
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc index 2660599..884e8f4 100644 --- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -36,30 +36,8 @@ #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_delegate.h" -#if defined(OS_CHROMEOS) -#include "ash/public/cpp/shell_window_ids.h" -#include "chrome/browser/ui/ash/ash_util.h" -#endif - namespace { -#if defined(OS_CHROMEOS) -views::Widget* CreateChromeOSAppListParentedDialog( - views::DialogDelegateView* delegate_view) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params = - views::DialogDelegate::GetDialogWidgetInitParams( - delegate_view, nullptr /* context */, nullptr /* parent */, - gfx::Rect() /* bounds */); - - ash_util::SetupWidgetInitParamsForContainer( - ¶ms, ash::kShellWindowId_AppListContainer); - - widget->Init(params); - return widget; -} -#endif - ToolbarActionView* GetExtensionAnchorView(const std::string& extension_id, gfx::NativeWindow window) { BrowserView* browser_view = @@ -169,14 +147,6 @@ if (anchor_view) { views::BubbleDialogDelegateView::CreateBubble(view_)->Show(); } else { -#if defined(OS_CHROMEOS) - // On ChromeOS, the uninstall dialog can be created from the App List, so we - // need to attach the AppList window as the parent window. - if (uninstall_source() == extensions::UNINSTALL_SOURCE_APP_LIST) { - CreateChromeOSAppListParentedDialog(view_)->Show(); - return; - } -#endif constrained_window::CreateBrowserModalDialogViews(view_, parent())->Show(); } }
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc index 598e8e74..10c6c9b 100644 --- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
@@ -27,15 +27,6 @@ #include "extensions/common/extension_urls.h" #include "extensions/common/value_builder.h" -#if defined(OS_CHROMEOS) -#include "ash/public/cpp/shell_window_ids.h" -#include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h" -#include "content/public/common/service_manager_connection.h" -#include "services/service_manager/public/cpp/connector.h" -#include "ui/aura/test/mus/change_completion_waiter.h" -#endif - namespace { const char kUninstallUrl[] = "https://www.google.com/"; @@ -62,25 +53,6 @@ std::make_unique<base::Value>(kUninstallUrl)); } -#if defined(OS_CHROMEOS) -// Returns the number of child windows in the AppList container on ChromeOS. -// Blocks until the ash service responds. -int GetWindowCountForAppListContainer() { - // Wait for window visibility to stabilize. - aura::test::WaitForAllChangesToComplete(); - - ash::mojom::ShellTestApiPtr shell_test_api; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &shell_test_api); - ash::mojom::ShellTestApiAsyncWaiter waiter(shell_test_api.get()); - int child_window_count = 0; - waiter.GetChildWindowCountInContainer(ash::kShellWindowId_AppListContainer, - &child_window_count); - return child_window_count; -} -#endif - class TestExtensionUninstallDialogDelegate : public extensions::ExtensionUninstallDialog::Delegate { public: @@ -164,54 +136,6 @@ } #if defined(OS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(ExtensionUninstallDialogViewBrowserTest, - ParentWindowIsAppList) { - scoped_refptr<const extensions::Extension> extension(BuildTestExtension()); - extensions::ExtensionSystem::Get(browser()->profile()) - ->extension_service() - ->AddExtension(extension.get()); - - // Initially the AppList window should have no children. - EXPECT_EQ(0, GetWindowCountForAppListContainer()); - - // Open the extension uninstall dialog without a browser parent window. This - // occurs when the dialog is opened from the Launcher. - std::unique_ptr<extensions::ExtensionUninstallDialog> dialog; - dialog = extensions::ExtensionUninstallDialog::Create(browser()->profile(), - nullptr, nullptr); - dialog->ConfirmUninstall(extension.get(), - extensions::UNINSTALL_REASON_FOR_TESTING, - extensions::UNINSTALL_SOURCE_APP_LIST); - - // Verify that a child dialog window has been added to the AppList as a child. - EXPECT_EQ(1, GetWindowCountForAppListContainer()); -} - -IN_PROC_BROWSER_TEST_F(ExtensionUninstallDialogViewBrowserTest, - ParentWindowIsBrowser) { - scoped_refptr<const extensions::Extension> extension(BuildTestExtension()); - extensions::ExtensionSystem::Get(browser()->profile()) - ->extension_service() - ->AddExtension(extension.get()); - - // When the uninstall dialog is launched from a browser, the AppList should - // never be the parent. - EXPECT_EQ(0, GetWindowCountForAppListContainer()); - - // Open the extension uninstall dialog with a browser parent window. This is - // occurs when the dialog is opened from chrome://extensions rather than the - // launcher. - std::unique_ptr<extensions::ExtensionUninstallDialog> dialog; - dialog = extensions::ExtensionUninstallDialog::Create( - browser()->profile(), browser()->window()->GetNativeWindow(), nullptr); - dialog->ConfirmUninstall(extension.get(), - extensions::UNINSTALL_REASON_FOR_TESTING, - extensions::UNINSTALL_SOURCE_FOR_TESTING); - - // Verify that the uninstall dialog is not parented to the AppList. - EXPECT_EQ(0, GetWindowCountForAppListContainer()); -} - // Test that we don't crash when uninstalling an extension from a bookmark app // window in Ash. Context: crbug.com/825554 IN_PROC_BROWSER_TEST_F(ExtensionUninstallDialogViewBrowserTest,
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc index 93abbea..ca53bf0 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -311,8 +311,8 @@ context_menu_runner_.reset(new views::MenuRunner( controller_->GetContextMenu(id), views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU, - base::Bind(&MediaGalleriesDialogViews::OnMenuClosed, - base::Unretained(this)))); + base::BindRepeating(&MediaGalleriesDialogViews::OnMenuClosed, + base::Unretained(this)))); context_menu_runner_->RunMenuAt( GetWidget(), NULL,
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index bba0a98..dbca6092a 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -248,7 +248,8 @@ menu_runner_.reset(new views::MenuRunner( GetSystemMenuModel(), views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU, - base::Bind(&BrowserFrame::OnMenuClosed, base::Unretained(this)))); + base::BindRepeating(&BrowserFrame::OnMenuClosed, + base::Unretained(this)))); menu_runner_->RunMenuAt(source->GetWidget(), nullptr, gfx::Rect(p, gfx::Size(0, 0)), views::MENU_ANCHOR_TOPLEFT, source_type);
diff --git a/chrome/browser/ui/views/tabs/glow_hover_controller.cc b/chrome/browser/ui/views/tabs/glow_hover_controller.cc index 681db8d..e2d9e0b 100644 --- a/chrome/browser/ui/views/tabs/glow_hover_controller.cc +++ b/chrome/browser/ui/views/tabs/glow_hover_controller.cc
@@ -40,15 +40,15 @@ subtle_opacity_scale_ = opacity_scale; } -void GlowHoverController::Show(ShowStyle style) { +void GlowHoverController::Show(TabStyle::ShowHoverStyle style) { switch (style) { - case ShowStyle::kSubtle: + case TabStyle::ShowHoverStyle::kSubtle: opacity_scale_ = subtle_opacity_scale_; animation_.SetSlideDuration(kTrackHoverDurationMs); animation_.SetTweenType(gfx::Tween::EASE_OUT); animation_.Show(); break; - case ShowStyle::kPronounced: + case TabStyle::ShowHoverStyle::kPronounced: opacity_scale_ = kPronouncedOpacityScale; // Force the end state to show immediately. animation_.Show(); @@ -57,13 +57,13 @@ } } -void GlowHoverController::Hide(HideStyle style) { +void GlowHoverController::Hide(TabStyle::HideHoverStyle style) { switch (style) { - case HideStyle::kGradual: + case TabStyle::HideHoverStyle::kGradual: animation_.SetTweenType(gfx::Tween::EASE_IN); animation_.Hide(); break; - case HideStyle::kImmediate: + case TabStyle::HideHoverStyle::kImmediate: if (ShouldDraw()) view_->SchedulePaint(); animation_.Reset();
diff --git a/chrome/browser/ui/views/tabs/glow_hover_controller.h b/chrome/browser/ui/views/tabs/glow_hover_controller.h index d95b558..1890bc34 100644 --- a/chrome/browser/ui/views/tabs/glow_hover_controller.h +++ b/chrome/browser/ui/views/tabs/glow_hover_controller.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_VIEWS_TABS_GLOW_HOVER_CONTROLLER_H_ #include "base/macros.h" +#include "chrome/browser/ui/tabs/tab_style.h" #include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/slide_animation.h" @@ -27,13 +28,6 @@ // invokes SchedulePaint() back on the View as necessary. class GlowHoverController : public gfx::AnimationDelegate { public: - enum class ShowStyle { kSubtle, kPronounced }; - - enum class HideStyle { - kGradual, // The hover should fade out. - kImmediate, // The hover should cut off, with no fade out. - }; - explicit GlowHoverController(views::View* view); ~GlowHoverController() override; @@ -50,10 +44,10 @@ const gfx::Point& location() const { return location_; } // Initiates showing the hover. - void Show(ShowStyle style); + void Show(TabStyle::ShowHoverStyle style); // Hides the hover. - void Hide(HideStyle); + void Hide(TabStyle::HideHoverStyle style); // Returns the value of the animation. double GetAnimationValue() const;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 3a3d939d8..a24bfa58 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" +#include "chrome/browser/ui/tabs/tab_style.h" #include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -39,7 +40,7 @@ #include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" #include "chrome/browser/ui/views/tabs/tab_icon.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "chrome/browser/ui/views/touch_uma/touch_uma.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" @@ -121,7 +122,7 @@ title_animation_(this) { DCHECK(controller); - tab_style_ = TabStyle::CreateForTab(this); + tab_style_ = TabStyleViews::CreateForTab(this); // So we get don't get enter/exit on children and don't prematurely stop the // hover. @@ -483,7 +484,7 @@ void Tab::OnMouseEntered(const ui::MouseEvent& event) { mouse_hovered_ = true; - tab_style_->ShowHover(GlowHoverController::ShowStyle::kSubtle); + tab_style_->ShowHover(TabStyle::ShowHoverStyle::kSubtle); UpdateForegroundColors(); Layout(); controller_->UpdateHoverCard(this, true); @@ -491,7 +492,7 @@ void Tab::OnMouseExited(const ui::MouseEvent& event) { mouse_hovered_ = false; - tab_style_->HideHover(GlowHoverController::HideStyle::kGradual); + tab_style_->HideHover(TabStyle::HideHoverStyle::kGradual); UpdateForegroundColors(); Layout(); }
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 0320a31..25b0fce 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -28,7 +28,7 @@ class TabCloseButton; class TabController; class TabIcon; -class TabStyle; +class TabStyleViews; namespace gfx { class Animation; @@ -169,8 +169,8 @@ bool mouse_hovered() const { return mouse_hovered_; } // Returns the TabStyle associated with this tab. - TabStyle* tab_style() { return tab_style_.get(); } - const TabStyle* tab_style() const { return tab_style_.get(); } + TabStyleViews* tab_style() { return tab_style_.get(); } + const TabStyleViews* tab_style() const { return tab_style_.get(); } // Returns the text to show in a tab's tooltip: The contents |title|, followed // by a break, followed by a localized string describing the |alert_state|. @@ -214,7 +214,7 @@ TabRendererData data_; - std::unique_ptr<TabStyle> tab_style_; + std::unique_ptr<TabStyleViews> tab_style_; // True if the tab is being animated closed. bool closing_ = false;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 3b0474cc..b807bc6a 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -31,7 +31,7 @@ #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "chrome/browser/ui/views/tabs/window_finder.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index 212ed4e..b269f06 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -9,10 +9,10 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_features.h" +#include "chrome/browser/ui/tabs/tab_style.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_renderer_data.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" #include "components/url_formatter/url_formatter.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/bubble/bubble_frame_view.h"
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index f1b44cb..b1d00fbc 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -39,7 +39,7 @@ #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_layout.h" #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "chrome/browser/ui/views/touch_uma/touch_uma.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" @@ -205,8 +205,8 @@ TabSizeInfo* info = MD::touch_ui() ? &touch_tab_size_info : &tab_size_info; if (info->standard_size.IsEmpty()) { info->pinned_tab_width = TabStyle::GetPinnedWidth(); - info->min_active_width = TabStyle::GetMinimumActiveWidth(); - info->min_inactive_width = TabStyle::GetMinimumInactiveWidth(); + info->min_active_width = TabStyleViews::GetMinimumActiveWidth(); + info->min_inactive_width = TabStyleViews::GetMinimumInactiveWidth(); info->standard_size = gfx::Size(TabStyle::GetStandardWidth(), GetLayoutConstant(TAB_HEIGHT)); info->tab_overlap = TabStyle::GetTabOverlap(); @@ -1482,8 +1482,8 @@ const int pinned_tab_count = GetPinnedTabCount(); needed_tab_width = pinned_tab_count * TabStyle::GetPinnedWidth(); const int remaining_tab_count = tab_count() - pinned_tab_count; - const int min_selected_width = TabStyle::GetMinimumActiveWidth(); - const int min_unselected_width = TabStyle::GetMinimumInactiveWidth(); + const int min_selected_width = TabStyleViews::GetMinimumActiveWidth(); + const int min_unselected_width = TabStyleViews::GetMinimumInactiveWidth(); if (remaining_tab_count > 0) { needed_tab_width += min_selected_width + ((remaining_tab_count - 1) * min_unselected_width);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 6529caf..a106daa7 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/ui/views/tabs/tab_renderer_data.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_views_test_base.h" #include "testing/gtest/include/gtest/gtest.h" @@ -779,7 +779,7 @@ tab_strip_->SetBounds(0, 0, 200, 20); // Create a lot of tabs in order to make inactive tabs tiny. - const int min_inactive_width = TabStyle::GetMinimumInactiveWidth(); + const int min_inactive_width = TabStyleViews::GetMinimumInactiveWidth(); while (current_inactive_width() != min_inactive_width) controller_->CreateNewTab(); @@ -792,7 +792,7 @@ // During mouse-based tab closure, the active tab should remain at least as // wide as it's minium width. controller_->SelectTab(0, dummy_event_); - for (const int min_active_width = TabStyle::GetMinimumActiveWidth(); + for (const int min_active_width = TabStyleViews::GetMinimumActiveWidth(); tab_strip_->tab_count();) { const int active_index = controller_->GetActiveIndex(); EXPECT_GE(tab_strip_->ideal_bounds(active_index).width(), min_active_width); @@ -808,8 +808,8 @@ // Create a lot of tabs in order to make inactive tabs smaller than active // tab but not the minimum. - const int min_inactive_width = TabStyle::GetMinimumInactiveWidth(); - const int min_active_width = TabStyle::GetMinimumActiveWidth(); + const int min_inactive_width = TabStyleViews::GetMinimumInactiveWidth(); + const int min_active_width = TabStyleViews::GetMinimumActiveWidth(); while (current_inactive_width() >= (min_inactive_width + min_active_width) / 2) controller_->CreateNewTab(); @@ -831,11 +831,11 @@ tab_strip_->SetBounds(0, 0, 200, 20); // Create a lot of tabs in order to make inactive tabs tiny. - const int min_inactive_width = TabStyle::GetMinimumInactiveWidth(); + const int min_inactive_width = TabStyleViews::GetMinimumInactiveWidth(); while (current_inactive_width() != min_inactive_width) controller_->CreateNewTab(); - const int min_active_width = TabStyle::GetMinimumActiveWidth(); + const int min_active_width = TabStyleViews::GetMinimumActiveWidth(); int dragged_tab_index = controller_->GetActiveIndex(); EXPECT_GE(tab_strip_->ideal_bounds(dragged_tab_index).width(),
diff --git a/chrome/browser/ui/views/tabs/tab_style.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc similarity index 93% rename from chrome/browser/ui/views/tabs/tab_style.cc rename to chrome/browser/ui/views/tabs/tab_style_views.cc index 7aaac14f7..f6c4165 100644 --- a/chrome/browser/ui/views/tabs/tab_style.cc +++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include <algorithm> #include <utility> @@ -11,7 +11,6 @@ #include "cc/paint/paint_record.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_close_button.h" @@ -19,7 +18,6 @@ #include "chrome/grit/theme_resources.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/pathops/SkPathOps.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/theme_provider.h" #include "ui/gfx/canvas.h" #include "ui/gfx/scoped_canvas.h" @@ -72,7 +70,7 @@ }; // Tab style implementation for the GM2 refresh (Chrome 69). -class GM2TabStyle : public TabStyle { +class GM2TabStyle : public TabStyleViews { public: explicit GM2TabStyle(Tab* tab); @@ -88,8 +86,8 @@ TabStyle::TabColors CalculateColors() const override; void PaintTab(gfx::Canvas* canvas, const SkPath& clip) const override; void SetHoverLocation(const gfx::Point& location) override; - void ShowHover(GlowHoverController::ShowStyle style) override; - void HideHover(GlowHoverController::HideStyle style) override; + void ShowHover(ShowHoverStyle style) override; + void HideHover(HideHoverStyle style) override; private: // Gets the bounds for the leading and trailing separators for a tab. @@ -162,27 +160,6 @@ DISALLOW_COPY_AND_ASSIGN(GM2TabStyle); }; -// Thickness in DIPs of the separator painted on the left and right edges of -// the tab. -constexpr int kSeparatorThickness = 1; - -// Returns the radius of the outer corners of the tab shape. -int GetCornerRadius() { - return ChromeLayoutProvider::Get()->GetCornerRadiusMetric( - views::EMPHASIS_HIGH); -} - -// Returns how far from the leading and trailing edges of a tab the contents -// should actually be laid out. -int GetContentsHorizontalInsetSize() { - return GetCornerRadius() * 2; -} - -// Returns the height of the separator between tabs. -int GetSeparatorHeight() { - return ui::MaterialDesignController::touch_ui() ? 24 : 20; -} - void DrawHighlight(gfx::Canvas* canvas, const SkPoint& p, SkScalar radius, @@ -551,18 +528,18 @@ hover_controller_->SetLocation(location); } -void GM2TabStyle::ShowHover(GlowHoverController::ShowStyle style) { +void GM2TabStyle::ShowHover(ShowHoverStyle style) { if (!hover_controller_) return; - if (style == GlowHoverController::ShowStyle::kSubtle) { + if (style == ShowHoverStyle::kSubtle) { hover_controller_->SetSubtleOpacityScale( tab_->controller()->GetHoverOpacityForRadialHighlight()); } hover_controller_->Show(style); } -void GM2TabStyle::HideHover(GlowHoverController::HideStyle style) { +void GM2TabStyle::HideHover(HideHoverStyle style) { if (hover_controller_) hover_controller_->Hide(style); } @@ -925,7 +902,7 @@ // bottom inset, because we want to pixel-align the bottom of the stroke, not // the bottom of the overlap. gfx::InsetsF layout_insets(stroke_thickness, corner_radius, stroke_thickness, - corner_radius + kSeparatorThickness); + corner_radius + GetSeparatorSize().width()); aligned_bounds.Inset(layout_insets); // Scale layout bounds from DIP to px. @@ -950,58 +927,24 @@ // TabStyle -------------------------------------------------------------------- -TabStyle::~TabStyle() = default; +TabStyleViews::~TabStyleViews() = default; // static -std::unique_ptr<TabStyle> TabStyle::CreateForTab(Tab* tab) { +std::unique_ptr<TabStyleViews> TabStyleViews::CreateForTab(Tab* tab) { return std::make_unique<GM2TabStyle>(tab); } // static -int TabStyle::GetMinimumActiveWidth() { +int TabStyleViews::GetMinimumActiveWidth() { return TabCloseButton::GetWidth() + GetContentsHorizontalInsetSize() * 2; } // static -int TabStyle::GetMinimumInactiveWidth() { +int TabStyleViews::GetMinimumInactiveWidth() { // Allow tabs to shrink until they appear to be 16 DIP wide excluding // outer corners. constexpr int kInteriorWidth = 16; // The overlap contains the trailing separator that is part of the interior // width; avoid double-counting it. - return kInteriorWidth - kSeparatorThickness + GetTabOverlap(); -} - -// static -int TabStyle::GetStandardWidth() { - // The standard tab width is 240 DIP including both separators. - constexpr int kTabWidth = 240; - // The overlap includes one separator, so subtract it here. - return kTabWidth + GetTabOverlap() - kSeparatorThickness; -} - -// static -int TabStyle::GetPinnedWidth() { - constexpr int kTabPinnedContentWidth = 23; - return kTabPinnedContentWidth + GetContentsHorizontalInsetSize() * 2; -} - -// static -int TabStyle::GetTabOverlap() { - return GetCornerRadius() * 2 + kSeparatorThickness; -} - -// static -int TabStyle::GetDragHandleExtension(int height) { - return (height - GetSeparatorHeight()) / 2 - 1; -} - -// static -gfx::Insets TabStyle::GetTabInternalPadding() { - return gfx::Insets(0, GetCornerRadius()); -} - -// static -gfx::Size TabStyle::GetSeparatorSize() { - return gfx::Size(kSeparatorThickness, GetSeparatorHeight()); + return kInteriorWidth - GetSeparatorSize().width() + GetTabOverlap(); }
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.h b/chrome/browser/ui/views/tabs/tab_style_views.h new file mode 100644 index 0000000..ea5b9f6c --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_style_views.h
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_VIEWS_H_ +#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_VIEWS_H_ + +#include <memory> + +#include "chrome/browser/ui/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/glow_hover_controller.h" +#include "ui/gfx/geometry/rect_f.h" + +class Tab; + +// Holds Views-specific logic for rendering and sizing tabs. +class TabStyleViews : public TabStyle { + public: + // Factory function allows to experiment with different variations on tab + // style at runtime or via flag. + static std::unique_ptr<TabStyleViews> CreateForTab(Tab* tab); + + ~TabStyleViews() override; + + // Returns the minimum possible width of a selected Tab. Selected tabs must + // always show a close button, and thus have a larger minimum size than + // unselected tabs. + static int GetMinimumActiveWidth(); + + // Returns the minimum possible width of a single unselected Tab. + static int GetMinimumInactiveWidth(); + + protected: + // Avoid implicitly-deleted constructor. + TabStyleViews() = default; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STYLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index d20db95..7b86a69 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -19,7 +19,7 @@ #include "chrome/browser/ui/views/tabs/tab_controller.h" #include "chrome/browser/ui/views/tabs/tab_icon.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/browser/ui/views/tabs/tab_style.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/theme_resources.h" #include "chrome/test/views/chrome_views_test_base.h" @@ -461,8 +461,8 @@ width = min_width = TabStyle::GetPinnedWidth(); } else { width = TabStyle::GetStandardWidth(); - min_width = is_active_tab ? TabStyle::GetMinimumActiveWidth() - : TabStyle::GetMinimumInactiveWidth(); + min_width = is_active_tab ? TabStyleViews::GetMinimumActiveWidth() + : TabStyleViews::GetMinimumInactiveWidth(); } const int height = GetLayoutConstant(TAB_HEIGHT); for (; width >= min_width; --width) {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc index f679c65..f51401b 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -343,8 +343,8 @@ // menu. Any action that would lead to the deletion of |this| first triggers // the closing of the menu through lost capture. menu_adapter_.reset(new views::MenuModelAdapter( - context_menu_model, - base::Bind(&ToolbarActionView::OnMenuClosed, base::Unretained(this)))); + context_menu_model, base::BindRepeating(&ToolbarActionView::OnMenuClosed, + base::Unretained(this)))); menu_ = menu_adapter_->CreateMenu(); menu_runner_.reset(new views::MenuRunner(menu_, run_types));
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc index 8b46908..4015441 100644 --- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -35,6 +35,16 @@ screen_->OnViewDestroyed(this); } +void ResetScreenHandler::Bind(ResetScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); +} + +void ResetScreenHandler::Unbind() { + screen_ = nullptr; + BaseScreenHandler::SetBaseScreen(nullptr); +} + void ResetScreenHandler::Show() { if (!page_is_ready()) { show_on_init_ = true; @@ -94,6 +104,11 @@ builder->Add("confirmResetButton", IDS_RESET_SCREEN_POPUP_CONFIRM_BUTTON); } +void ResetScreenHandler::DeclareJSCallbacks() { + AddCallback("ResetScreen.setTpmFirmwareUpdateChecked", + &ResetScreenHandler::HandleSetTpmFirmwareUpdateChecked); +} + void ResetScreenHandler::Initialize() { if (!page_is_ready()) return; @@ -104,14 +119,70 @@ } } -void ResetScreenHandler::Bind(ResetScreen* screen) { - screen_ = screen; - BaseScreenHandler::SetBaseScreen(screen_); +void ResetScreenHandler::SetIsRollbackAvailable(bool value) { + is_rollback_available_ = value; + CallJS("login.ResetScreen.setIsRollbackAvailable", value); } -void ResetScreenHandler::Unbind() { - screen_ = nullptr; - BaseScreenHandler::SetBaseScreen(nullptr); +void ResetScreenHandler::SetIsRollbackChecked(bool value) { + is_rollback_checked_ = value; + CallJS("login.ResetScreen.setIsRollbackChecked", value); +} + +void ResetScreenHandler::SetIsTpmFirmwareUpdateAvailable(bool value) { + CallJS("login.ResetScreen.setIsTpmFirmwareUpdateAvailable", value); +} + +void ResetScreenHandler::SetIsTpmFirmwareUpdateChecked(bool value) { + is_tpm_firmware_update_checked_ = value; + CallJS("login.ResetScreen.setIsTpmFirmwareUpdateChecked", value); +} + +void ResetScreenHandler::SetIsTpmFirmwareUpdateEditable(bool value) { + CallJS("login.ResetScreen.setIsTpmFirmwareUpdateEditable", value); +} + +void ResetScreenHandler::SetTpmFirmwareUpdateMode( + tpm_firmware_update::Mode value) { + mode_ = value; + CallJS("login.ResetScreen.setTpmFirmwareUpdateMode", static_cast<int>(value)); +} + +void ResetScreenHandler::SetIsConfirmational(bool value) { + CallJS("login.ResetScreen.setIsConfirmational", value); +} + +void ResetScreenHandler::SetIsOfficialBuild(bool value) { + CallJS("login.ResetScreen.setIsOfficialBuild", value); +} + +void ResetScreenHandler::SetScreenState(State value) { + state_ = value; + CallJS("login.ResetScreen.setScreenState", static_cast<int>(value)); +} + +ResetView::State ResetScreenHandler::GetScreenState() { + return state_; +} + +tpm_firmware_update::Mode ResetScreenHandler::GetTpmFirmwareUpdateMode() { + return mode_; +} + +bool ResetScreenHandler::GetIsRollbackAvailable() { + return is_rollback_available_; +} + +bool ResetScreenHandler::GetIsRollbackChecked() { + return is_rollback_checked_; +} + +bool ResetScreenHandler::GetIsTpmFirmwareUpdateChecked() { + return is_tpm_firmware_update_checked_; +} + +void ResetScreenHandler::HandleSetTpmFirmwareUpdateChecked(bool value) { + is_tpm_firmware_update_checked_ = value; } } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h index f69d5b2c..e23e06bf 100644 --- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "chrome/browser/chromeos/login/screens/reset_view.h" +#include "chrome/browser/chromeos/tpm_firmware_update.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "content/public/browser/web_ui.h" @@ -29,14 +30,37 @@ // BaseScreenHandler implementation: void DeclareLocalizedValues( ::login::LocalizedValuesBuilder* builder) override; + void DeclareJSCallbacks() override; void Initialize() override; + void SetIsRollbackAvailable(bool value) override; + void SetIsRollbackChecked(bool value) override; + void SetIsTpmFirmwareUpdateAvailable(bool value) override; + void SetIsTpmFirmwareUpdateChecked(bool value) override; + void SetIsTpmFirmwareUpdateEditable(bool value) override; + void SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode value) override; + void SetIsConfirmational(bool value) override; + void SetIsOfficialBuild(bool value) override; + void SetScreenState(State value) override; + State GetScreenState() override; + tpm_firmware_update::Mode GetTpmFirmwareUpdateMode() override; + bool GetIsRollbackAvailable() override; + bool GetIsRollbackChecked() override; + bool GetIsTpmFirmwareUpdateChecked() override; private: + void HandleSetTpmFirmwareUpdateChecked(bool value); + ResetScreen* screen_ = nullptr; // If true, Initialize() will call Show(). bool show_on_init_ = false; + ResetView::State state_ = ResetView::State::kRestartRequired; + tpm_firmware_update::Mode mode_ = tpm_firmware_update::Mode::kNone; + bool is_rollback_available_ = false; + bool is_rollback_checked_ = false; + bool is_tpm_firmware_update_checked_ = false; + DISALLOW_COPY_AND_ASSIGN(ResetScreenHandler); };
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc index 5026d255..3c3885bc 100644 --- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc +++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -8,10 +8,12 @@ #include <string> #include "base/bind.h" +#include "base/feature_list.h" #include "base/i18n/rtl.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" @@ -29,6 +31,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/native_theme/native_theme.h" #include "url/gurl.h" namespace { @@ -50,7 +53,11 @@ /////////////////////////////////////////////////////////////////////////////// // NewTabUI -NewTabUI::NewTabUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { +NewTabUI::NewTabUI(content::WebUI* web_ui) + : content::WebUIController(web_ui), + dark_mode_observer_(ui::NativeTheme::GetInstanceForNativeUi(), + base::BindRepeating(&NewTabUI::OnDarkModeChanged, + base::Unretained(this))) { web_ui->OverrideTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE)); Profile* profile = GetProfile(); @@ -69,6 +76,8 @@ pref_change_registrar_.Add( prefs::kWebKitDefaultFontSize, base::Bind(&NewTabUI::OnDefaultFontSizeChanged, base::Unretained(this))); + + dark_mode_observer_.Start(); } NewTabUI::~NewTabUI() {} @@ -82,6 +91,16 @@ attached); } +void NewTabUI::OnDarkModeChanged(bool /*dark_mode*/) { + if (!web_ui() || !web_ui()->CanCallJavascript()) + return; + + bool enabled = base::FeatureList::IsEnabled(features::kWebUIDarkMode); + web_ui()->CallJavascriptFunctionUnsafe( + "document.documentElement.toggleAttribute", base::Value("dark"), + base::Value(enabled && dark_mode_observer_.InDarkMode())); +} + void NewTabUI::OnDefaultFontSizeChanged() { web_ui()->CallJavascriptFunctionUnsafe("ntp.defaultFontSizeChanged"); }
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.h b/chrome/browser/ui/webui/ntp/new_tab_ui.h index e3bf3c65..f5e776d 100644 --- a/chrome/browser/ui/webui/ntp/new_tab_ui.h +++ b/chrome/browser/ui/webui/ntp/new_tab_ui.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/strings/string16.h" +#include "chrome/browser/ui/dark_mode_observer.h" #include "components/prefs/pref_change_registrar.h" #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_ui_controller.h" @@ -73,11 +74,14 @@ DISALLOW_COPY_AND_ASSIGN(NewTabHTMLSource); }; - void OnShowBookmarkBarChanged(); + void OnDarkModeChanged(bool dark_mode); void OnDefaultFontSizeChanged(); + void OnShowBookmarkBarChanged(); Profile* GetProfile() const; + DarkModeObserver dark_mode_observer_; + PrefChangeRegistrar pref_change_registrar_; DISALLOW_COPY_AND_ASSIGN(NewTabUI);
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index dab1b70..6d373f6 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" #include "base/values.h" @@ -92,17 +93,46 @@ LocalPrinterHandlerChromeos::LocalPrinterHandlerChromeos( Profile* profile, - content::WebContents* preview_web_contents) + content::WebContents* preview_web_contents, + chromeos::CupsPrintersManager* printers_manager, + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer) : profile_(profile), preview_web_contents_(preview_web_contents), - printers_manager_( - CupsPrintersManagerFactory::GetForBrowserContext(profile)), - printer_configurer_(chromeos::PrinterConfigurer::Create(profile)), + printers_manager_(printers_manager), + printer_configurer_(std::move(printer_configurer)), weak_factory_(this) { // Construct the CupsPrintJobManager to listen for printing events. chromeos::CupsPrintJobManagerFactory::GetForBrowserContext(profile); } +// static +std::unique_ptr<LocalPrinterHandlerChromeos> +LocalPrinterHandlerChromeos::CreateDefault( + Profile* profile, + content::WebContents* preview_web_contents) { + chromeos::CupsPrintersManager* printers_manager( + CupsPrintersManagerFactory::GetForBrowserContext(profile)); + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer( + chromeos::PrinterConfigurer::Create(profile)); + // Using 'new' to access non-public constructor. + return base::WrapUnique(new LocalPrinterHandlerChromeos( + profile, preview_web_contents, printers_manager, + std::move(printer_configurer))); +} + +// static +std::unique_ptr<LocalPrinterHandlerChromeos> +LocalPrinterHandlerChromeos::CreateForTesting( + Profile* profile, + content::WebContents* preview_web_contents, + chromeos::CupsPrintersManager* printers_manager, + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer) { + // Using 'new' to access non-public constructor. + return base::WrapUnique(new LocalPrinterHandlerChromeos( + profile, preview_web_contents, printers_manager, + std::move(printer_configurer))); +} + LocalPrinterHandlerChromeos::~LocalPrinterHandlerChromeos() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } @@ -185,27 +215,9 @@ VLOG(1) << "Printer setup successful for " << printer->id() << " fetching properties"; printers_manager_->PrinterInstalled(*printer, true /*is_automatic*/); - - // populate |policies| with policies for native printers. - base::Value policies(base::Value::Type::DICTIONARY); - const PrefService* prefs = profile_->GetPrefs(); - policies.SetKey( - kAllowedColorModes, - base::Value(prefs->GetInteger(prefs::kPrintingAllowedColorModes))); - policies.SetKey( - kAllowedDuplexModes, - base::Value(prefs->GetInteger(prefs::kPrintingAllowedDuplexModes))); - policies.SetKey( - kAllowedPinModes, - base::Value(prefs->GetInteger(prefs::kPrintingAllowedPinModes))); - policies.SetKey(kDefaultColorMode, - base::Value(prefs->Get(prefs::kPrintingColorDefault))); - policies.SetKey(kDefaultDuplexMode, - base::Value(prefs->Get(prefs::kPrintingDuplexDefault))); - policies.SetKey(kDefaultPinMode, - base::Value(prefs->Get(prefs::kPrintingPinDefault))); // fetch settings on the blocking pool and invoke callback. - FetchCapabilities(std::move(printer), std::move(policies), std::move(cb)); + FetchCapabilities(std::move(printer), GetNativePrinterPolicies(), + std::move(cb)); return; } case chromeos::PrinterSetupResult::kPpdNotFound: @@ -258,4 +270,25 @@ preview_web_contents_, std::move(callback)); } +base::Value LocalPrinterHandlerChromeos::GetNativePrinterPolicies() const { + base::Value policies(base::Value::Type::DICTIONARY); + const PrefService* prefs = profile_->GetPrefs(); + policies.SetKey( + kAllowedColorModes, + base::Value(prefs->GetInteger(prefs::kPrintingAllowedColorModes))); + policies.SetKey( + kAllowedDuplexModes, + base::Value(prefs->GetInteger(prefs::kPrintingAllowedDuplexModes))); + policies.SetKey( + kAllowedPinModes, + base::Value(prefs->GetInteger(prefs::kPrintingAllowedPinModes))); + policies.SetKey(kDefaultColorMode, + base::Value(prefs->Get(prefs::kPrintingColorDefault))); + policies.SetKey(kDefaultDuplexMode, + base::Value(prefs->Get(prefs::kPrintingDuplexDefault))); + policies.SetKey(kDefaultPinMode, + base::Value(prefs->Get(prefs::kPrintingPinDefault))); + return policies; +} + } // namespace printing
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h index de085a0d..fe9fea9 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h
@@ -27,8 +27,16 @@ class LocalPrinterHandlerChromeos : public PrinterHandler { public: - LocalPrinterHandlerChromeos(Profile* profile, - content::WebContents* preview_web_contents); + static std::unique_ptr<LocalPrinterHandlerChromeos> CreateDefault( + Profile* profile, + content::WebContents* preview_web_contents); + + static std::unique_ptr<LocalPrinterHandlerChromeos> CreateForTesting( + Profile* profile, + content::WebContents* preview_web_contents, + chromeos::CupsPrintersManager* printers_manager, + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer); + ~LocalPrinterHandlerChromeos() override; // PrinterHandler implementation @@ -44,6 +52,16 @@ PrintCallback callback) override; private: + explicit LocalPrinterHandlerChromeos( + Profile* profile, + content::WebContents* preview_web_contents, + chromeos::CupsPrintersManager* printers_manager, + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer); + + // Creates a value dictionary containing the printing policies set by + // |profile_|. + base::Value GetNativePrinterPolicies() const; + void HandlePrinterSetup(std::unique_ptr<chromeos::Printer> printer, GetCapabilityCallback cb, chromeos::PrinterSetupResult result);
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc new file mode 100644 index 0000000..de450a08 --- /dev/null +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc
@@ -0,0 +1,293 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc" + +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/containers/flat_set.h" +#include "base/json/json_string_value_serializer.h" +#include "base/memory/ref_counted.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "printing/backend/print_backend.h" +#include "printing/backend/test_print_backend.h" +#include "printing/print_job_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace printing { + +namespace { + +using chromeos::CupsPrintersManager; +using chromeos::Printer; +using chromeos::PrinterConfigurer; +using chromeos::PrinterSetupCallback; +using chromeos::PrinterSetupResult; + +// Used as a callback to StartGetPrinters in tests. +// Increases |*call_count| and records values returned by StartGetPrinters. +void RecordPrinterList(size_t* call_count, + std::unique_ptr<base::ListValue>* printers_out, + const base::ListValue& printers) { + ++(*call_count); + printers_out->reset(printers.DeepCopy()); +} + +// Used as a callback to StartGetPrinters in tests. +// Records that the test is done. +void RecordPrintersDone(bool* is_done_out) { + *is_done_out = true; +} + +void RecordGetCapability(std::unique_ptr<base::Value>* capabilities_out, + base::Value capability) { + capabilities_out->reset(capability.DeepCopy()); +} + +Printer CreateTestPrinter(const std::string& id, const std::string& name) { + Printer printer; + printer.set_id(id); + printer.set_display_name(name); + return printer; +} + +Printer CreateEnterprisePrinter(const std::string& id, + const std::string& name) { + Printer printer = CreateTestPrinter(id, name); + printer.set_source(Printer::SRC_POLICY); + return printer; +} + +class FakeCupsPrintersManager : public CupsPrintersManager { + public: + FakeCupsPrintersManager() : printers_(kNumPrinterClasses) {} + + std::vector<Printer> GetPrinters(PrinterClass printer_class) const override { + return printers_[printer_class]; + } + + void RemoveUnavailablePrinters(std::vector<Printer>*) const override {} + void UpdateConfiguredPrinter(const Printer& printer) override {} + void RemoveConfiguredPrinter(const std::string& printer_id) override {} + void AddObserver(CupsPrintersManager::Observer* observer) override {} + void RemoveObserver(CupsPrintersManager::Observer* observer) override {} + void PrinterInstalled(const Printer& printer, bool is_automatic) override {} + void RecordSetupAbandoned(const Printer& printer) override {} + + bool IsPrinterInstalled(const Printer& printer) const override { + return installed_.contains(printer.id()); + } + + std::unique_ptr<Printer> GetPrinter(const std::string& id) const override { + for (const std::vector<Printer>& v : printers_) { + auto iter = std::find_if( + v.begin(), v.end(), [&id](const Printer& p) { return p.id() == id; }); + if (iter != v.end()) { + return std::make_unique<Printer>(*iter); + } + } + return nullptr; + } + + // Add |printer| to the corresponding list in |printers_| bases on the given + // |printer_class|. + void AddPrinter(const Printer& printer, PrinterClass printer_class) { + ASSERT_LT(printer_class, printers_.size()); + printers_[printer_class].push_back(printer); + } + + void InstallPrinter(const std::string& id) { installed_.insert(id); } + + private: + std::vector<std::vector<Printer>> printers_; + base::flat_set<std::string> installed_; +}; + +class FakePrinterConfigurer : public PrinterConfigurer { + public: + void SetUpPrinter(const Printer& printer, + PrinterSetupCallback callback) override { + std::move(callback).Run(PrinterSetupResult::kSuccess); + } +}; + +// Converts JSON string to base::ListValue object. +// On failure, returns NULL and fills |*error| string. +std::unique_ptr<base::ListValue> GetJSONAsListValue(const std::string& json, + std::string* error) { + auto ret = base::ListValue::From( + JSONStringValueDeserializer(json).Deserialize(nullptr, error)); + if (!ret) + *error = "Value is not a list."; + return ret; +} + +} // namespace + +class LocalPrinterHandlerChromeosTest : public testing::Test { + public: + LocalPrinterHandlerChromeosTest() = default; + ~LocalPrinterHandlerChromeosTest() override = default; + + void SetUp() override { + test_backend_ = base::MakeRefCounted<TestPrintBackend>(); + PrintBackend::SetPrintBackendForTesting(test_backend_.get()); + local_printer_handler_ = LocalPrinterHandlerChromeos::CreateForTesting( + &profile_, nullptr, &printers_manager_, + std::make_unique<FakePrinterConfigurer>()); + } + + protected: + // Must outlive |profile_|. + content::TestBrowserThreadBundle thread_bundle_; + // Must outlive |printers_manager_|. + TestingProfile profile_; + scoped_refptr<TestPrintBackend> test_backend_; + FakeCupsPrintersManager printers_manager_; + std::unique_ptr<LocalPrinterHandlerChromeos> local_printer_handler_; + + private: + DISALLOW_COPY_AND_ASSIGN(LocalPrinterHandlerChromeosTest); +}; + +TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) { + size_t call_count = 0; + std::unique_ptr<base::ListValue> printers; + bool is_done = false; + + Printer configured_printer = CreateTestPrinter("printer1", "configured"); + Printer enterprise_printer = + CreateEnterprisePrinter("printer2", "enterprise"); + Printer automatic_printer = CreateTestPrinter("printer3", "automatic"); + + printers_manager_.AddPrinter(configured_printer, + CupsPrintersManager::kConfigured); + printers_manager_.AddPrinter(enterprise_printer, + CupsPrintersManager::kEnterprise); + printers_manager_.AddPrinter(automatic_printer, + CupsPrintersManager::kAutomatic); + + local_printer_handler_->StartGetPrinters( + base::BindRepeating(&RecordPrinterList, &call_count, &printers), + base::BindOnce(&RecordPrintersDone, &is_done)); + + EXPECT_EQ(call_count, 1u); + EXPECT_TRUE(is_done); + ASSERT_TRUE(printers); + + const std::string expected_list = R"( + [ + { + "cupsEnterprisePrinter": false, + "deviceName": "printer1", + "printerDescription": "", + "printerName": "configured", + "printerOptions": { + "cupsEnterprisePrinter": "false", + "system_driverinfo": "" + } + }, + { + "cupsEnterprisePrinter": true, + "deviceName": "printer2", + "printerDescription": "", + "printerName": "enterprise", + "printerOptions": { + "cupsEnterprisePrinter": "true", + "system_driverinfo": "" + } + }, + { + "cupsEnterprisePrinter": false, + "deviceName": "printer3", + "printerDescription": "", + "printerName": "automatic", + "printerOptions": { + "cupsEnterprisePrinter": "false", + "system_driverinfo": "" + } + } + ] + )"; + std::string error; + std::unique_ptr<base::ListValue> expected_printers( + GetJSONAsListValue(expected_list, &error)); + ASSERT_TRUE(expected_printers) << "Error deserializing printers: " << error; + EXPECT_EQ(*printers, *expected_printers); +} + +// Tests that fetching capabilities for an existing installed printer is +// successful. +TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityValidPrinter) { + Printer configured_printer = CreateTestPrinter("printer1", "configured"); + printers_manager_.AddPrinter(configured_printer, + CupsPrintersManager::kConfigured); + printers_manager_.InstallPrinter("printer1"); + + // Add printer capabilities to |test_backend_|. + PrinterSemanticCapsAndDefaults caps; + test_backend_->AddValidPrinter( + "printer1", std::make_unique<PrinterSemanticCapsAndDefaults>(caps)); + + std::unique_ptr<base::Value> fetched_caps; + local_printer_handler_->StartGetCapability( + "printer1", base::BindOnce(&RecordGetCapability, &fetched_caps)); + + thread_bundle_.RunUntilIdle(); + + ASSERT_TRUE(fetched_caps); + base::DictionaryValue* dict; + ASSERT_TRUE(fetched_caps->GetAsDictionary(&dict)); + ASSERT_TRUE(dict->HasKey(kSettingCapabilities)); + ASSERT_TRUE(dict->HasKey(kPrinter)); +} + +// Test that printers which have not yet been installed are installed with +// SetUpPrinter before their capabilities are fetched. +TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityPrinterNotInstalled) { + Printer discovered_printer = CreateTestPrinter("printer1", "discovered"); + // NOTE: The printer |discovered_printer| is not installed using + // InstallPrinter. + printers_manager_.AddPrinter(discovered_printer, + CupsPrintersManager::kDiscovered); + + // Add printer capabilities to |test_backend_|. + PrinterSemanticCapsAndDefaults caps; + test_backend_->AddValidPrinter( + "printer1", std::make_unique<PrinterSemanticCapsAndDefaults>(caps)); + + std::unique_ptr<base::Value> fetched_caps; + local_printer_handler_->StartGetCapability( + "printer1", base::BindOnce(&RecordGetCapability, &fetched_caps)); + + thread_bundle_.RunUntilIdle(); + + ASSERT_TRUE(fetched_caps); + base::DictionaryValue* dict; + ASSERT_TRUE(fetched_caps->GetAsDictionary(&dict)); + ASSERT_TRUE(dict->HasKey(kSettingCapabilities)); + ASSERT_TRUE(dict->HasKey(kPrinter)); +} + +// In this test we expect the StartGetCapability to bail early because the +// provided printer can't be found in the CupsPrintersManager. +TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityInvalidPrinter) { + std::unique_ptr<base::Value> fetched_caps; + local_printer_handler_->StartGetCapability( + "invalid printer", base::BindOnce(&RecordGetCapability, &fetched_caps)); + + thread_bundle_.RunUntilIdle(); + + ASSERT_TRUE(fetched_caps); + EXPECT_TRUE(fetched_caps->is_none()); +} + +} // namespace printing
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chrome/browser/ui/webui/print_preview/printer_handler.cc index d5fcabd..84afb6f 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/printer_handler.cc
@@ -38,8 +38,8 @@ content::WebContents* preview_web_contents, Profile* profile) { #if defined(OS_CHROMEOS) - return std::make_unique<LocalPrinterHandlerChromeos>(profile, - preview_web_contents); + return LocalPrinterHandlerChromeos::CreateDefault(profile, + preview_web_contents); #else return std::make_unique<LocalPrinterHandlerDefault>(preview_web_contents); #endif
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index b0e6f27c..4deb4c34 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -132,7 +132,7 @@ #include "chrome/browser/ui/webui/settings/printing_handler.h" #endif -#if defined(SAFE_BROWSING_FULL) +#if defined(FULL_SAFE_BROWSING) #include "chrome/browser/safe_browsing/chrome_password_protection_service.h" #include "chrome/browser/ui/webui/settings/change_password_handler.h" #endif @@ -270,7 +270,7 @@ #endif // OS_WIN && defined(GOOGLE_CHROME_BUILD) bool password_protection_available = false; -#if defined(SAFE_BROWSING_FULL) +#if defined(FULL_SAFE_BROWSING) safe_browsing::ChromePasswordProtectionService* password_protection = safe_browsing::ChromePasswordProtectionService:: GetPasswordProtectionService(profile);
diff --git a/chrome/browser/ui/webui/welcome/welcome_ui.cc b/chrome/browser/ui/webui/welcome/welcome_ui.cc index 4d26cf73..7fb5102e2 100644 --- a/chrome/browser/ui/webui/welcome/welcome_ui.cc +++ b/chrome/browser/ui/webui/welcome/welcome_ui.cc
@@ -4,7 +4,11 @@ #include "chrome/browser/ui/webui/welcome/welcome_ui.h" +#include <vector> + +#include "base/bind.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "build/build_config.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/ui/webui/dark_mode_handler.h" @@ -144,13 +148,17 @@ const bool is_nux_onboarding_enabled = nux::IsNuxOnboardingEnabled(profile); if (is_nux_onboarding_enabled) { - html_source->UseGzip(base::BindRepeating([](const std::string& path) { - for (size_t i = 0; i < kOnboardingWelcomeResourcesSize; ++i) { - if (path == kOnboardingWelcomeResources[i].name) - return kOnboardingWelcomeResources[i].gzipped; - } - return true; - })); + std::vector<std::string> gzipped_paths{""}; + for (size_t i = 0; i < kOnboardingWelcomeResourcesSize; ++i) { + if (kOnboardingWelcomeResources[i].gzipped) + gzipped_paths.emplace_back(kOnboardingWelcomeResources[i].name); + } + html_source->UseGzip(base::BindRepeating( + [](const std::vector<std::string>& gzipped_paths, + const std::string& path) { + return base::ContainsValue(gzipped_paths, path); + }, + std::move(gzipped_paths))); } bool is_dice =
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm index cde6a67..878bf53 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
@@ -75,6 +75,7 @@ @implementation TerminationObserver - (id)initWithRunningApplication:(NSRunningApplication*)app callback:(base::OnceClosure)callback { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (self = [super init]) { callback_ = std::move(callback); app_.reset(app, base::scoped_policy::RETAIN); @@ -96,22 +97,60 @@ NSNumber* newNumberValue = [change objectForKey:NSKeyValueChangeNewKey]; BOOL newValue = [newNumberValue boolValue]; if (newValue) { + base::scoped_nsobject<TerminationObserver> scoped_self( + self, base::scoped_policy::RETAIN); base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce( - [](TerminationObserver* observer) { [observer onTerminated]; }, - self)); + [](base::scoped_nsobject<TerminationObserver> observer) { + [observer onTerminated]; + }, + scoped_self)); } } - (void)onTerminated { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // If |onTerminated| is called repeatedly (which in theory it should not), + // then ensure that we only call removeObserver and release once by doing an + // early-out if |callback_| has already been made. + if (!callback_) + return; std::move(callback_).Run(); + DCHECK(!callback_); [app_ removeObserver:self forKeyPath:@"isTerminated" context:nullptr]; [self release]; } @end +// TODO(https://crbug.com/941909): Change all launch functions to take a single +// callback that returns a NSRunningApplication, rather than separate launch and +// termination callbacks. +void RunAppLaunchCallbacks( + base::scoped_nsobject<NSRunningApplication> app, + base::OnceCallback<void(base::Process)> launch_callback, + base::OnceClosure termination_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(app); + + // If the app doesn't have a valid pid, or if the application has been + // terminated, then indicate failure in |launch_callback|. + base::Process process([app processIdentifier]); + if (!process.IsValid() || [app isTerminated]) { + std::move(launch_callback).Run(base::Process()); + return; + } + + // Otherwise, indicate successful launch, and watch for termination. + // TODO(https://crbug.com/941909): This watches for termination indefinitely, + // but we only need to watch for termination until the app establishes a + // (whereupon termination will be noticed by the mojo connection closing). + std::move(launch_callback).Run(std::move(process)); + [[TerminationObserver alloc] + initWithRunningApplication:app + callback:std::move(termination_callback)]; +} + bool g_app_shims_allow_update_and_launch_in_tests = false; namespace { @@ -369,17 +408,16 @@ command_line.AppendSwitch(app_mode::kLaunchedAfterRebuild); // Launch without activating (NSWorkspaceLaunchWithoutActivation). - NSRunningApplication* app = base::mac::OpenApplicationWithPath( - shim_path, command_line, - NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation); + base::scoped_nsobject<NSRunningApplication> app( + base::mac::OpenApplicationWithPath( + shim_path, command_line, + NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation), + base::scoped_policy::RETAIN); if (app) { - base::Process process([app processIdentifier]); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(launched_callback), std::move(process))); - [[TerminationObserver alloc] - initWithRunningApplication:app - callback:std::move(terminated_callback)]; + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&RunAppLaunchCallbacks, app, + std::move(launched_callback), + std::move(terminated_callback))); return; } }
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 7c82a92..370728b 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -4,12 +4,21 @@ #include "chrome/common/chrome_features.h" +#include <vector> + #include "base/command_line.h" +#include "base/metrics/field_trial_params.h" +#include "base/no_destructor.h" +#include "base/strings/string_split.h" #include "build/build_config.h" #include "chrome/common/chrome_switches.h" #include "extensions/buildflags/buildflags.h" #include "ppapi/buildflags/buildflags.h" +#if defined(OS_ANDROID) +#include "base/android/build_info.h" +#endif + namespace features { // All features in alphabetical order. @@ -628,6 +637,39 @@ base::FEATURE_ENABLED_BY_DEFAULT}; #endif +#if defined(OS_ANDROID) +const base::Feature kUseDisplayWideColorGamut{"UseDisplayWideColorGamut", + base::FEATURE_ENABLED_BY_DEFAULT}; + +bool UseDisplayWideColorGamut() { + auto compute_use_display_wide_color_gamut = []() { + // Enabled this feature for devices listed in "enabled_models" field trial + // param. This is a comma separated list. + std::string enabled_models_list = base::GetFieldTrialParamValueByFeature( + kUseDisplayWideColorGamut, "enabled_models"); + if (enabled_models_list.empty()) + return false; + + const char* current_model = + base::android::BuildInfo::GetInstance()->model(); + std::vector<std::string> enabled_models = + base::SplitString(enabled_models_list, ",", base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + for (const std::string& model : enabled_models) { + if (model == current_model) + return true; + } + + return false; + }; + + // As it takes some work to compute this, cache the result. + static base::NoDestructor<bool> is_wide_color_gamut_enabled( + compute_use_display_wide_color_gamut()); + return *is_wide_color_gamut_enabled; +} +#endif + #if defined(OS_CHROMEOS) // Enables or disables logging for adaptive screen brightness on Chrome OS. const base::Feature kAdaptiveScreenBrightnessLogging{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 0b947172..39c60442 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -416,6 +416,14 @@ extern const base::Feature kUsageTimeStateNotifier; #endif +#if defined(OS_ANDROID) +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kUseDisplayWideColorGamut; + +COMPONENT_EXPORT(CHROME_FEATURES) +bool UseDisplayWideColorGamut(); +#endif + #if defined(OS_CHROMEOS) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kAdaptiveScreenBrightnessLogging;
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index d8207cd2..e27de98 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -13,6 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" +#include "build/build_config.h" #include "chrome/test/base/chrome_render_view_test.h" #include "components/autofill/content/renderer/form_autofill_util.h" #include "components/autofill/content/renderer/form_cache.h" @@ -32,6 +33,10 @@ #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_select_element.h" +#if defined(OS_WIN) +#include "third_party/blink/public/web/win/web_font_rendering.h" +#endif + using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics; using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery; using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload; @@ -279,6 +284,17 @@ } ~FormAutofillTest() override {} +#if defined(OS_WIN) + void SetUp() override { + ChromeRenderViewTest::SetUp(); + + // Autofill uses the system font to render suggestion previews. On Windows + // an extra step is required to ensure that the system font is configured. + blink::WebFontRendering::SetMenuFontMetrics( + base::ASCIIToUTF16("Arial").c_str(), 12); + } +#endif + void ExpectLabels(const char* html, const std::vector<base::string16>& id_attributes, const std::vector<base::string16>& name_attributes,
diff --git a/chrome/renderer/resources/plugins/plugin_poster.html b/chrome/renderer/resources/plugins/plugin_poster.html index 6758fa72..ec97d91 100644 --- a/chrome/renderer/resources/plugins/plugin_poster.html +++ b/chrome/renderer/resources/plugins/plugin_poster.html
@@ -72,7 +72,7 @@ <body> <div title="$i18n{name}" id="outer"> - <img id="poster" i18n-values="srcset:poster"> + <img id="poster" srcset="$i18n{poster}"> <div id="shielding"></div> <div id="inner-container" style="width:$i18n{visibleWidth};height:$i18n{visibleHeight}">
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 7478f0d..65aacb7 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -354,6 +354,7 @@ # For isolate contract. "//testing/scripts/common.py", "//testing/xvfb.py", + "//testing/scripts/gpu_integration_test_adapter.py", "//testing/scripts/run_gpu_integration_test_as_googletest.py", "//testing/trigger_scripts/trigger_multiple_dimensions.py", @@ -2858,6 +2859,7 @@ # TODO(hashimoto): those tests should be componentized and moved to # //components:components_unittests, http://crbug.com/527882. + "../browser/scoped_visibility_tracker_unittest.cc", "../browser/search_engines/template_url_fetcher_unittest.cc", "../browser/search_engines/template_url_parser_unittest.cc", "../browser/search_engines/template_url_service_sync_unittest.cc", @@ -2920,7 +2922,6 @@ "../browser/ui/bloated_renderer/bloated_renderer_tab_helper_unittest.cc", "../browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc", "../browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc", - "../browser/ui/blocked_content/scoped_visibility_tracker_unittest.cc", "../browser/ui/bookmarks/bookmark_editor_unittest.cc", "../browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc", "../browser/ui/bookmarks/recently_used_folders_combo_model_unittest.cc", @@ -4325,6 +4326,8 @@ "../service/service_ipc_server_unittest.cc", "../service/service_process_prefs_unittest.cc", ] + } else { + sources += [ "../browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc" ] } }
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index c4808c4..41ca463 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc
@@ -90,10 +90,14 @@ #if defined(OS_CHROMEOS) #include "ash/test/ui_controls_factory_ash.h" +#include "base/system/sys_info.h" #include "chrome/browser/chromeos/input_method/input_method_configuration.h" #include "chrome/test/base/default_ash_event_generator_delegate.h" +#include "chromeos/constants/chromeos_switches.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/services/device_sync/device_sync_impl.h" #include "chromeos/services/device_sync/fake_device_sync.h" +#include "components/user_manager/user_names.h" #include "ui/aura/test/mus/change_completion_waiter.h" #include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window.h" @@ -231,17 +235,37 @@ << "Could not set up user data directory."; #if defined(OS_CHROMEOS) - // Make sure that the log directory exists. - base::FilePath log_dir = logging::GetSessionLogDir(*command_line); - base::CreateDirectory(log_dir); + // No need to redirect log for test. + command_line->AppendSwitch(switches::kDisableLoggingRedirect); + // Disable IME extension loading to avoid many browser tests failures. chromeos::input_method::DisableExtensionLoading(); - if (!command_line->HasSwitch(switches::kHostWindowBounds)) { + + if (!command_line->HasSwitch(switches::kHostWindowBounds) && + !base::SysInfo::IsRunningOnChromeOS()) { // Adjusting window location & size so that the ash desktop window fits - // inside the Xvfb'x default resolution. + // inside the Xvfb's default resolution. Only do that when not running + // on device. Otherwise, device display is not properly configured. command_line->AppendSwitchASCII(switches::kHostWindowBounds, "0+0-1280x800"); } + + // Default to run in a signed in session of stub user if tests do not run + // in the login screen (--login-manager), or logged in user session + // (--login-user), or the guest session (--bwsi). This is essentially + // the same as in ChromeBrowserMainPartsChromeos::PreEarlyInitialization + // but it will be done on device and only for tests. + if (!command_line->HasSwitch(chromeos::switches::kLoginManager) && + !command_line->HasSwitch(chromeos::switches::kLoginUser) && + !command_line->HasSwitch(chromeos::switches::kGuestSession)) { + command_line->AppendSwitchASCII( + chromeos::switches::kLoginUser, + cryptohome::Identification(user_manager::StubAccountId()).id()); + if (!command_line->HasSwitch(chromeos::switches::kLoginProfile)) { + command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, + chrome::kTestUserProfileDir); + } + } #endif SetScreenInstance();
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc index 1d43bf2d..a2b42ba 100644 --- a/chrome/test/chromedriver/capabilities.cc +++ b/chrome/test/chromedriver/capabilities.cc
@@ -225,12 +225,20 @@ return Status(kInvalidArgument, "'timeouts' must be a JSON object"); for (const auto& it : timeouts->DictItems()) { int64_t timeout_ms_int64 = -1; - if (!GetOptionalSafeInt(timeouts, it.first, &timeout_ms_int64) - || timeout_ms_int64 < 0) - return Status(kInvalidArgument, "value must be a non-negative integer"); - base::TimeDelta timeout = - base::TimeDelta::FromMilliseconds(timeout_ms_int64); + base::TimeDelta timeout; const std::string& type = it.first; + if (it.second.is_none()) { + if (type == "script") + timeout = base::TimeDelta::Max(); + else + return Status(kInvalidArgument, "timeout can not be null"); + } else { + if (!GetOptionalSafeInt(timeouts, it.first, &timeout_ms_int64) || + timeout_ms_int64 < 0) + return Status(kInvalidArgument, "value must be a non-negative integer"); + else + timeout = base::TimeDelta::FromMilliseconds(timeout_ms_int64); + } if (type == "script") { capabilities->script_timeout = timeout; } else if (type == "pageLoad") {
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc index abe0053..055ad1a 100644 --- a/chrome/test/chromedriver/session_commands.cc +++ b/chrome/test/chromedriver/session_commands.cc
@@ -133,8 +133,11 @@ } else { caps->SetBoolean("setWindowRect", true); } - SetSafeInt(caps.get(), "timeouts.script", - session->script_timeout.InMilliseconds()); + if (session->script_timeout == base::TimeDelta::Max()) + caps->SetPath({"timeouts", "script"}, base::Value()); + else + SetSafeInt(caps.get(), "timeouts.script", + session->script_timeout.InMilliseconds()); SetSafeInt(caps.get(), "timeouts.pageLoad", session->page_load_timeout.InMilliseconds()); SetSafeInt(caps.get(), "timeouts.implicit", @@ -755,12 +758,21 @@ std::unique_ptr<base::Value>* value) { for (const auto& setting : params.DictItems()) { int64_t timeout_ms_int64 = -1; - if (!GetOptionalSafeInt(¶ms, setting.first, &timeout_ms_int64) || - timeout_ms_int64 < 0) - return Status(kInvalidArgument, "value must be a non-negative integer"); - base::TimeDelta timeout = - base::TimeDelta::FromMilliseconds(timeout_ms_int64); + base::TimeDelta timeout; const std::string& type = setting.first; + if (setting.second.is_none()) { + if (type == "script") + timeout = base::TimeDelta::Max(); + else + return Status(kInvalidArgument, "timeout can not be null"); + } else { + if (!GetOptionalSafeInt(¶ms, setting.first, &timeout_ms_int64) + || timeout_ms_int64 < 0) + return Status(kInvalidArgument, + "value must be a non-negative integer"); + else + timeout = base::TimeDelta::FromMilliseconds(timeout_ms_int64); + } if (type == "script") { session->script_timeout = timeout; } else if (type == "pageLoad") { @@ -791,7 +803,11 @@ const base::DictionaryValue& params, std::unique_ptr<base::Value>* value) { base::DictionaryValue timeouts; - SetSafeInt(&timeouts, "script", session->script_timeout.InMilliseconds()); + if (session->script_timeout == base::TimeDelta::Max()) + timeouts.SetKey("script", base::Value()); + else + SetSafeInt(&timeouts, "script", session->script_timeout.InMilliseconds()); + SetSafeInt(&timeouts, "pageLoad", session->page_load_timeout.InMilliseconds()); SetSafeInt(&timeouts, "implicit", session->implicit_wait.InMilliseconds());
diff --git a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js index aaa43008..6774e9b 100644 --- a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js +++ b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js
@@ -58,11 +58,7 @@ chrome.runtime.sendMessage(FRIEND_EXTENSION_ID, 'message_self', function response() { }); }, - expected_activity_js: [ - 'runtime.connect', - 'runtime.sendMessage' - ], - expected_activity_native: [ + expected_activity: [ 'runtime.sendMessage' ] }); @@ -71,11 +67,7 @@ chrome.runtime.sendMessage(FRIEND_EXTENSION_ID, 'message_other', function response() { }); }, - expected_activity_js: [ - 'runtime.connect', - 'runtime.sendMessage' - ], - expected_activity_native: [ + expected_activity: [ 'runtime.sendMessage' ] }); @@ -182,17 +174,7 @@ chrome.runtime.sendMessage(FRIEND_EXTENSION_ID, 'api_tab_updated', function response() { }); }, - expected_activity_js: [ - 'tabs.onUpdated', - 'tabs.onUpdated', - 'tabs.onUpdated', - 'tabs.connect', - 'tabs.sendMessage', - 'tabs.executeScript', - 'tabs.executeScript', - 'tabs.remove' - ], - expected_activity_native: [ + expected_activity: [ 'tabs.onUpdated', 'tabs.onUpdated', 'tabs.onUpdated', @@ -209,18 +191,7 @@ function response() { }); }, is_incognito: true, - expected_activity_js: [ - 'windows.create', - 'tabs.onUpdated', - 'tabs.onUpdated', - 'tabs.onUpdated', - 'tabs.connect', - 'tabs.sendMessage', - 'tabs.executeScript', - 'tabs.executeScript', - 'tabs.remove' - ], - expected_activity_native: [ + expected_activity: [ 'windows.create', 'tabs.onUpdated', 'tabs.onUpdated', @@ -556,16 +527,6 @@ console.log('Expecting OS specific activity for: ' + info.os); enabledTestCase.expected_activity = enabledTestCase[activityListForOS]; - } else if ('expected_activity_js' in enabledTestCase) { - // Some tests have different activity depending on whether native - // bindings are being used. This is in the case of the extension - // using the sendMessage() API. With JS bindings, this is - // implemented using connect(), so both API calls are seen. With - // native bindings, we fix this, and only the sendMessage call is - // seen. - var key = config.nativeCrxBindingsEnabled ? - 'expected_activity_native' : 'expected_activity_js'; - enabledTestCase.expected_activity = enabledTestCase[key]; } enabledTestCases.push(enabledTestCase);
diff --git a/chrome/test/data/extensions/api_test/bindings/invalidate_context/background.js b/chrome/test/data/extensions/api_test/bindings/invalidate_context/background.js index 5ea3ef4..9280fae 100644 --- a/chrome/test/data/extensions/api_test/bindings/invalidate_context/background.js +++ b/chrome/test/data/extensions/api_test/bindings/invalidate_context/background.js
@@ -6,7 +6,6 @@ var frameRuntime; var frameStorage; var frameTabs; -var nativeBindingsEnabled; function createFrame() { frame = document.createElement('iframe'); @@ -54,12 +53,6 @@ chrome.test.assertTrue(result.postMessageThrow); chrome.test.assertTrue(result.disconnectThrow); - // With native bindings, the event object instantiated on a Port is set as a - // lazy data property, and thus is safe to access even after the context has - // been removed. JS bindings always throw errors when trying to access them - // after context invalidation. - expectEventsValid &= nativeBindingsEnabled; - if (expectEventsValid) { chrome.test.assertFalse(result.getOnMessageThrow); chrome.test.assertFalse(result.getOnDisconnectThrow); @@ -73,7 +66,7 @@ } } -const tests = [ +chrome.test.runTests([ function useFrameStorageAndRuntime() { createFrame().then(() => { frameRuntime = frame.contentWindow.chrome.runtime; @@ -150,9 +143,4 @@ chrome.test.succeed(); }); }, -]; - -chrome.test.getConfig((config) => { - nativeBindingsEnabled = config.nativeCrxBindingsEnabled; - chrome.test.runTests(tests); -}); +]);
diff --git a/chrome/test/data/extensions/api_test/messaging/connect/page.js b/chrome/test/data/extensions/api_test/messaging/connect/page.js index f349a355..02c7675d 100644 --- a/chrome/test/data/extensions/api_test/messaging/connect/page.js +++ b/chrome/test/data/extensions/api_test/messaging/connect/page.js
@@ -2,30 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -function clobberJSON() { - JSON.parse = function() { - return "JSON.parse clobbered by content script."; - }; - - JSON.stringify = function() { - return "JSON.stringify clobbered by content script."; - }; - - Array.prototype.toJSON = function() { - return "Array.prototype.toJSON clobbered by content script."; - }; - - Object.prototype.toJSON = function() { - return "Object.prototype.toJSON clobbered by content script."; - }; -} - -chrome.test.getConfig((config) => { - // We don't clobber JSON with native bindings. See https://crbug.com/792602. - if (!config.nativeCrxBindingsEnabled) - clobberJSON(); -}); - // For complex connect tests. chrome.runtime.onConnect.addListener(function onConnect(port) { console.log('connected');
diff --git a/chrome/test/data/extensions/api_test/messaging/connect/test.js b/chrome/test/data/extensions/api_test/messaging/connect/test.js index 48ab6425..0310b73 100644 --- a/chrome/test/data/extensions/api_test/messaging/connect/test.js +++ b/chrome/test/data/extensions/api_test/messaging/connect/test.js
@@ -5,24 +5,6 @@ var listenOnce = chrome.test.listenOnce; var listenForever = chrome.test.listenForever; -function clobberJSON() { - JSON.parse = function() { - return "JSON.parse clobbered by extension."; - }; - - JSON.stringify = function() { - return "JSON.stringify clobbered by extension."; - }; - - Array.prototype.toJSON = function() { - return "Array.prototype.toJSON clobbered by extension."; - }; - - Object.prototype.toJSON = function() { - return "Object.prototype.toJSON clobbered by extension."; - }; -} - // Keep track of the tab that we're running tests in, for simplicity. var testTab = null; @@ -45,10 +27,6 @@ } chrome.test.getConfig(function(config) { - // We don't clobber JSON with native bindings. See https://crbug.com/792602. - if (!config.nativeCrxBindingsEnabled) - clobberJSON(); - chrome.test.runTests([ function setupTestTab() { chrome.test.log("Creating tab..."); @@ -279,20 +257,16 @@ // Tests that a message which fails to serialize prints an error and // doesn't send (http://crbug.com/263077). function unserializableMessage() { - // Unserializable messages throw an error with native bindings, and only - // log a warning with JS bindings. - var expectThrow = config.nativeCrxBindingsEnabled; try { chrome.tabs.connect(testTab.id).postMessage(function() { // This shouldn't ever be called, so it's a bit pointless. chrome.test.fail(); }); - // Didn't crash. - chrome.test.assertFalse(expectThrow); + // The call above should have thrown an error. + chrome.test.fail(); } catch (e) { - chrome.test.assertTrue(expectThrow); + chrome.test.succeed(); } - chrome.test.succeed(); }, // Tests that reloading a child frame disconnects the port if it was the
diff --git a/chrome/test/data/webui/print_preview/destination_select_test.js b/chrome/test/data/webui/print_preview/destination_select_test.js index 68b91f5e..7575ac6 100644 --- a/chrome/test/data/webui/print_preview/destination_select_test.js +++ b/chrome/test/data/webui/print_preview/destination_select_test.js
@@ -21,7 +21,7 @@ const suiteName = 'DestinationSelectTests'; suite(suiteName, function() { /** @type {?PrintPreviewAppElement} */ - let page = null; + let destinationSettings = null; /** @type {?PrintPreview.NativeLayerStub} */ let nativeLayer = null; @@ -63,30 +63,45 @@ nativeLayer.setLocalDestinations(localDestinations); print_preview.NativeLayer.setInstance(nativeLayer); const cloudPrintInterface = new print_preview.CloudPrintInterfaceStub(); - cloudprint.setCloudPrintInterfaceForTesting(cloudPrintInterface); cloudDestinations.forEach(cloudDestination => { cloudPrintInterface.setPrinter(cloudDestination); }); PolymerTest.clearBody(); - page = document.createElement('print-preview-app'); - document.body.appendChild(page); - cr.webUIListenerCallback('use-cloud-print', 'cloudprint url', false); - page.destinationStore_.addEventListener( + destinationSettings = + document.createElement('print-preview-destination-settings'); + destinationSettings.destination = null; + document.body.appendChild(destinationSettings); + const whenCapabilitiesReady = test_util.eventToPromise( + print_preview.DestinationStore.EventType + .SELECTED_DESTINATION_CAPABILITIES_READY, + destinationSettings.destinationStore_); + destinationSettings.destinationStore_.addEventListener( print_preview.DestinationStore.EventType.DESTINATION_SELECT, function() { numPrintersSelected++; }); - const whenCapabilitiesReady = test_util.eventToPromise( - print_preview.DestinationStore.EventType - .SELECTED_DESTINATION_CAPABILITIES_READY, - page.destinationStore_); - - return nativeLayer.whenCalled('getInitialSettings').then(() => { - return opt_expectPrinterFailure ? Promise.resolve() : Promise.race([ - nativeLayer.whenCalled('getPrinterCapabilities'), - whenCapabilitiesReady - ]); - }); + destinationSettings.setCloudPrintInterface(cloudPrintInterface); + destinationSettings.appKioskMode = initialSettings.isInAppKioskMode; + const recentDestinations = initialSettings.serializedAppStateStr ? + JSON.parse(initialSettings.serializedAppStateStr).recentDestinations : + []; + destinationSettings.settings = { + recentDestinations: { + value: recentDestinations, + unavailableValue: [], + valid: true, + available: true, + setByPolicy: false, + key: 'recentDestinations', + }, + }; + destinationSettings.initDestinationStore( + initialSettings.printerName, + initialSettings.serializedDefaultDestinationSelectionRulesStr); + destinationSettings.disabled = false; + return opt_expectPrinterFailure ? Promise.resolve() : Promise.race([ + nativeLayer.whenCalled('getPrinterCapabilities'), whenCapabilitiesReady + ]); } /** @@ -97,7 +112,6 @@ * @return {!Promise} Promise that resolves when checks are complete. */ function assertPrinterDisplay(printerName, disabled) { - const destinationSettings = page.$$('print-preview-destination-settings'); const destinationSelect = destinationSettings.$.destinationSelect; Polymer.dom.flush(); @@ -130,7 +144,7 @@ return setInitialSettings().then(function(args) { assertEquals('ID1', args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals('ID1', page.destination_.id); + assertEquals('ID1', destinationSettings.destination.id); return assertPrinterDisplay('One', false); }); }); @@ -155,12 +169,13 @@ // recent. assertEquals('ID1', args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals('ID1', page.destination_.id); + assertEquals('ID1', destinationSettings.destination.id); return assertPrinterDisplay('One', false); }) .then(function() { // Verify the correct printers are marked as recent in the store. - const reportedPrinters = page.destinationStore_.destinations(); + const reportedPrinters = + destinationSettings.destinationStore_.destinations(); destinations.forEach((destination, index) => { const match = reportedPrinters.find((reportedPrinter) => { return reportedPrinter.id == destination.id; @@ -191,18 +206,12 @@ // recent. assertEquals('ID1', args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals('ID1', page.destination_.id); - - return nativeLayer.whenCalled('getPreview'); - }) - .then(function(previewArgs) { - const ticket = JSON.parse(previewArgs.printTicket); - assertEquals(0, ticket.requestID); - assertEquals('ID1', ticket.deviceName); + assertEquals('ID1', destinationSettings.destination.id); // The other recent destinations should be prefetched, but only one // should have been selected so there was only one preview request. - const reportedPrinters = page.destinationStore_.destinations(); + const reportedPrinters = + destinationSettings.destinationStore_.destinations(); assertEquals(4, reportedPrinters.length); destinations.forEach((destination, index) => { assertEquals( @@ -226,7 +235,7 @@ // the rules. assertEquals('ID4', args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals('ID4', page.destination_.id); + assertEquals('ID4', destinationSettings.destination.id); return assertPrinterDisplay('Four', false); }); }); @@ -255,12 +264,12 @@ test_util.eventToPromise( print_preview.DestinationStore.EventType .SELECTED_DESTINATION_CAPABILITIES_READY, - page.destinationStore_), + destinationSettings.destinationStore_), ]) .then(function(argsArray) { // Need to load FooDevice as the printer, since it is the system // default. - assertEquals('FooDevice', page.destination_.id); + assertEquals('FooDevice', destinationSettings.destination.id); assertPrinterDisplay('FooName', false); }); }); @@ -281,7 +290,7 @@ // Should have loaded the first destination as the selected printer. assertEquals(destinations[0].id, args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals(destinations[0].id, page.destination_.id); + assertEquals(destinations[0].id, destinationSettings.destination.id); return assertPrinterDisplay(destinations[0].displayName, false); }); }); @@ -303,13 +312,11 @@ .all([ setInitialSettings(true), test_util.eventToPromise( - print_preview.DestinationStore.EventType.NO_DESTINATIONS_FOUND, - page.destinationStore_), + print_preview.DestinationStore.EventType.ERROR, + destinationSettings.destinationStore_), ]) .then(function() { - assertEquals(null, page.destination_); - const destinationSettings = - page.$$('print-preview-destination-settings'); + assertEquals(null, destinationSettings.destination); assertTrue(destinationSettings.$$('.throbber-container').hidden); const destinationSelect = destinationSettings.$.destinationSelect; assertFalse(destinationSelect.hidden); @@ -334,10 +341,9 @@ }); return setInitialSettings().then(function(args) { - assertEquals(print_preview_new.State.READY, page.state); assertEquals('FooDevice', args.destinationId); assertEquals(print_preview.PrinterType.LOCAL, args.type); - assertEquals('FooDevice', page.destination_.id); + assertEquals('FooDevice', destinationSettings.destination.id); return assertPrinterDisplay('FooName', false); }); }); @@ -358,17 +364,15 @@ print_preview.DestinationStore.AUTO_SELECT_TIMEOUT_ = 0; return setInitialSettings() .then(function() { - assertEquals(print_preview_new.State.READY, page.state); assertPrinterDisplay('Save as PDF', false); // Simulate setting a bad ticket value. - page.$.state.transitTo(print_preview_new.State.INVALID_TICKET); + destinationSettings.disabled = true; return new Promise(resolve => setTimeout(resolve)); }) .then(function() { // Should still have Save as PDF. Dropdown is disabled due to // invalid ticket. assertPrinterDisplay('Save as PDF', true); - assertEquals(print_preview_new.State.INVALID_TICKET, page.state); }); }); @@ -405,20 +409,13 @@ // was most recent. assertEquals( print_preview.Destination.GooglePromotedId.DOCS, - page.destination_.id); + destinationSettings.destination.id); assertPrinterDisplay('Save to Google Drive', false); - return nativeLayer.whenCalled('getPreview'); - }) - .then(function(previewArgs) { - const ticket = JSON.parse(previewArgs.printTicket); - assertEquals(0, ticket.requestID); - assertEquals( - print_preview.Destination.GooglePromotedId.DOCS, - ticket.deviceName); // Only the other cloud destination for the same user account should // have been prefetched. - const loadedPrinters = page.destinationStore_.destinations(); + const loadedPrinters = + destinationSettings.destinationStore_.destinations(); assertEquals(3, loadedPrinters.length); cloudDestinations.forEach((destination) => { assertEquals(
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js index 1e174e18..19191d8 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test.js +++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -15,6 +15,7 @@ SelectRecentDestination: 'select recent destination', OpenDialog: 'open dialog', TwoAccountsRecentDestinations: 'two accounts recent destinations', + UpdateRecentDestinations: 'update recent destinations', }; const suiteName = 'DestinationSettingsTest'; @@ -57,14 +58,16 @@ destinationSettings = document.createElement('print-preview-destination-settings'); - destinationSettings.destinationStore = null; - destinationSettings.destination = null; - destinationSettings.recentDestinations = []; - destinationSettings.state = print_preview_new.State.NOT_READY; - destinationSettings.cloudPrintState = - print_preview.CloudPrintState.DISABLED; - destinationSettings.noDestinationsFound = false; - // Disabled is true when state is NOT_READY. + destinationSettings.settings = { + recentDestinations: { + value: [], + unavailableValue: [], + available: true, + valid: true, + setByPolicy: false, + key: 'recentDestinations', + }, + }; destinationSettings.disabled = true; document.body.appendChild(destinationSettings); }); @@ -79,58 +82,61 @@ // Set up the destination store, but no destination yet. Dropdown is still // hidden. - const destinationStore = - print_preview_test_utils.createDestinationStore(); - destinationStore.init( - false /* isInAppKioskMode */, 'FooDevice' /* printerName */, - '' /* serializedDefaultDestinationSelectionRulesStr */, - [] /* recentDestinations */); - destinationSettings.destinationStore = destinationStore; - destinationSettings.state = print_preview_new.State.NOT_READY; + destinationSettings.initDestinationStore( + 'FooDevice' /* printerName */, + '' /* serializedDefaultDestinationSelectionRulesStr */); assertTrue(dropdown.hidden); - // Simulate loading a recent destination. - destinationSettings.destination = new print_preview.Destination( - 'FooDevice', print_preview.DestinationType.LOCAL, getLocalOrigin(), - 'FooName', print_preview.DestinationConnectionStatus.ONLINE); - destinationSettings.recentDestinations = [ - print_preview.makeRecentDestination(destinationSettings.destination), - ]; - destinationSettings.cloudPrintState = - print_preview.CloudPrintState.NOT_SIGNED_IN; - destinationSettings.state = print_preview_new.State.READY; + return test_util + .eventToPromise( + print_preview.DestinationStore.EventType + .SELECTED_DESTINATION_CAPABILITIES_READY, + destinationSettings.destinationStore_) + .then(() => { + // Dropdown is visible but disabled since controls are disabled. + assertTrue(dropdown.disabled); + assertFalse(dropdown.hidden); + destinationSettings.disabled = false; - // Dropdown is visible but disabled due to NOT_READY state. - assertTrue(dropdown.disabled); - assertFalse(dropdown.hidden); + assertFalse(dropdown.disabled); - // Enable controls. - destinationSettings.disabled = false; - return test_util.waitForRenderOrTimeout0(dropdown).then(() => { - assertFalse(dropdown.disabled); + // Simulate setting a setting to an invalid value. Dropdown is + // disabled due to validation error on another control. + destinationSettings.disabled = true; + assertTrue(dropdown.disabled); - // Simulate setting a setting to an invalid value. Dropdown is disabled - // due to validation error on another control. - destinationSettings.state = print_preview_new.State.INVALID_TICKET; - destinationSettings.disabled = true; - assertTrue(dropdown.disabled); + // Simulate the user fixing the validation error, and then selecting + // an invalid printer. Dropdown is enabled, so that the user can fix + // the error. + destinationSettings.disabled = false; + destinationSettings.destinationStore_.dispatchEvent(new CustomEvent( + print_preview.DestinationStore.EventType.ERROR, + {detail: print_preview.DestinationErrorType.INVALID})); + Polymer.dom.flush(); - // Simulate the user fixing the validation error, and then selecting an - // invalid printer. Dropdown is enabled, so that the user can fix the - // error. - destinationSettings.state = print_preview_new.State.READY; - destinationSettings.disabled = false; - destinationSettings.state = print_preview_new.State.INVALID_PRINTER; - destinationSettings.disabled = true; - assertFalse(dropdown.disabled); + assertEquals( + print_preview.DestinationState.INVALID, + destinationSettings.destinationState); + destinationSettings.disabled = true; + assertFalse(dropdown.disabled); - // Simulate the user having no printers. - destinationSettings.destination = null; - destinationSettings.state = print_preview_new.State.INVALID_PRINTER; - destinationSettings.disabled = true; - destinationSettings.noDestinationsFound = true; - assertTrue(dropdown.disabled); - }); + if (cr.isChromeOS) { + // Simulate the user having no printers. + destinationSettings.destinationStore_.dispatchEvent( + new CustomEvent( + print_preview.DestinationStore.EventType.ERROR, { + detail: + print_preview.DestinationErrorType.NO_DESTINATIONS + })); + Polymer.dom.flush(); + + assertEquals( + print_preview.DestinationState.NO_DESTINATIONS, + destinationSettings.destinationState); + destinationSettings.disabled = true; + assertTrue(dropdown.disabled); + } + }); }); /** @return {!print_preview.DestinationOrigin} */ @@ -144,39 +150,21 @@ * |destinations| and |recentDestinations|. */ function initialize() { - const destinationStore = - print_preview_test_utils.createDestinationStore(); - // Initialize destination settings. - destinationSettings.destinationStore = destinationStore; - destinationSettings.invitationStore = new print_preview.InvitationStore(); - destinationSettings.recentDestinations = recentDestinations; + destinationSettings.setCloudPrintInterface(cloudPrintInterface); + destinationSettings.setSetting('recentDestinations', recentDestinations); destinationSettings.appKioskMode = false; - destinationSettings.activeUser = ''; - destinationSettings.users = []; + destinationSettings.initDestinationStore( + '' /* printerName */, + '' /* serializedDefaultDestinationSelectionRulesStr */); destinationSettings.disabled = false; - destinationSettings.state = print_preview_new.State.READY; - destinationSettings.cloudPrintState = - print_preview.CloudPrintState.ENABLED; - - // Initialize destination store. - destinationStore.setCloudPrintInterface(cloudPrintInterface); - destinationStore.init( - false /* isInAppKioskMode */, 'FooDevice' /* printerName */, - '' /* serializedDefaultDestinationSelectionRulesStr */, - recentDestinations); } /** Simulates a user signing in to Chrome. */ function signIn() { cloudPrintInterface.setPrinter( print_preview_test_utils.getGoogleDriveDestination(defaultUser)); - destinationSettings.activeUser = defaultUser; - destinationSettings.users = [defaultUser]; - destinationSettings.cloudPrintState = - print_preview.CloudPrintState.SIGNED_IN; - destinationSettings.destinationStore.setActiveUser(defaultUser); - destinationSettings.destinationStore.onDestinationsReload(); + cr.webUIListenerCallback('reload-printer-list'); Polymer.dom.flush(); } @@ -376,7 +364,7 @@ // Simulate selection of Save as PDF printer. const whenDestinationSelect = test_util.eventToPromise( print_preview.DestinationStore.EventType.DESTINATION_SELECT, - destinationSettings.destinationStore); + destinationSettings.destinationStore_); dropdown.fire('selected-option-change', 'Save as PDF/local/'); // Ensure this fires the destination select event. @@ -385,7 +373,7 @@ .then(() => { assertEquals( print_preview.Destination.GooglePromotedId.SAVE_AS_PDF, - destinationSettings.destinationStore.selectedDestination_.id); + destinationSettings.destination.id); }); }); @@ -425,7 +413,7 @@ // Simulate selection of Google Drive printer. const whenDestinationSelect = test_util.eventToPromise( print_preview.DestinationStore.EventType.DESTINATION_SELECT, - destinationSettings.destinationStore); + destinationSettings.destinationStore_); dropdown.fire( 'selected-option-change', '__google__docs/cookies/foo@chromium.org'); @@ -434,7 +422,7 @@ .then(() => { assertEquals( print_preview.Destination.GooglePromotedId.DOCS, - destinationSettings.destinationStore.selectedDestination_.id); + destinationSettings.destination.id); }); }); @@ -468,15 +456,13 @@ // Simulate selection of Save as PDF printer. const whenDestinationSelect = test_util.eventToPromise( print_preview.DestinationStore.EventType.DESTINATION_SELECT, - destinationSettings.destinationStore); + destinationSettings.destinationStore_); dropdown.fire( 'selected-option-change', makeLocalDestinationKey('ID2')); return whenDestinationSelect; }) .then(() => { - assertEquals( - 'ID2', - destinationSettings.destinationStore.selectedDestination_.id); + assertEquals('ID2', destinationSettings.destination.id); }); }); @@ -513,17 +499,6 @@ }); }); - /* - * Simulates setting a new user account. Normally done in user_info.js. - * @param {string} newAccount - */ - function updateUser(newAccount) { - destinationSettings.activeUser = newAccount; - destinationSettings.destinationStore.setActiveUser(newAccount); - destinationSettings.destinationStore.reloadUserCookieBasedDestinations( - newAccount); - } - test(assert(TestNames.TwoAccountsRecentDestinations), function() { const account2 = 'bar@chromium.org'; const driveUser1 = @@ -551,10 +526,6 @@ ].map(destination => print_preview.makeRecentDestination(destination)); initialize(); - destinationSettings.users = [defaultUser, account2]; - destinationSettings.cloudPrintState = - print_preview.CloudPrintState.SIGNED_IN; - updateUser(defaultUser); Polymer.dom.flush(); const dropdown = destinationSettings.$.destinationSelect; @@ -580,11 +551,11 @@ return test_util.waitForRender(destinationSettings); }) .then(() => { - assertTrue( - destinationSettings.$$('print-preview-destination-dialog') - .isOpen()); + const dialog = + destinationSettings.$$('print-preview-destination-dialog'); + assertTrue(dialog.isOpen()); // Simulate setting a new account. - updateUser(account2); + dialog.fire('account-change', account2); Polymer.dom.flush(); return test_util.waitForRender(destinationSettings); }) @@ -597,6 +568,57 @@ ]); }); }); + + /** + * @param {!Array<string>} expectedDestinationIds An array of the expected + * recent destination ids. + */ + function assertRecentDestinations(expectedDestinationIds) { + const recentDestinations = + destinationSettings.getSettingValue('recentDestinations'); + assertEquals(expectedDestinationIds.length, recentDestinations.length); + expectedDestinationIds.forEach((expectedId, index) => { + assertEquals(expectedId, recentDestinations[index].id); + }); + } + + function selectDestination(destination) { + destinationSettings.destinationStore_.selectDestination(destination); + Polymer.dom.flush(); + } + + /** + * Tests that the destination being set correctly updates the recent + * destinations array. + */ + test(assert(TestNames.UpdateRecentDestinations), function() { + // Recent destinations start out empty. + assertRecentDestinations([]); + + initialize(); + + // Recent destinations start out empty. + assertRecentDestinations(['Save as PDF']); + + // Simulate setting a destination. + selectDestination(destinations[0]); + assertRecentDestinations(['ID1', 'Save as PDF']); + + // Reselect a recent destination. Still 2 destinations, but in a + // different order. + selectDestination( + destinationSettings.destinationStore_.getDestinationByKey( + 'Save as PDF/local/')), + assertRecentDestinations(['Save as PDF', 'ID1']); + + // Select a third destination + selectDestination(destinations[1]); + assertRecentDestinations(['ID2', 'Save as PDF', 'ID1']); + + // Select a fourth destination. List does not grow. + selectDestination(destinations[2]); + assertRecentDestinations(['ID3', 'ID2', 'Save as PDF']); + }); }); return {
diff --git a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js index 46b056f..f9416e4 100644 --- a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js +++ b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
@@ -100,8 +100,6 @@ createPage(true); - page.activeUser = 'foo@chromium.org'; - page.users = [page.activeUser]; cr.webUIListenerCallback('use-cloud-print', 'cloudprint url', false); printers.forEach(printer => cloudPrintInterface.setPrinter(printer)); } @@ -155,10 +153,11 @@ const messageEl = previewAreaEl.$$('.preview-area-message'); const header = page.$$('print-preview-header'); const printButton = header.$$('.action-button'); + const destinationSettings = page.$$('print-preview-destination-settings'); return nativeLayer.whenCalled('getInitialSettings') .then(function() { - page.destinationStore_.startLoadAllDestinations(); + destinationSettings.destinationStore_.startLoadAllDestinations(); // Wait for the preview request. return Promise.all([ nativeLayer.whenCalled('getPrinterCapabilities'), @@ -178,15 +177,14 @@ nativeLayer.reset(); // Select a new destination - const barDestination = page.destinationStore_.destinations().find( - d => d.id == 'BarDevice'); - page.destinationStore_.selectDestination(barDestination); + const barDestination = + destinationSettings.destinationStore_.destinations().find( + d => d.id == 'BarDevice'); + destinationSettings.destinationStore_.selectDestination( + barDestination); // Wait for the preview to be updated. - return Promise.all([ - nativeLayer.whenCalled('getPrinterCapabilities'), - nativeLayer.whenCalled('getPreview') - ]); + return nativeLayer.whenCalled('getPreview'); }) .then(function() { // Message should be gone. @@ -260,7 +258,7 @@ // Set this to enable the scaling input. page.setSetting('customScaling', true); - page.destinationStore_.startLoadCloudDestinations(); + destinationSettings.destinationStore_.startLoadCloudDestinations(); // FooDevice will be selected since it is the most recently used // printer, so the invalid certificate error should be shown. @@ -288,7 +286,9 @@ nativeLayer.reset(); // Select a new, valid cloud destination. - page.destinationStore_.selectDestination(validPrinter); + destinationSettings.destinationStore_.selectDestination( + validPrinter); + return nativeLayer.whenCalled('getPreview'); }) .then(function() { @@ -329,12 +329,15 @@ const messageEl = previewAreaEl.$$('.preview-area-message'); const header = page.$$('print-preview-header'); const printButton = header.$$('.action-button'); + const destinationSettings = + page.$$('print-preview-destination-settings'); return nativeLayer.whenCalled('getInitialSettings') .then(function() { // Start loading cloud destinations so that the printer // capabilities arrive. - page.destinationStore_.startLoadCloudDestinations(); + destinationSettings.destinationStore_ + .startLoadCloudDestinations(); return nativeLayer.whenCalled('getPreview'); }) .then(function() { @@ -345,10 +348,10 @@ // Select the invalid destination and wait for the event. const whenInvalid = test_util.eventToPromise( - print_preview.DestinationStore.EventType - .SELECTED_DESTINATION_UNSUPPORTED, - page.destinationStore_); - page.destinationStore_.selectDestination(invalidPrinter); + print_preview.DestinationStore.EventType.ERROR, + destinationSettings.destinationStore_); + destinationSettings.destinationStore_.selectDestination( + invalidPrinter); return whenInvalid; }) .then(function() { @@ -361,8 +364,9 @@ // Reselect the valid cloud destination. const whenSelected = test_util.eventToPromise( print_preview.DestinationStore.EventType.DESTINATION_SELECT, - page.destinationStore_); - page.destinationStore_.selectDestination(validPrinter); + destinationSettings.destinationStore_); + destinationSettings.destinationStore_.selectDestination( + validPrinter); return whenSelected; }) .then(function() {
diff --git a/chrome/test/data/webui/print_preview/model_test.js b/chrome/test/data/webui/print_preview/model_test.js index f9a2091..6efc19c7 100644 --- a/chrome/test/data/webui/print_preview/model_test.js +++ b/chrome/test/data/webui/print_preview/model_test.js
@@ -9,7 +9,6 @@ SetPolicySettings: 'set policy settings', GetPrintTicket: 'get print ticket', GetCloudPrintTicket: 'get cloud print ticket', - UpdateRecentDestinations: 'update recent destinations', ChangeDestination: 'change destination' }; @@ -383,55 +382,6 @@ expectEquals(expectedNewTicket, newTicket); }); - /** - * @param {!Array<string>} expectedDestinationIds An array of the expected - * recent destination ids. - */ - function assertRecentDestinations(expectedDestinationIds) { - assertEquals( - expectedDestinationIds.length, model.recentDestinations.length); - expectedDestinationIds.forEach((expectedId, index) => { - assertEquals(expectedId, model.recentDestinations[index].id); - }); - } - - /** - * Tests that the destination being set correctly updates the recent - * destinations array. - */ - test(assert(TestNames.UpdateRecentDestinations), function() { - initializeModel(); - model.applyStickySettings(); - - let localDestinations = []; - let destinations = - print_preview_test_utils.getDestinations(null, localDestinations); - - // Recent destinations start out empty. - assertRecentDestinations([]); - - // Simulate setting a destination. - model.destination = destinations[0]; - assertRecentDestinations(['ID1']); - - // Set a new destination - model.destination = destinations[1]; - assertRecentDestinations(['ID2', 'ID1']); - - // Reselect a recent destination. Still 2 destinations, but in a - // different order. - model.destination = destinations[0]; - assertRecentDestinations(['ID1', 'ID2']); - - // Select a third destination - model.destination = destinations[2]; - assertRecentDestinations(['ID3', 'ID1', 'ID2']); - - // Select a fourth destination. List does not grow. - model.destination = destinations[3]; - assertRecentDestinations(['ID4', 'ID3', 'ID1']); - }); - test(assert(TestNames.ChangeDestination), function() { const testDestination = new print_preview.Destination( 'FooDevice', print_preview.DestinationType.LOCAL,
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index 03508b3b..dbd57b9 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -291,10 +291,6 @@ this.runMochaTest(model_test.TestNames.GetCloudPrintTicket); }); -TEST_F('PrintPreviewModelTest', 'UpdateRecentDestinations', function() { - this.runMochaTest(model_test.TestNames.UpdateRecentDestinations); -}); - TEST_F('PrintPreviewModelTest', 'ChangeDestination', function() { this.runMochaTest(model_test.TestNames.ChangeDestination); }); @@ -566,7 +562,7 @@ PrintPreviewDestinationSelectTest = class extends NewPrintPreviewTest { /** @override */ get browsePreload() { - return 'chrome://print/new/app.html'; + return 'chrome://print/new/destination_settings.html'; } /** @override */ @@ -1206,6 +1202,13 @@ destination_settings_test.TestNames.TwoAccountsRecentDestinations); }); +TEST_F( + 'PrintPreviewDestinationSettingsTest', 'UpdateRecentDestinations', + function() { + this.runMochaTest( + destination_settings_test.TestNames.UpdateRecentDestinations); + }); + PrintPreviewScalingSettingsTest = class extends NewPrintPreviewTest { /** @override */ get browsePreload() {
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.js b/chrome/test/data/webui/print_preview/preview_generation_test.js index 9e75bad5..157e686c 100644 --- a/chrome/test/data/webui/print_preview/preview_generation_test.js +++ b/chrome/test/data/webui/print_preview/preview_generation_test.js
@@ -360,6 +360,8 @@ .capabilities; nativeLayer.resetResolver('getPreview'); page.set('destination_', barDestination); + page.destinationState_ = print_preview.DestinationState.SELECTED; + page.destinationState_ = print_preview.DestinationState.UPDATED; return nativeLayer.whenCalled('getPreview'); }) .then(function(args) {
diff --git a/chrome/test/data/webui/print_preview/print_button_test.js b/chrome/test/data/webui/print_preview/print_button_test.js index f8cc50c0..e418ae6 100644 --- a/chrome/test/data/webui/print_preview/print_button_test.js +++ b/chrome/test/data/webui/print_preview/print_button_test.js
@@ -74,7 +74,6 @@ function waitForInitialPreview() { return nativeLayer.whenCalled('getInitialSettings') .then(function() { - page.destinationStore_.startLoadAllDestinations(); // Wait for the preview request. return Promise.all([ nativeLayer.whenCalled('getPrinterCapabilities'), @@ -105,30 +104,30 @@ test(assert(TestNames.PDFPrintVisiblePreview), function() { printBeforePreviewReady = false; - return waitForInitialPreview().then(function() { - // Setup to print before the preview loads. - printBeforePreviewReady = true; + return waitForInitialPreview() + .then(function() { + nativeLayer.reset(); + // Setup to print before the preview loads. + printBeforePreviewReady = true; - // Select Save as PDF destination - const pdfDestination = page.destinationStore_.destinations().find( - d => d.id == 'Save as PDF'); - assertTrue(!!pdfDestination); - page.destinationStore_.selectDestination(pdfDestination); + // Select Save as PDF destination + const pdfDestination = page.$$('print-preview-destination-settings') + .destinationStore_.destinations() + .find(d => d.id == 'Save as PDF'); + assertTrue(!!pdfDestination); + page.$$('print-preview-destination-settings') + .destinationStore_.selectDestination(pdfDestination); - // Reload preview and wait for print. - return Promise.all([ - nativeLayer.whenCalled('getPrinterCapabilities'), - nativeLayer.whenCalled('getPreview'), - nativeLayer.whenCalled('print') - ]); - }).then(function(args) { - assertFalse(previewHidden); + // Reload preview and wait for print. + return nativeLayer.whenCalled('print'); + }) + .then(function(printTicket) { + assertFalse(previewHidden); - const printTicket = args[2]; - // Verify that the printer name is correct. - assertEquals('Save as PDF', JSON.parse(printTicket).deviceName); - return nativeLayer.whenCalled('dialogClose'); - }); + // Verify that the printer name is correct. + assertEquals('Save as PDF', JSON.parse(printTicket).deviceName); + return nativeLayer.whenCalled('dialogClose'); + }); }); });
diff --git a/chrome/test/data/webui/print_preview/print_preview_app_test.js b/chrome/test/data/webui/print_preview/print_preview_app_test.js index d7bddbf..0aee7b7 100644 --- a/chrome/test/data/webui/print_preview/print_preview_app_test.js +++ b/chrome/test/data/webui/print_preview/print_preview_app_test.js
@@ -40,34 +40,18 @@ serializedDefaultDestinationSelectionRulesStr: null }; - let localDestinations = []; - let cloudDestinations = []; - /** @override */ setup(function() { // Stub out the native layer, the cloud print interface, and the plugin. nativeLayer = new print_preview.NativeLayerStub(); print_preview.NativeLayer.setInstance(nativeLayer); + nativeLayer.setInitialSettings(initialSettings); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate(initialSettings.printerName)); cloudPrintInterface = new print_preview.CloudPrintInterfaceStub(); cloudprint.setCloudPrintInterfaceForTesting(cloudPrintInterface); pluginProxy = new print_preview.PDFPluginStub(); print_preview_new.PluginProxy.setInstance(pluginProxy); - }); - - /** - * Initializes the native layer and cloud print interface based on - * |initialSettings|, |localDestinations|, and |cloudDestinations|, and - * creates the page. - * @return {!Promise} Promise that resolves when the selected printer is - * loaded. - */ - function finishSetup() { - nativeLayer.setInitialSettings(initialSettings); - nativeLayer.setLocalDestinations(localDestinations); - nativeLayer.setLocalDestinationCapabilities( - print_preview_test_utils.getCddTemplate(initialSettings.printerName)); - cloudDestinations.forEach( - destination => cloudPrintInterface.setPrinter(destination)); PolymerTest.clearBody(); page = document.createElement('print-preview-app'); @@ -75,35 +59,23 @@ const previewArea = page.$.previewArea; pluginProxy.setLoadCallback(previewArea.onPluginLoad_.bind(previewArea)); cr.webUIListenerCallback('use-cloud-print', 'cloudprint url', false); - - return test_util.eventToPromise( - print_preview.DestinationStore.EventType - .SELECTED_DESTINATION_CAPABILITIES_READY, - page.destinationStore_); - } + return nativeLayer.whenCalled('getInitialSettings').then(() => { + page.destination_ = new print_preview.Destination( + 'FooDevice', print_preview.DestinationType.LOCAL, + print_preview.DestinationOrigin.LOCAL, 'FooName', + print_preview.DestinationConnectionStatus.ONLINE); + page.destination_.capabilities = + print_preview_test_utils.getCddTemplate('FooDevice').capabilities; + }); + }); // Regression test for https://crbug.com/936029 test(assert(TestNames.PrintToGoogleDrive), async () => { - // Set up the UI to have Google Drive as the most recent printer. - const account = 'foo@chromium.org'; - const drivePrinter = - print_preview_test_utils.getGoogleDriveDestination(account); - const recentDestinations = [ - print_preview.makeRecentDestination(drivePrinter), - ]; - cloudDestinations = [drivePrinter]; - initialSettings.serializedAppStateStr = JSON.stringify({ - version: 2, - recentDestinations: recentDestinations, - }); - - await finishSetup(); - - // Should have loaded Google Drive as the selected printer, since it - // was most recent. - assertEquals( - print_preview.Destination.GooglePromotedId.DOCS, - page.destination_.id); + // Set up the UI to have Google Drive as the printer. + page.destination_ = print_preview_test_utils.getGoogleDriveDestination( + 'foo@chromium.org'); + page.destination_.capabilities = + print_preview_test_utils.getCddTemplate(page.destination_.id); // Trigger print. const header = page.$$('print-preview-header'); @@ -119,8 +91,7 @@ assertEquals('1.0', JSON.parse(args.printTicket).version); }); - test(assert(TestNames.SettingsSectionsVisibilityChange), async () => { - await finishSetup(); + test(assert(TestNames.SettingsSectionsVisibilityChange), function() { const moreSettingsElement = page.$$('print-preview-more-settings'); moreSettingsElement.$.label.click(); const camelToKebab = s => s.replace(/([A-Z])/g, '-$1').toLowerCase(); @@ -138,9 +109,7 @@ }); }); - test(assert(TestNames.PrintPresets), async () => { - await finishSetup(); - + test(assert(TestNames.PrintPresets), function() { assertEquals(1, page.settings.copies.value); page.setSetting('duplex', false); assertFalse(page.settings.duplex.value);
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 4e6a6d6..31e79e3 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -568,9 +568,9 @@ # A meta-target which repacks resources by locale. group("chromecast_locales_pak") { - deps = [] + data_deps = [] foreach(locale, cast_locales) { - deps += [ ":_cast_repack_${locale}" ] + data_deps += [ ":_cast_repack_${locale}" ] } }
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java index 21d6f251..b8d94f9 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -13,6 +13,7 @@ import android.media.AudioTrack; import android.os.Build; import android.os.SystemClock; +import android.support.annotation.IntDef; import android.util.SparseIntArray; import org.chromium.base.ContextUtils; @@ -21,6 +22,8 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.chromecast.media.AudioContentType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -134,19 +137,25 @@ private ThrottledLog mUnderrunWarningLog; private ThrottledLog mTStampJitterWarningLog; - private enum ReferenceTimestampState { - STARTING_UP, // Starting up, no valid reference time yet. - STABLE, // Reference time exists and is updated regularly. - RESYNCING_AFTER_PAUSE, // Sync the timestamp after pause so that the renderer delay will be - // correct. - RESYNCING_AFTER_UNDERRUN, // The AudioTrack hit an underrun and we need to find a new - // reference timestamp after the underrun point. - RESYNCING_AFTER_EXCESSIVE_TIMESTAMP_DRIFT, // We experienced excessive and consistent - // jitters in the timestamps and we should find a - // new reference timestamp. + @IntDef({ReferenceTimestampState.STARTING_UP, ReferenceTimestampState.STABLE, + ReferenceTimestampState.RESYNCING_AFTER_PAUSE, + ReferenceTimestampState.RESYNCING_AFTER_UNDERRUN, + ReferenceTimestampState.RESYNCING_AFTER_EXCESSIVE_TIMESTAMP_DRIFT}) + @Retention(RetentionPolicy.SOURCE) + private @interface ReferenceTimestampState { + int STARTING_UP = 0; // Starting up, no valid reference time yet. + int STABLE = 1; // Reference time exists and is updated regularly. + int RESYNCING_AFTER_PAUSE = 2; // Sync the timestamp after pause so that the renderer delay + // will be correct. + int RESYNCING_AFTER_UNDERRUN = 3; // The AudioTrack hit an underrun and we need to find a + // new reference timestamp after the underrun point. + int RESYNCING_AFTER_EXCESSIVE_TIMESTAMP_DRIFT = + 4; // We experienced excessive and consistent + // jitters in the timestamps and we should find a + // new reference timestamp. } - ReferenceTimestampState mReferenceTimestampState; + private @ReferenceTimestampState int mReferenceTimestampState; private boolean mIsInitialized; @@ -630,7 +639,7 @@ } } - private void resyncTimestamp(ReferenceTimestampState reason) { + private void resyncTimestamp(@ReferenceTimestampState int reason) { mLastTimestampUpdateNsec = NO_TIMESTAMP; mTimestampStabilityCounter = 0; mReferenceTimestampState = reason; @@ -687,7 +696,7 @@ long prevRefNanoTimeAtFramePos0 = mRefNanoTimeAtFramePos0; switch (mReferenceTimestampState) { - case STARTING_UP: + case ReferenceTimestampState.STARTING_UP: // The Audiotrack produces a few timestamps at the beginning of time that are widely // inaccurate. Hence, we require several stable timestamps before setting a // reference point. @@ -701,11 +710,11 @@ "First stable timestamp [" + mTimestampStabilityCounter + "/" + elapsedNsec(mTimestampStabilityStartTimeNsec) / 1000000 + "ms]"); break; - case RESYNCING_AFTER_PAUSE: + case ReferenceTimestampState.RESYNCING_AFTER_PAUSE: // fall-through - case RESYNCING_AFTER_EXCESSIVE_TIMESTAMP_DRIFT: + case ReferenceTimestampState.RESYNCING_AFTER_EXCESSIVE_TIMESTAMP_DRIFT: // fall-through - case RESYNCING_AFTER_UNDERRUN: + case ReferenceTimestampState.RESYNCING_AFTER_UNDERRUN: // Resyncing happens after we hit a pause, underrun or excessive drift in the // AudioTrack. This causes the Android Audio stack to insert additional samples, // which increases the reference timestamp (at framePosition=0) by thousands of @@ -730,7 +739,7 @@ + elapsedNsec(mTimestampStabilityStartTimeNsec) / 1000000 + "ms]"); break; - case STABLE: + case ReferenceTimestampState.STABLE: // Timestamps can be jittery, and on some systems they are occasionally off by // hundreds of usecs. Filter out timestamps that are too jittery and use a low-pass // filter on the smaller ones.
diff --git a/chromecast/media/cma/backend/audio_decoder_software_wrapper_unittest.cc b/chromecast/media/cma/backend/audio_decoder_software_wrapper_unittest.cc index 09cbde4..7441d86 100644 --- a/chromecast/media/cma/backend/audio_decoder_software_wrapper_unittest.cc +++ b/chromecast/media/cma/backend/audio_decoder_software_wrapper_unittest.cc
@@ -46,6 +46,7 @@ TEST_F(AudioDecoderSoftwareWrapperTest, IsUsingSoftwareDecoder) { AudioConfig audio_config; + audio_config.channel_layout = ChannelLayout::STEREO; audio_config.sample_format = kSampleFormatS16; audio_config.bytes_per_channel = 2; audio_config.channel_number = 2;
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc index 517e348..04f7dfc 100644 --- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc +++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -72,6 +72,7 @@ AudioConfig DefaultAudioConfig() { AudioConfig default_config; default_config.codec = kCodecPCM; + default_config.channel_layout = ChannelLayout::STEREO; default_config.sample_format = kSampleFormatS16; default_config.channel_number = 2; default_config.bytes_per_channel = 2; @@ -466,6 +467,7 @@ AudioConfig config; // First, make sure that kAudioCodecUnknown is not accepted. config.codec = kAudioCodecUnknown; + config.channel_layout = ChannelLayout::STEREO; config.sample_format = kSampleFormatS16; config.channel_number = 2; config.bytes_per_channel = 2;
diff --git a/chromecast/media/cma/backend/multizone_backend_unittest.cc b/chromecast/media/cma/backend/multizone_backend_unittest.cc index 43ce10f..fc18fa7 100644 --- a/chromecast/media/cma/backend/multizone_backend_unittest.cc +++ b/chromecast/media/cma/backend/multizone_backend_unittest.cc
@@ -318,6 +318,7 @@ int playback_rate_change_count) { AudioConfig config; config.codec = kCodecPCM; + config.channel_layout = ChannelLayout::STEREO; config.sample_format = kSampleFormatPlanarF32; config.channel_number = 2; config.bytes_per_channel = 4; @@ -334,6 +335,7 @@ void MultizoneBackendTest::AddEffectsStreams() { AudioConfig effects_config; effects_config.codec = kCodecPCM; + effects_config.channel_layout = ChannelLayout::STEREO; effects_config.sample_format = kSampleFormatS16; effects_config.channel_number = 2; effects_config.bytes_per_channel = 2;
diff --git a/chromecast/media/cma/base/decoder_config_adapter.cc b/chromecast/media/cma/base/decoder_config_adapter.cc index 933704f..9075813c 100644 --- a/chromecast/media/cma/base/decoder_config_adapter.cc +++ b/chromecast/media/cma/base/decoder_config_adapter.cc
@@ -46,6 +46,25 @@ return kAudioCodecUnknown; } +ChannelLayout ToChannelLayout(const ::media::ChannelLayout channel_layout) { + switch (channel_layout) { + case ::media::ChannelLayout::CHANNEL_LAYOUT_UNSUPPORTED: + return ChannelLayout::UNSUPPORTED; + case ::media::ChannelLayout::CHANNEL_LAYOUT_MONO: + return ChannelLayout::MONO; + case ::media::ChannelLayout::CHANNEL_LAYOUT_STEREO: + return ChannelLayout::STEREO; + case ::media::ChannelLayout::CHANNEL_LAYOUT_5_1: + return ChannelLayout::SURROUND_5_1; + case ::media::ChannelLayout::CHANNEL_LAYOUT_BITSTREAM: + return ChannelLayout::BITSTREAM; + + default: + NOTREACHED(); + return ChannelLayout::UNSUPPORTED; + } +} + SampleFormat ToSampleFormat(const ::media::SampleFormat sample_format) { switch (sample_format) { case ::media::kUnknownSampleFormat: @@ -74,15 +93,22 @@ return kUnknownSampleFormat; } -::media::ChannelLayout ToMediaChannelLayout(int channel_number) { - switch (channel_number) { - case 1: +::media::ChannelLayout ToMediaChannelLayout( + const ChannelLayout channel_layout) { + switch (channel_layout) { + case ChannelLayout::UNSUPPORTED: + return ::media::ChannelLayout::CHANNEL_LAYOUT_UNSUPPORTED; + case ChannelLayout::MONO: return ::media::ChannelLayout::CHANNEL_LAYOUT_MONO; - case 2: + case ChannelLayout::STEREO: return ::media::ChannelLayout::CHANNEL_LAYOUT_STEREO; - case 6: + case ChannelLayout::SURROUND_5_1: return ::media::ChannelLayout::CHANNEL_LAYOUT_5_1; + case ChannelLayout::BITSTREAM: + return ::media::ChannelLayout::CHANNEL_LAYOUT_BITSTREAM; + default: + NOTREACHED(); return ::media::ChannelLayout::CHANNEL_LAYOUT_UNSUPPORTED; } } @@ -192,12 +218,13 @@ audio_config.codec = ToAudioCodec(config.codec()); audio_config.sample_format = ToSampleFormat(config.sample_format()); audio_config.bytes_per_channel = config.bytes_per_channel(); + audio_config.channel_layout = ToChannelLayout(config.channel_layout()); audio_config.channel_number = ::media::ChannelLayoutToChannelCount(config.channel_layout()), audio_config.samples_per_second = config.samples_per_second(); audio_config.extra_data = config.extra_data(); - audio_config.encryption_scheme = ToEncryptionScheme( - config.encryption_scheme()); + audio_config.encryption_scheme = + ToEncryptionScheme(config.encryption_scheme()); #if defined(OS_ANDROID) // On Android, Chromium's mp4 parser adds extra data for AAC, but we don't @@ -215,9 +242,8 @@ return ::media::AudioDecoderConfig( ToMediaAudioCodec(config.codec), ToMediaSampleFormat(config.sample_format), - ToMediaChannelLayout(config.channel_number), config.samples_per_second, - config.extra_data, - ToMediaEncryptionScheme(config.encryption_scheme)); + ToMediaChannelLayout(config.channel_layout), config.samples_per_second, + config.extra_data, ToMediaEncryptionScheme(config.encryption_scheme)); } // static
diff --git a/chromecast/public/media/decoder_config.h b/chromecast/public/media/decoder_config.h index 4dc0acf..a81a9a22 100644 --- a/chromecast/public/media/decoder_config.h +++ b/chromecast/public/media/decoder_config.h
@@ -20,6 +20,7 @@ // Maximum audio sampling rate. static const int kMaxSampleRate = 192000; +// TODO(guohuideng): change at least AudioCodec and SampleFormat to enum class. enum AudioCodec : int { kAudioCodecUnknown = 0, kCodecAAC, @@ -38,6 +39,41 @@ kAudioCodecMax = kCodecMpegHAudio, }; +enum class ChannelLayout { + UNSUPPORTED, + + // Front C + MONO, + + // Front L, Front R + STEREO, + + // Front L, Front R, Front C, LFE, Side L, Side R + SURROUND_5_1, + + // Actual channel layout is specified in the bitstream and the actual channel + // count is unknown at Chromium media pipeline level (useful for audio + // pass-through mode). + BITSTREAM, + + // Max value, must always equal the largest entry ever logged. + MAX_LAST = BITSTREAM, +}; + +// Internal chromecast apps use this to decide on channel_layout. +inline ChannelLayout ChannelLayoutFromChannelNumber(int channel_number) { + switch (channel_number) { + case 1: + return ChannelLayout::MONO; + case 2: + return ChannelLayout::STEREO; + case 6: + return ChannelLayout::SURROUND_5_1; + default: + return ChannelLayout::UNSUPPORTED; + } +} + enum SampleFormat : int { kUnknownSampleFormat = 0, kSampleFormatU8, // Unsigned 8-bit w/ bias of 128. @@ -238,6 +274,8 @@ StreamId id; // Audio codec. AudioCodec codec; + // Audio channel layout. + ChannelLayout channel_layout; // The format of each audio sample. SampleFormat sample_format; // Number of bytes in each channel. @@ -255,6 +293,7 @@ inline AudioConfig::AudioConfig() : id(kPrimary), codec(kAudioCodecUnknown), + channel_layout(ChannelLayout::UNSUPPORTED), sample_format(kUnknownSampleFormat), bytes_per_channel(0), channel_number(0), @@ -313,19 +352,15 @@ inline VideoConfig::~VideoConfig() { } -// TODO(erickung): Remove following two inline IsValidConfig() functions. These -// are to keep existing CMA backend implementation consistent until the clean up -// is done. These SHOULD NOT be used in New CMA backend implementation. inline bool IsValidConfig(const AudioConfig& config) { return config.codec >= kAudioCodecMin && config.codec <= kAudioCodecMax && config.codec != kAudioCodecUnknown && + config.channel_layout != ChannelLayout::UNSUPPORTED && config.sample_format >= kSampleFormatMin && config.sample_format <= kSampleFormatMax && config.sample_format != kUnknownSampleFormat && - // TODO(servolk): Add channel_layout field to the AudioConfig in the - // next Cast system update and change this condition to - // (channel_number > 0 || channel_layout == CHANNEL_LAYOUT_BITSTREAM) - (config.channel_number > 0 || config.codec == kCodecMpegHAudio) && + (config.channel_number > 0 || + config.channel_layout == ChannelLayout::BITSTREAM) && config.bytes_per_channel > 0 && config.bytes_per_channel <= kMaxBytesPerSample && config.samples_per_second > 0 &&
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index a545aee0..626546ac 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -63,6 +63,7 @@ constexpr char kScreenBrightnessDeviceSettingId[] = "BRIGHTNESS_LEVEL"; constexpr char kDoNotDisturbDeviceSettingId[] = "DO_NOT_DISTURB"; constexpr char kNightLightDeviceSettingId[] = "NIGHT_LIGHT_SWITCH"; +constexpr char kIntentActionView[] = "android.intent.action.VIEW"; constexpr base::Feature kChromeOSAssistantDogfood{ "ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -206,9 +207,16 @@ // Register handler for media actions. assistant_manager_internal_->RegisterFallbackMediaHandler( [this](std::string play_media_args_proto) { - std::string url = GetWebUrlFromMediaArgs(play_media_args_proto); - if (!url.empty()) { - OnOpenUrl(url); + std::unique_ptr<action::AndroidAppInfo> android_app_info = + GetAndroidAppInfoFromMediaArgs(play_media_args_proto); + if (android_app_info) { + OnOpenMediaAndroidIntent(play_media_args_proto, + android_app_info.get()); + } else { + std::string url = GetWebUrlFromMediaArgs(play_media_args_proto); + // Fallack to web URL. + if (!url.empty()) + OnOpenUrl(url); } }); } @@ -517,7 +525,7 @@ const std::vector<action::AndroidAppInfo>& apps_info, const action::InteractionInfo& interaction) { std::vector<mojom::AndroidAppInfoPtr> apps_info_list; - for (auto app_info : apps_info) { + for (auto& app_info : apps_info) { mojom::AndroidAppInfoPtr app_info_ptr = mojom::AndroidAppInfo::New(); app_info_ptr->package_name = app_info.package_name; apps_info_list.push_back(std::move(app_info_ptr)); @@ -529,6 +537,31 @@ weak_factory_.GetWeakPtr(), interaction)); } +void AssistantManagerServiceImpl::OnOpenMediaAndroidIntent( + const std::string play_media_args_proto, + action::AndroidAppInfo* android_app_info) { + ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnOpenMediaAndroidIntent, + play_media_args_proto, android_app_info); + + // Handle android media playback intent. + mojom::AndroidAppInfoPtr app_info_ptr = mojom::AndroidAppInfo::New(); + app_info_ptr->package_name = android_app_info->package_name; + app_info_ptr->action = kIntentActionView; + if (!android_app_info->intent.empty()) { + app_info_ptr->intent = android_app_info->intent; + } else { + std::string url = GetAndroidIntentUrlFromMediaArgs(play_media_args_proto); + if (!url.empty()) { + app_info_ptr->intent = url; + } + } + service_->device_actions()->OpenAndroidApp( + std::move(app_info_ptr), + base::BindOnce( + &AssistantManagerServiceImpl::HandleLaunchMediaIntentResponse, + weak_factory_.GetWeakPtr())); +} + void AssistantManagerServiceImpl::OnRecognitionStateChanged( assistant_client::ConversationStateListener::RecognitionState state, const assistant_client::ConversationStateListener::RecognitionResult& @@ -830,6 +863,12 @@ assistant_settings_manager_->SyncSpeakerIdEnrollmentStatus(); } +void AssistantManagerServiceImpl::HandleLaunchMediaIntentResponse( + bool app_opened) { + // TODO(llin): Handle the response. + NOTIMPLEMENTED(); +} + void AssistantManagerServiceImpl::HandleOpenAndroidAppResponse( const action::InteractionInfo& interaction, bool app_opened) {
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index b4f4a36d..3576fcc 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -196,6 +196,8 @@ const action::InteractionInfo& interaction, std::vector<mojom::AndroidAppInfoPtr> apps_info); + void HandleLaunchMediaIntentResponse(bool app_opened); + void OnConversationTurnStartedOnMainThread(bool is_mic_open); void OnConversationTurnFinishedOnMainThread( assistant_client::ConversationStateListener::Resolution resolution); @@ -216,6 +218,8 @@ void OnRespondingStartedOnMainThread(bool is_error_response); void OnSpeechLevelUpdatedOnMainThread(const float speech_level); void OnModifySettingsAction(const std::string& modify_setting_args_proto); + void OnOpenMediaAndroidIntent(const std::string play_media_args_proto, + action::AndroidAppInfo* android_app_info); void RegisterFallbackMediaHandler();
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc index 88f10e5..0997623e 100644 --- a/chromeos/services/assistant/platform/audio_input_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "base/timer/timer.h" #include "chromeos/services/assistant/public/features.h" +#include "chromeos/services/assistant/utils.h" #include "libassistant/shared/public/platform_audio_buffer.h" #include "media/audio/audio_device_description.h" #include "media/base/audio_parameters.h" @@ -23,11 +24,11 @@ namespace { constexpr assistant_client::BufferFormat kFormatMono{ - 16000 /* sample_rate */, assistant_client::INTERLEAVED_S32, 1 /* channels */ + 16000 /* sample_rate */, assistant_client::INTERLEAVED_S16, 1 /* channels */ }; constexpr assistant_client::BufferFormat kFormatStereo{ - 16000 /* sample_rate */, assistant_client::INTERLEAVED_S32, 2 /* channels */ + 44100 /* sample_rate */, assistant_client::INTERLEAVED_S16, 2 /* channels */ }; assistant_client::BufferFormat g_current_format = kFormatMono; @@ -193,12 +194,12 @@ state_manager_->OnCaptureDataArrived(); - std::vector<int32_t> buffer(audio_source->channels() * + std::vector<int16_t> buffer(audio_source->channels() * audio_source->frames()); - audio_source->ToInterleaved<media::SignedInt32SampleTypeTraits>( + audio_source->ToInterleaved<media::SignedInt16SampleTypeTraits>( audio_source->frames(), buffer.data()); - int64_t time = base::TimeTicks::Now().since_origin().InMilliseconds() - - audio_delay_milliseconds; + int64_t time = base::TimeTicks::Now().since_origin().InMicroseconds() - + 1000 * audio_delay_milliseconds; AudioInputBufferImpl input_buffer(buffer.data(), audio_source->frames()); { base::AutoLock lock(lock_); @@ -211,7 +212,7 @@ auto now = base::TimeTicks::Now(); if ((now - last_frame_count_report_time_) > base::TimeDelta::FromMinutes(2)) { - VLOG(1) << "Captured frames: " << captured_frames_count_; + VLOG(1) << device_id_ << " captured frames: " << captured_frames_count_; last_frame_count_report_time_ = now; } } @@ -219,7 +220,7 @@ // Runs on audio service thread. void AudioInputImpl::OnCaptureError(const std::string& message) { - LOG(ERROR) << "Capture error " << message; + LOG(ERROR) << device_id_ << " capture error " << message; base::AutoLock lock(lock_); for (auto* observer : observers_) observer->OnAudioError(AudioInput::Error::FATAL_ERROR); @@ -237,7 +238,7 @@ void AudioInputImpl::AddObserver( assistant_client::AudioInput::Observer* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(observer_sequence_checker_); - VLOG(1) << "Add observer"; + VLOG(1) << device_id_ << " add observer"; bool have_first_observer = false; { base::AutoLock lock(lock_); @@ -259,7 +260,7 @@ void AudioInputImpl::RemoveObserver( assistant_client::AudioInput::Observer* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(observer_sequence_checker_); - VLOG(1) << "Remove observer"; + VLOG(1) << device_id_ << " remove observer"; bool have_no_observer = false; { base::AutoLock lock(lock_); @@ -345,7 +346,7 @@ source_->Initialize(param, this); source_->Start(); - VLOG(1) << "Start recording"; + VLOG(1) << device_id_ << " start recording"; } bool AudioInputImpl::IsHotwordAvailable() { @@ -361,10 +362,11 @@ void AudioInputImpl::StopRecording() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (source_) { - VLOG(1) << "Stop recording"; + VLOG(1) << device_id_ << " stop recording"; source_->Stop(); source_.reset(); - VLOG(1) << "Ending captured frames: " << captured_frames_count_; + VLOG(1) << device_id_ + << " ending captured frames: " << captured_frames_count_; } }
diff --git a/chromeos/services/assistant/platform/audio_input_impl.h b/chromeos/services/assistant/platform/audio_input_impl.h index ed70da3..fc46811 100644 --- a/chromeos/services/assistant/platform/audio_input_impl.h +++ b/chromeos/services/assistant/platform/audio_input_impl.h
@@ -91,7 +91,7 @@ scoped_refptr<media::AudioCapturerSource> source_; // Should audio input always recording actively. - bool default_on_ = false; + bool default_on_ = true; // User explicitly requested to open microphone. bool mic_open_ = false;
diff --git a/chromeos/services/assistant/platform/audio_input_provider_impl.cc b/chromeos/services/assistant/platform/audio_input_provider_impl.cc index 3c70135f..bf4b8c2 100644 --- a/chromeos/services/assistant/platform/audio_input_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_provider_impl.cc
@@ -4,6 +4,8 @@ #include "chromeos/services/assistant/platform/audio_input_provider_impl.h" +#include "chromeos/services/assistant/public/features.h" + namespace chromeos { namespace assistant { @@ -20,7 +22,9 @@ } int64_t AudioInputProviderImpl::GetCurrentAudioTime() { - // TODO(xiaohuic): see if we can support real timestamp. + if (features::IsAudioEraserEnabled()) + return base::TimeTicks::Now().since_origin().InMicroseconds(); + return 0; }
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.cc b/chromeos/services/assistant/platform/audio_output_provider_impl.cc index 5fae1867..6e53cd54 100644 --- a/chromeos/services/assistant/platform/audio_output_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
@@ -14,6 +14,7 @@ #include "chromeos/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" #include "chromeos/services/assistant/public/mojom/constants.mojom.h" #include "libassistant/shared/public/platform_audio_buffer.h" +#include "media/audio/audio_device_description.h" #include "services/service_manager/public/cpp/connector.h" namespace chromeos { @@ -123,7 +124,10 @@ AssistantMediaSession* media_session, scoped_refptr<base::SequencedTaskRunner> background_task_runner, const std::string& device_id) - : volume_control_impl_(connector, media_session), + : loop_back_input_(connector, + media::AudioDeviceDescription::kLoopbackInputDeviceId, + /*hotword_device_id=*/std::string()), + volume_control_impl_(connector, media_session), connector_(connector), main_task_runner_(base::SequencedTaskRunnerHandle::Get()), background_task_runner_(background_task_runner), @@ -157,8 +161,7 @@ } assistant_client::AudioInput* AudioOutputProviderImpl::GetReferenceInput() { - // TODO(muyuanli): implement. - return nullptr; + return &loop_back_input_; } bool AudioOutputProviderImpl::SupportsPlaybackTimestamp() const {
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.h b/chromeos/services/assistant/platform/audio_output_provider_impl.h index 287e44b..a68f9f5 100644 --- a/chromeos/services/assistant/platform/audio_output_provider_impl.h +++ b/chromeos/services/assistant/platform/audio_output_provider_impl.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "chromeos/services/assistant/platform/audio_device_owner.h" +#include "chromeos/services/assistant/platform/audio_input_impl.h" #include "chromeos/services/assistant/platform/volume_control_impl.h" #include "chromeos/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" #include "libassistant/shared/public/platform_audio_output.h" @@ -54,6 +55,7 @@ AudioEmittingStateCallback callback) override; private: + AudioInputImpl loop_back_input_; VolumeControlImpl volume_control_impl_; service_manager::Connector* connector_; scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
diff --git a/chromeos/services/assistant/public/features.cc b/chromeos/services/assistant/public/features.cc index 1dde5ad..b48fb73 100644 --- a/chromeos/services/assistant/public/features.cc +++ b/chromeos/services/assistant/public/features.cc
@@ -10,6 +10,9 @@ namespace assistant { namespace features { +const base::Feature kAssistantAudioEraser{"AssistantAudioEraser", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kAssistantFeedbackUi{"AssistantFeedbackUi", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -64,6 +67,10 @@ assistant::features::kAssistantAppSupport); } +bool IsAudioEraserEnabled() { + return base::FeatureList::IsEnabled(kAssistantAudioEraser); +} + bool IsClearCutLogEnabled() { return base::FeatureList::IsEnabled(kEnableClearCutLog); } @@ -80,12 +87,26 @@ return base::FeatureList::IsEnabled(kInAssistantNotifications); } +bool IsKeyRemappingEnabled() { + return base::FeatureList::IsEnabled(kAssistantKeyRemapping); +} + +bool IsPowerManagerEnabled() { + return base::FeatureList::IsEnabled(kEnablePowerManager); +} + bool IsRoutinesEnabled() { return base::FeatureList::IsEnabled(kAssistantRoutines); } +bool IsScreenContextQueryEnabled() { + return base::FeatureList::IsEnabled(kScreenContextQuery); +} + bool IsStereoAudioInputEnabled() { - return base::FeatureList::IsEnabled(kEnableStereoAudioInput); + return base::FeatureList::IsEnabled(kEnableStereoAudioInput) || + // Audio eraser requires 2 channel input. + base::FeatureList::IsEnabled(kAssistantAudioEraser); } bool IsTimerNotificationEnabled() { @@ -100,18 +121,6 @@ return base::FeatureList::IsEnabled(kAssistantWarmerWelcomeFeature); } -bool IsPowerManagerEnabled() { - return base::FeatureList::IsEnabled(kEnablePowerManager); -} - -bool IsKeyRemappingEnabled() { - return base::FeatureList::IsEnabled(kAssistantKeyRemapping); -} - -bool IsScreenContextQueryEnabled() { - return base::FeatureList::IsEnabled(kScreenContextQuery); -} - } // namespace features } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/public/features.h b/chromeos/services/assistant/public/features.h index f9fdada..abd109c 100644 --- a/chromeos/services/assistant/public/features.h +++ b/chromeos/services/assistant/public/features.h
@@ -14,6 +14,10 @@ // Enable Assistant Feedback UI. COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) +extern const base::Feature kAssistantAudioEraser; + +// Enable Assistant Feedback UI. +COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) extern const base::Feature kAssistantFeedbackUi; // Enables Assistant voice match enrollment. @@ -74,6 +78,8 @@ COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAppSupportEnabled(); +COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAudioEraserEnabled(); + COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsClearCutLogEnabled(); COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsDspHotwordEnabled(); @@ -83,8 +89,14 @@ COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsInAssistantNotificationsEnabled(); +COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsKeyRemappingEnabled(); + +COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsPowerManagerEnabled(); + COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsRoutinesEnabled(); +COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsScreenContextQueryEnabled(); + COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsStereoAudioInputEnabled(); COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsTimerNotificationEnabled(); @@ -93,11 +105,6 @@ COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsWarmerWelcomeEnabled(); -COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsKeyRemappingEnabled(); - -COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsScreenContextQueryEnabled(); - -COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsPowerManagerEnabled(); } // namespace features } // namespace assistant
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom index 339b2c3..3fbc76e 100644 --- a/chromeos/services/assistant/public/mojom/assistant.mojom +++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -271,11 +271,23 @@ // Models an Android app. struct AndroidAppInfo { + // Unique name to identify a specific app. string package_name; + + // Version number of the app. int32 version; + + // Localized app name. string localized_app_name; + + // Intent data to operate on. string intent; + + // Status of the app. AppStatus status; + + // The general action to be performed, such as ACTION_VIEW, ACTION_MAIN, etc. + string action; }; // Details for Assistant feedback.
diff --git a/chromeos/services/assistant/service_unittest.cc b/chromeos/services/assistant/service_unittest.cc index 01ee656c..585334e73 100644 --- a/chromeos/services/assistant/service_unittest.cc +++ b/chromeos/services/assistant/service_unittest.cc
@@ -76,9 +76,6 @@ void GetPrimaryAccountWhenAvailable( GetPrimaryAccountWhenAvailableCallback callback) override {} - void GetAccountInfoFromGaiaId( - const std::string& gaia_id, - GetAccountInfoFromGaiaIdCallback callback) override {} void GetAccessToken(const std::string& account_id, const ::identity::ScopeSet& scopes, const std::string& consumer_id,
diff --git a/chromeos/services/assistant/utils.cc b/chromeos/services/assistant/utils.cc index ff0fd1f..49cbf7c 100644 --- a/chromeos/services/assistant/utils.cc +++ b/chromeos/services/assistant/utils.cc
@@ -14,6 +14,7 @@ #include "base/values.h" #include "chromeos/assistant/internal/internal_constants.h" #include "chromeos/dbus/util/version_loader.h" +#include "chromeos/services/assistant/public/features.h" namespace chromeos { namespace assistant { @@ -71,6 +72,15 @@ Value audio_input(Type::DICTIONARY); // Skip sending speaker ID selection info to disable user verification. audio_input.SetKey("should_send_speaker_id_selection_info", Value(false)); + + Value sources(Type::LIST); + Value dict(Type::DICTIONARY); + dict.SetKey("enable_eraser", Value(features::IsAudioEraserEnabled())); + dict.SetKey("enable_eraser_toggling", + Value(features::IsAudioEraserEnabled())); + sources.GetList().push_back(std::move(dict)); + audio_input.SetKey("sources", std::move(sources)); + config.SetKey("audio_input", std::move(audio_input)); std::string json;
diff --git a/components/BUILD.gn b/components/BUILD.gn index 4dbc6a7..948478e 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -570,6 +570,7 @@ sources += [ "dom_distiller/standalone/content_extractor_browsertest.cc" ] deps += [ "//components/leveldb_proto", + "//components/leveldb_proto/content:factory", "//components/prefs:test_support", "//components/sync_preferences:test_support", ]
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index b3ea166..28bae00 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -93,8 +93,6 @@ "autofill_subject.h", "autofill_type.cc", "autofill_type.h", - "autofill_wallet_data_type_controller.cc", - "autofill_wallet_data_type_controller.h", "contact_form_label_formatter.cc", "contact_form_label_formatter.h", "contact_info.cc", @@ -145,6 +143,8 @@ "password_requirements_spec_printer.cc", "password_requirements_spec_printer.h", "payments/account_info_getter.h", + "payments/autofill_wallet_data_type_controller.cc", + "payments/autofill_wallet_data_type_controller.h", "payments/autofill_wallet_model_type_controller.cc", "payments/autofill_wallet_model_type_controller.h", "payments/card_unmask_delegate.cc", @@ -541,7 +541,6 @@ "autofill_profile_validator_unittest.cc", "autofill_subject_unittest.cc", "autofill_type_unittest.cc", - "autofill_wallet_data_type_controller_unittest.cc", "contact_info_unittest.cc", "country_combobox_model_unittest.cc", "country_names_unittest.cc", @@ -557,6 +556,7 @@ "password_generator_fips181_unittest.cc", "password_generator_unittest.cc", "password_requirements_spec_fetcher_unittest.cc", + "payments/autofill_wallet_data_type_controller_unittest.cc", "payments/credit_card_save_manager_unittest.cc", "payments/full_card_request_unittest.cc", "payments/legacy_strike_database_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_wallet_data_type_controller.cc b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc similarity index 95% rename from components/autofill/core/browser/autofill_wallet_data_type_controller.cc rename to components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc index 7ad8b87..caeb3e4 100644 --- a/components/autofill/core/browser/autofill_wallet_data_type_controller.cc +++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_wallet_data_type_controller.h" +#include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h" #include <utility> @@ -22,7 +22,7 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController( syncer::ModelType type, scoped_refptr<base::SingleThreadTaskRunner> db_thread, - const base::Closure& dump_stack, + const base::RepeatingClosure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, const PersonalDataManagerProvider& pdm_provider, @@ -69,8 +69,8 @@ if (!callback_registered_) { web_data_service_->RegisterDBLoadedCallback( - base::Bind(&AutofillWalletDataTypeController::OnModelLoaded, - base::AsWeakPtr(this))); + base::BindRepeating(&AutofillWalletDataTypeController::OnModelLoaded, + base::AsWeakPtr(this))); callback_registered_ = true; }
diff --git a/components/autofill/core/browser/autofill_wallet_data_type_controller.h b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h similarity index 88% rename from components/autofill/core/browser/autofill_wallet_data_type_controller.h rename to components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h index be0e0fff..af98486 100644 --- a/components/autofill/core/browser/autofill_wallet_data_type_controller.h +++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ #include "base/callback.h" #include "base/macros.h" @@ -35,7 +35,7 @@ AutofillWalletDataTypeController( syncer::ModelType type, scoped_refptr<base::SingleThreadTaskRunner> db_thread, - const base::Closure& dump_stack, + const base::RepeatingClosure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, const PersonalDataManagerProvider& pdm_provider, @@ -78,4 +78,4 @@ } // namespace browser_sync -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_
diff --git a/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc similarity index 90% rename from components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc rename to components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc index c8a98af..1c5d218a 100644 --- a/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc +++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_wallet_data_type_controller.h" +#include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h" #include <memory> @@ -47,7 +47,7 @@ const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner) : AutofillWebDataService(ui_task_runner, db_task_runner), is_database_loaded_(false), - db_loaded_callback_(base::Callback<void(void)>()) {} + db_loaded_callback_(base::RepeatingCallback<void(void)>()) {} // Mark the database as loaded and send out the appropriate notification. void LoadDatabase() { @@ -57,14 +57,17 @@ db_loaded_callback_.Run(); // Clear the callback here or the WDS and DTC will have refs to each other // and create a memory leak. - db_loaded_callback_ = base::Callback<void(void)>(); + // TODO(crbug.com/941530): Solve this with a OnceCallback. Note that + // RegisterDBLoadedCallback overrides other functions that still use + // base::[Repeating]Callbacks, so it would affect non-Autofill code. + db_loaded_callback_ = base::RepeatingCallback<void(void)>(); } } bool IsDatabaseLoaded() override { return is_database_loaded_; } void RegisterDBLoadedCallback( - const base::Callback<void(void)>& callback) override { + const base::RepeatingCallback<void(void)>& callback) override { db_loaded_callback_ = callback; } @@ -72,7 +75,7 @@ ~FakeWebDataService() override {} bool is_database_loaded_; - base::Callback<void(void)> db_loaded_callback_; + base::RepeatingCallback<void(void)> db_loaded_callback_; DISALLOW_COPY_AND_ASSIGN(FakeWebDataService); }; @@ -123,13 +126,14 @@ void Start() { autofill_wallet_dtc_->LoadModels( syncer::ConfigureContext(), - base::Bind(&AutofillWalletDataTypeControllerTest::OnLoadFinished, - base::Unretained(this))); + base::BindRepeating( + &AutofillWalletDataTypeControllerTest::OnLoadFinished, + base::Unretained(this))); base::RunLoop().RunUntilIdle(); if (autofill_wallet_dtc_->state() != syncer::DataTypeController::MODEL_LOADED) return; - autofill_wallet_dtc_->StartAssociating(base::Bind( + autofill_wallet_dtc_->StartAssociating(base::BindRepeating( &syncer::StartCallbackMock::Run, base::Unretained(&start_callback_))); base::RunLoop().RunUntilIdle(); }
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 7237048..b953a1b 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -25,7 +25,7 @@ } oneof client { Chrome chrome = 1; } - // locale should be a comma separated list of language tags. Each tag should + // locale will be the language tag of the default locale. The tag should // be a well-formed IETF BCP 47 language tag with language and country code // (e.g., "en-US"). // The intent is to communicate the client language preferences to the server.
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index 7fc51a1..c669f35 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -11,7 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_wallet_data_type_controller.h" +#include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h" #include "components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h" #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h" #include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
diff --git a/components/dom_distiller/core/dom_distiller_service_unittest.cc b/components/dom_distiller/core/dom_distiller_service_unittest.cc index 5fe955c..d781a985c 100644 --- a/components/dom_distiller/core/dom_distiller_service_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_service_unittest.cc
@@ -92,7 +92,7 @@ std::unique_ptr<DistillerFactory>(distiller_factory_), std::unique_ptr<DistillerPageFactory>(distiller_page_factory_), std::unique_ptr<DistilledPagePrefs>())); - fake_db->InitCallback(true); + fake_db->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db->LoadCallback(true); }
diff --git a/components/dom_distiller/core/dom_distiller_store.cc b/components/dom_distiller/core/dom_distiller_store.cc index 06cbad4..483b9c5 100644 --- a/components/dom_distiller/core/dom_distiller_store.cc +++ b/components/dom_distiller/core/dom_distiller_store.cc
@@ -29,39 +29,25 @@ using syncer::SyncError; using syncer::SyncMergeResult; -namespace { -// Statistics are logged to UMA with this string as part of histogram name. They -// can all be found under LevelDB.*.DomDistillerStore. Changing this needs to -// synchronize with histograms.xml, AND will also become incompatible with older -// browsers still reporting the previous values. -const char kDatabaseUMAClientName[] = "DomDistillerStore"; -} - namespace dom_distiller { DomDistillerStore::DomDistillerStore( - std::unique_ptr<ProtoDatabase<ArticleEntry>> database, - const base::FilePath& database_dir) + std::unique_ptr<ProtoDatabase<ArticleEntry>> database) : database_(std::move(database)), database_loaded_(false), weak_ptr_factory_(this) { - database_->Init(kDatabaseUMAClientName, database_dir, - leveldb_proto::CreateSimpleOptions(), - base::BindOnce(&DomDistillerStore::OnDatabaseInit, + database_->Init(base::BindOnce(&DomDistillerStore::OnDatabaseInit, weak_ptr_factory_.GetWeakPtr())); } DomDistillerStore::DomDistillerStore( std::unique_ptr<ProtoDatabase<ArticleEntry>> database, - const std::vector<ArticleEntry>& initial_data, - const base::FilePath& database_dir) + const std::vector<ArticleEntry>& initial_data) : database_(std::move(database)), database_loaded_(false), model_(initial_data), weak_ptr_factory_(this) { - database_->Init(kDatabaseUMAClientName, database_dir, - leveldb_proto::CreateSimpleOptions(), - base::BindOnce(&DomDistillerStore::OnDatabaseInit, + database_->Init(base::BindOnce(&DomDistillerStore::OnDatabaseInit, weak_ptr_factory_.GetWeakPtr())); } @@ -176,8 +162,9 @@ NotifyObservers(*changes_applied); } -void DomDistillerStore::OnDatabaseInit(bool success) { - if (!success) { +void DomDistillerStore::OnDatabaseInit( + leveldb_proto::Enums::InitStatus status) { + if (status != leveldb_proto::Enums::InitStatus::kOK) { DVLOG(1) << "DOM Distiller database init failed."; database_.reset(); return;
diff --git a/components/dom_distiller/core/dom_distiller_store.h b/components/dom_distiller/core/dom_distiller_store.h index d98e538..1b04a16a 100644 --- a/components/dom_distiller/core/dom_distiller_store.h +++ b/components/dom_distiller/core/dom_distiller_store.h
@@ -23,10 +23,6 @@ #include "components/sync/model/syncable_service.h" #include "url/gurl.h" -namespace base { -class FilePath; -} - namespace dom_distiller { // Interface for accessing the stored/synced DomDistiller entries. @@ -72,19 +68,15 @@ public: typedef std::vector<ArticleEntry> EntryVector; - // Creates storage using the given database for local storage. Initializes the - // database with |database_dir|. + // Creates storage using the given database for local storage. DomDistillerStore( - std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>> database, - const base::FilePath& database_dir); + std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>> database); // Creates storage using the given database for local storage. Initializes the - // database with |database_dir|. Also initializes the internal model to - // |initial_model|. + // internal model to |initial_model|. DomDistillerStore( std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>> database, - const std::vector<ArticleEntry>& initial_data, - const base::FilePath& database_dir); + const std::vector<ArticleEntry>& initial_data); ~DomDistillerStore() override; @@ -100,7 +92,7 @@ void RemoveObserver(DomDistillerObserver* observer) override; private: - void OnDatabaseInit(bool success); + void OnDatabaseInit(leveldb_proto::Enums::InitStatus status); void OnDatabaseLoad(bool success, std::unique_ptr<EntryVector> entries); void OnDatabaseSave(bool success);
diff --git a/components/dom_distiller/core/dom_distiller_store_unittest.cc b/components/dom_distiller/core/dom_distiller_store_unittest.cc index 92b35c70..4e4812f 100644 --- a/components/dom_distiller/core/dom_distiller_store_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -209,9 +209,7 @@ CreateStore(); - fake_db_->InitCallback(true); - EXPECT_EQ(fake_db_->GetDirectory(), - FakeDB<ArticleEntry>::DirectoryForTestDB()); + fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db_->LoadCallback(true); EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), db_model_)); @@ -231,7 +229,7 @@ AddEntry(GetSampleEntry(4), &expected_model); CreateStore(); - fake_db_->InitCallback(true); + fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db_->LoadCallback(true); EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model)); @@ -240,7 +238,7 @@ TEST_F(DomDistillerStoreTest, TestAddAndRemoveEntry) { CreateStore(); - fake_db_->InitCallback(true); + fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db_->LoadCallback(true); EXPECT_TRUE(store_->GetEntries().empty()); @@ -263,7 +261,7 @@ TEST_F(DomDistillerStoreTest, TestAddAndUpdateEntry) { CreateStore(); - fake_db_->InitCallback(true); + fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db_->LoadCallback(true); EXPECT_TRUE(store_->GetEntries().empty()); @@ -297,7 +295,7 @@ CreateStore(); MockDistillerObserver observer; store_->AddObserver(&observer); - fake_db_->InitCallback(true); + fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); fake_db_->LoadCallback(true); std::vector<DomDistillerObserver::ArticleUpdate> expected_updates; DomDistillerObserver::ArticleUpdate update;
diff --git a/components/dom_distiller/core/dom_distiller_test_util.cc b/components/dom_distiller/core/dom_distiller_test_util.cc index a69c7b7..52c77c34 100644 --- a/components/dom_distiller/core/dom_distiller_test_util.cc +++ b/components/dom_distiller/core/dom_distiller_test_util.cc
@@ -92,7 +92,7 @@ const FakeDB<ArticleEntry>::EntryMap& store_model) { return new DomDistillerStore( std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>>(fake_db), - EntryMapToList(store_model), FakeDB<ArticleEntry>::DirectoryForTestDB()); + EntryMapToList(store_model)); } } // namespace util
diff --git a/components/dom_distiller/standalone/content_extractor_browsertest.cc b/components/dom_distiller/standalone/content_extractor_browsertest.cc index 2b235bb..6d7210f 100644 --- a/components/dom_distiller/standalone/content_extractor_browsertest.cc +++ b/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -30,6 +30,7 @@ #include "components/dom_distiller/core/proto/distilled_article.pb.h" #include "components/dom_distiller/core/proto/distilled_page.pb.h" #include "components/dom_distiller/core/task_tracker.h" +#include "components/leveldb_proto/content/proto_database_provider_factory.h" #include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/public/proto_database_provider.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -130,12 +131,18 @@ scoped_refptr<base::SequencedTaskRunner> background_task_runner = base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}); + auto* db_provider = + leveldb_proto::ProtoDatabaseProviderFactory::GetForBrowserContext( + context); + // TODO(cjhopman): use an in-memory database instead of an on-disk one with // temporary directory. - auto db = leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB<ArticleEntry>( + auto db = db_provider->GetDB<ArticleEntry>( + leveldb_proto::ProtoDbType::DOM_DISTILLER_STORE, db_path, background_task_runner); + std::unique_ptr<DomDistillerStore> dom_distiller_store( - new DomDistillerStore(std::move(db), db_path)); + new DomDistillerStore(std::move(db))); std::unique_ptr<DistillerPageFactory> distiller_page_factory( new DistillerPageWebContentsFactory(context));
diff --git a/components/gwp_asan/crash_handler/crash_handler.cc b/components/gwp_asan/crash_handler/crash_handler.cc index 925ebde..ca6a75e9 100644 --- a/components/gwp_asan/crash_handler/crash_handler.cc +++ b/components/gwp_asan/crash_handler/crash_handler.cc
@@ -80,8 +80,8 @@ HandleException(const crashpad::ProcessSnapshot& snapshot) { gwp_asan::Crash proto; auto result = CrashAnalyzer::GetExceptionInfo(snapshot, &proto); - UMA_HISTOGRAM_ENUMERATION("GwpAsan.CrashAnalysisResult", result); - + if (result != GwpAsanCrashAnalysisResult::kUnrelatedCrash) + UMA_HISTOGRAM_ENUMERATION("GwpAsan.CrashAnalysisResult", result); if (result != GwpAsanCrashAnalysisResult::kGwpAsanCrash) return nullptr;
diff --git a/components/leveldb_proto/internal/proto_database_impl.h b/components/leveldb_proto/internal/proto_database_impl.h index 0b23b981..f6dc67d2 100644 --- a/components/leveldb_proto/internal/proto_database_impl.h +++ b/components/leveldb_proto/internal/proto_database_impl.h
@@ -82,16 +82,14 @@ virtual ~ProtoDatabaseImpl() = default; - // DEPRECATED. This is to be used in case of forced unique db behavior. + void Init(Callbacks::InitStatusCallback callback) override; void Init(const char* client_name, const base::FilePath& database_dir, const leveldb_env::Options& options, Callbacks::InitCallback callback) override; - - // This can be used along with a database obtained from new api - // Provider::GetDB(). If using the old api to create unique db, then we do not - // know the database dir and init will fail. - void Init(const std::string& client_name, + void Init(const std::string& uma_name, + Callbacks::InitStatusCallback callback) override; + void Init(const leveldb_env::Options& unique_db_options, Callbacks::InitStatusCallback callback) override; // Internal only api. @@ -161,9 +159,10 @@ template <typename T_> friend class ProtoDatabaseImplTest; - void Init(const std::string& client_name, - bool use_shared_db, - Callbacks::InitStatusCallback callback); + void InitInternal(const std::string& client_name, + const leveldb_env::Options& options, + bool use_shared_db, + Callbacks::InitStatusCallback callback); void PostTransaction(base::OnceClosure task); @@ -391,23 +390,47 @@ bool use_shared_db = !force_unique_db_ && SharedProtoDatabaseClientList::ShouldUseSharedDB(db_type_); - Init(client_uma_name, use_shared_db, std::move(callback)); + InitInternal(client_uma_name, CreateSimpleOptions(), use_shared_db, + std::move(callback)); } template <typename P, typename T> -void ProtoDatabaseImpl<P, T>::Init(const std::string& client_name, - bool use_shared_db, - Callbacks::InitStatusCallback callback) { - auto options = CreateSimpleOptions(); - // If we're NOT using a shared DB, we want to force creation of the unique one - // because that's what we expect to be using moving forward. If we ARE using - // the shared DB, we only want to see if there's a unique DB that already - // exists and can be opened so that we can perform migration if necessary. - options.create_if_missing = !use_shared_db; +void ProtoDatabaseImpl<P, T>::Init( + typename Callbacks::InitStatusCallback callback) { + bool use_shared_db = + !force_unique_db_ && + SharedProtoDatabaseClientList::ShouldUseSharedDB(db_type_); + const std::string& client_uma_name = + SharedProtoDatabaseClientList::ProtoDbTypeToString(db_type_); + + InitInternal(client_uma_name, CreateSimpleOptions(), use_shared_db, + std::move(callback)); +} + +template <typename P, typename T> +void ProtoDatabaseImpl<P, T>::Init( + const leveldb_env::Options& unique_db_options, + typename Callbacks::InitStatusCallback callback) { + bool use_shared_db = + !force_unique_db_ && + SharedProtoDatabaseClientList::ShouldUseSharedDB(db_type_); + const std::string& client_uma_name = + SharedProtoDatabaseClientList::ProtoDbTypeToString(db_type_); + + InitInternal(client_uma_name, unique_db_options, use_shared_db, + std::move(callback)); +} + +template <typename P, typename T> +void ProtoDatabaseImpl<P, T>::InitInternal( + const std::string& client_name, + const leveldb_env::Options& unique_db_options, + bool use_shared_db, + Callbacks::InitStatusCallback callback) { task_runner_->PostTask( FROM_HERE, base::BindOnce(&ProtoDatabaseSelector::InitUniqueOrShared, db_wrapper_, - client_name, db_dir_, options, use_shared_db, + client_name, db_dir_, unique_db_options, use_shared_db, base::SequencedTaskRunnerHandle::Get(), std::move(callback))); }
diff --git a/components/leveldb_proto/internal/proto_database_impl_unittest.cc b/components/leveldb_proto/internal/proto_database_impl_unittest.cc index 2d5a0b8..43571a3 100644 --- a/components/leveldb_proto/internal/proto_database_impl_unittest.cc +++ b/components/leveldb_proto/internal/proto_database_impl_unittest.cc
@@ -188,14 +188,12 @@ base::RunLoop run_init; // Initialize a database, it should succeed. - db->Init(kDefaultClientName, - base::BindOnce( - [](base::OnceClosure closure, - leveldb_proto::Enums::InitStatus status) { - std::move(closure).Run(); - EXPECT_TRUE(status == leveldb_proto::Enums::InitStatus::kOK); - }, - run_init.QuitClosure())); + db->Init(base::BindOnce( + [](base::OnceClosure closure, leveldb_proto::Enums::InitStatus status) { + std::move(closure).Run(); + EXPECT_TRUE(status == leveldb_proto::Enums::InitStatus::kOK); + }, + run_init.QuitClosure())); run_init.Run(); } @@ -234,7 +232,8 @@ const std::string& client_name, bool use_shared_db, Callbacks::InitStatusCallback callback) { - db_impl->Init(client_name, use_shared_db, std::move(callback)); + db_impl->InitInternal(client_name, leveldb_proto::CreateSimpleOptions(), + use_shared_db, std::move(callback)); } void InitDBImplAndWait(ProtoDatabaseImpl<TestProto, T>* db_impl, @@ -937,13 +936,43 @@ EXPECT_FALSE(base::PathExists(temp_dir.GetPath())); } +TYPED_TEST(ProtoDatabaseImplTest, InitWithOptions) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + EXPECT_TRUE(base::IsDirectoryEmpty(temp_dir.GetPath())); + + auto db_provider = this->CreateProviderNoSharedDB(); + auto db_impl = + this->CreateDBImpl(ProtoDbType::TEST_DATABASE1, temp_dir.GetPath(), + this->GetTestThreadTaskRunner(), + this->CreateSharedProvider(db_provider.get())); + + base::RunLoop run_init; + auto options = leveldb_proto::CreateSimpleOptions(); + options.create_if_missing = false; + + // Initialize database with unique DB arguments, it should fail because we + // specified create_if_missing = false and there's no shared DB. + db_impl->Init( + options, + base::BindOnce( + [](base::OnceClosure closure, Enums::InitStatus expect_status, + Enums::InitStatus status) { + ASSERT_EQ(status, expect_status); + std::move(closure).Run(); + }, + run_init.QuitClosure(), Enums::InitStatus::kError)); + + run_init.Run(); +} + TYPED_TEST(ProtoDatabaseImplTest, InitUniqueTwiceShouldSucceed) { base::ScopedTempDir temp_dir_profile; ASSERT_TRUE(temp_dir_profile.CreateUniqueTempDir()); // Both databases will be opened as unique. auto experiment_params = std::map<std::string, std::string>{ - {"migrate_TEST_DATABASE1", "false"}, {"migrate_TEST_DATABASE2", "false"}}; + {"migrate_TestDatabase1", "false"}, {"migrate_TestDatabase2", "false"}}; this->SetUpExperimentParams(experiment_params); leveldb_proto::ProtoDatabaseProvider* db_provider = @@ -961,7 +990,7 @@ // First database will open as unique, second DB will open as shared. auto experiment_params = std::map<std::string, std::string>{ - {"migrate_TEST_DATABASE1", "false"}, {"migrate_TEST_DATABASE2", "true"}}; + {"migrate_TestDatabase1", "false"}, {"migrate_TestDatabase2", "true"}}; this->SetUpExperimentParams(experiment_params); leveldb_proto::ProtoDatabaseProvider* db_provider = @@ -979,7 +1008,7 @@ // First database will open as shared, second DB will open as unique. auto experiment_params = std::map<std::string, std::string>{ - {"migrate_TEST_DATABASE1", "true"}, {"migrate_TEST_DATABASE2", "false"}}; + {"migrate_TestDatabase1", "true"}, {"migrate_TestDatabase2", "false"}}; this->SetUpExperimentParams(experiment_params); leveldb_proto::ProtoDatabaseProvider* db_provider = @@ -997,7 +1026,7 @@ // Both databases will open as shared. auto experiment_params = std::map<std::string, std::string>{ - {"migrate_TEST_DATABASE1", "true"}, {"migrate_TEST_DATABASE2", "true"}}; + {"migrate_TestDatabase1", "true"}, {"migrate_TestDatabase2", "true"}}; this->SetUpExperimentParams(experiment_params); leveldb_proto::ProtoDatabaseProvider* db_provider =
diff --git a/components/leveldb_proto/internal/proto_database_selector.cc b/components/leveldb_proto/internal/proto_database_selector.cc index 5edef99..695b42d 100644 --- a/components/leveldb_proto/internal/proto_database_selector.cc +++ b/components/leveldb_proto/internal/proto_database_selector.cc
@@ -63,7 +63,7 @@ void ProtoDatabaseSelector::InitUniqueOrShared( const std::string& client_name, base::FilePath db_dir, - const leveldb_env::Options& options, + const leveldb_env::Options& unique_db_options, bool use_shared_db, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, Callbacks::InitStatusCallback callback) { @@ -71,8 +71,19 @@ init_status_ = InitStatus::IN_PROGRESS; unique_database_dir_ = db_dir; client_name_ = client_name; - auto unique_db = - std::make_unique<UniqueProtoDatabase>(db_dir, options, task_runner_); + + auto unique_options = unique_db_options; + // There are two Init methods, one that receives Options for its unique DB and + // another that uses CreateSimpleOptions() to open the unique DB. In case a + // shared DB needs to be used then we don't need to create a new unique DB if + // it doesn't exist. In case a unique DB needs to be used then we don't change + // the create_if_missing parameter, because it may have been set by a client. + if (use_shared_db) { + unique_options.create_if_missing = false; + } + + auto unique_db = std::make_unique<UniqueProtoDatabase>(db_dir, unique_options, + task_runner_); auto* unique_db_ptr = unique_db.get(); unique_db_ptr->Init( client_name, base::BindOnce(&ProtoDatabaseSelector::OnInitUniqueDB, this,
diff --git a/components/leveldb_proto/internal/proto_database_selector.h b/components/leveldb_proto/internal/proto_database_selector.h index afc80f2..48cab0c4 100644 --- a/components/leveldb_proto/internal/proto_database_selector.h +++ b/components/leveldb_proto/internal/proto_database_selector.h
@@ -43,7 +43,7 @@ void InitUniqueOrShared( const std::string& client_name, base::FilePath db_dir, - const leveldb_env::Options& options, + const leveldb_env::Options& unique_db_options, bool use_shared_db, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, Callbacks::InitStatusCallback callback);
diff --git a/components/leveldb_proto/internal/shared_proto_database_client_list_unittest.cc b/components/leveldb_proto/internal/shared_proto_database_client_list_unittest.cc index 86e5662c0..35113c73 100644 --- a/components/leveldb_proto/internal/shared_proto_database_client_list_unittest.cc +++ b/components/leveldb_proto/internal/shared_proto_database_client_list_unittest.cc
@@ -13,16 +13,16 @@ namespace leveldb_proto { namespace { -const char kTestClientName[] = "TEST_DATABASE1"; +const char kTestClientName[] = "TestDatabase1"; } class SharedProtoDatabaseClientListTest : public testing::Test { public: void SetUpExperimentParam(std::string key, std::string value) { std::map<std::string, std::string> params = { - {"migrate_TEST_DATABASE0", "true"}, + {"migrate_TestDatabase0", "true"}, {"migrate_" + key, value}, - {"migrate_TEST_DATABASE2", "false"}, + {"migrate_TestDatabase2", "false"}, }; scoped_feature_list_.InitAndEnableFeatureWithParameters( @@ -45,7 +45,7 @@ TEST_F(SharedProtoDatabaseClientListTest, ShouldUseSharedDBTest_OnlyWhenParamMatchesName) { - SetUpExperimentParam("TEST_DATABASE10", "true"); + SetUpExperimentParam("TestDatabase10", "true"); bool use_shared = SharedProtoDatabaseClientList::ShouldUseSharedDB( ProtoDbType::TEST_DATABASE1);
diff --git a/components/leveldb_proto/public/proto_database.h b/components/leveldb_proto/public/proto_database.h index a8369ef..f752e7fb 100644 --- a/components/leveldb_proto/public/proto_database.h +++ b/components/leveldb_proto/public/proto_database.h
@@ -96,12 +96,25 @@ virtual ~ProtoDatabase() = default; - // Asynchronously initializes the object with the specified |options|. - // |callback| will be invoked on the calling thread when complete. - virtual void Init(const std::string& client_name, + // Asynchronously initializes the object, which must have been created by the + // ProtoDatabaseProvider::GetDB<T> function. |callback| will be invoked on the + // calling thread when complete. + // + // DEPRECATED: |unique_db_options| is used only when a unique DB is loaded, + // once migration to shared DB is done, this parameter will be ignored. + // + // DEPRECATED: |client_uma_name| was used to record UMA metrics, new clients + // should instead add their name to + // SharedProtoDatabaseClientList::ProtoDbTypeToString. + virtual void Init(Callbacks::InitStatusCallback callback) = 0; + virtual void Init(const std::string& client_uma_name, Callbacks::InitStatusCallback callback) = 0; - // This version of Init is for compatibility, since many of the current - // proto database clients still use this. + virtual void Init(const leveldb_env::Options& unique_db_options, + Callbacks::InitStatusCallback callback) = 0; + + // DEPRECATED. This version of Init is for compatibility, must be called only + // when the object is created by the ProtoDatabaseProvider::CreateUniqueDB<T> + // function. virtual void Init(const char* client_name, const base::FilePath& database_dir, const leveldb_env::Options& options,
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.cc b/components/leveldb_proto/public/shared_proto_database_client_list.cc index 64d46e1..d3ecd28 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.cc +++ b/components/leveldb_proto/public/shared_proto_database_client_list.cc
@@ -17,31 +17,6 @@ namespace { -std::string PtotoDbTypeToString(ProtoDbType db_type) { - switch (db_type) { - case ProtoDbType::FEATURE_ENGAGEMENT_EVENT: - return "FEATURE_ENGAGEMENT_EVENT"; - case ProtoDbType::FEATURE_ENGAGEMENT_AVAILABILITY: - return "FEATURE_ENGAGEMENT_AVAILABILITY"; - case ProtoDbType::USAGE_STATS_WEBSITE_EVENT: - return "USAGE_STATS_WEBSITE_EVENT"; - case ProtoDbType::USAGE_STATS_SUSPENSION: - return "USAGE_STATS_SUSPENSION"; - case ProtoDbType::USAGE_STATS_TOKEN_MAPPING: - return "USAGE_STATS_TOKEN_MAPPING"; - case ProtoDbType::LAST: - NOTREACHED(); - break; - case ProtoDbType::TEST_DATABASE0: - return "TEST_DATABASE0"; - case ProtoDbType::TEST_DATABASE1: - return "TEST_DATABASE1"; - case ProtoDbType::TEST_DATABASE2: - return "TEST_DATABASE2"; - } - return std::string(); -} - constexpr ProtoDbType kWhitelistedListForSharedImpl[]{ ProtoDbType::LAST, // Marks the end of list. }; @@ -51,6 +26,35 @@ } // namespace // static +std::string SharedProtoDatabaseClientList::ProtoDbTypeToString( + ProtoDbType db_type) { + switch (db_type) { + case ProtoDbType::FEATURE_ENGAGEMENT_EVENT: + return "FeatureEngagementTrackerEventStore"; + case ProtoDbType::FEATURE_ENGAGEMENT_AVAILABILITY: + return "FeatureEngagementTrackerAvailabilityStore"; + case ProtoDbType::USAGE_STATS_WEBSITE_EVENT: + return "UsageStatsWebsiteEvent"; + case ProtoDbType::USAGE_STATS_SUSPENSION: + return "UsageStatsSuspension"; + case ProtoDbType::USAGE_STATS_TOKEN_MAPPING: + return "UsageStatsTokenMapping"; + case ProtoDbType::DOM_DISTILLER_STORE: + return "DomDistillerStore"; + case ProtoDbType::LAST: + NOTREACHED(); + break; + case ProtoDbType::TEST_DATABASE0: + return "TestDatabase0"; + case ProtoDbType::TEST_DATABASE1: + return "TestDatabase1"; + case ProtoDbType::TEST_DATABASE2: + return "TestDatabase2"; + } + return std::string(); +} + +// static bool SharedProtoDatabaseClientList::ShouldUseSharedDB(ProtoDbType db_type) { for (size_t i = 0; kWhitelistedListForSharedImpl[i] != ProtoDbType::LAST; ++i) { @@ -61,11 +65,8 @@ if (!base::FeatureList::IsEnabled(kProtoDBSharedMigration)) return false; - std::map<std::string, std::string> params; - if (!base::GetFieldTrialParamsByFeature(kProtoDBSharedMigration, ¶ms)) - return false; - - std::string name = PtotoDbTypeToString(db_type); + std::string name = + SharedProtoDatabaseClientList::ProtoDbTypeToString(db_type); return base::GetFieldTrialParamByFeatureAsBool( kProtoDBSharedMigration, kDBNameParamPrefix + name, false); }
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.h b/components/leveldb_proto/public/shared_proto_database_client_list.h index 211a24ab..332f079 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.h +++ b/components/leveldb_proto/public/shared_proto_database_client_list.h
@@ -25,6 +25,7 @@ USAGE_STATS_WEBSITE_EVENT = 5, USAGE_STATS_SUSPENSION = 6, USAGE_STATS_TOKEN_MAPPING = 7, + DOM_DISTILLER_STORE = 8, LAST, }; @@ -43,7 +44,12 @@ class SharedProtoDatabaseClientList { public: + // Determines if the given |db_type| should use a unique or shared DB. static bool ShouldUseSharedDB(ProtoDbType db_type); + + // Converts a ProtoDbType to a string, which is used for UMA metrics and field + // trials. The strings returned should match the strings on histograms.xml + static std::string ProtoDbTypeToString(ProtoDbType db_type); }; } // namespace leveldb_proto
diff --git a/components/leveldb_proto/testing/fake_db.h b/components/leveldb_proto/testing/fake_db.h index 3d947a3..8d7cba1f 100644 --- a/components/leveldb_proto/testing/fake_db.h +++ b/components/leveldb_proto/testing/fake_db.h
@@ -34,6 +34,9 @@ // ProtoDatabase implementation. void Init(const std::string& client_name, Callbacks::InitStatusCallback callback) override; + void Init(Callbacks::InitStatusCallback callback) override; + void Init(const leveldb_env::Options& unique_db_options, + Callbacks::InitStatusCallback callback) override; void Init(const char* client_name, const base::FilePath& database_dir, const leveldb_env::Options& options, @@ -145,6 +148,17 @@ } template <typename P, typename T> +void FakeDB<P, T>::Init(const leveldb_env::Options& unique_db_options, + Callbacks::InitStatusCallback callback) { + Init("fake_db", std::move(callback)); +} + +template <typename P, typename T> +void FakeDB<P, T>::Init(Callbacks::InitStatusCallback callback) { + Init("fake_db", std::move(callback)); +} + +template <typename P, typename T> void FakeDB<P, T>::Init(const char* client_name, const base::FilePath& database_dir, const leveldb_env::Options& options,
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc index 3c6f0572..ec510fd 100644 --- a/components/omnibox/browser/autocomplete_input.cc +++ b/components/omnibox/browser/autocomplete_input.cc
@@ -18,6 +18,7 @@ #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" #include "third_party/metrics_proto/omnibox_event.pb.h" +#include "third_party/re2/src/re2/re2.h" #include "url/url_canon_ip.h" #include "url/url_util.h" @@ -204,6 +205,12 @@ return metrics::OmniboxInputType::URL; } + // Treat javascript: scheme queries followed by things that are unlikely to + // be code as QUERY, rather than script to execute (URL). + if (RE2::FullMatch(base::UTF16ToUTF8(text), "(?i)javascript:([^;=().]*)")) { + return metrics::OmniboxInputType::QUERY; + } + // If the user typed a scheme, and it's HTTP or HTTPS, we know how to parse it // well enough that we can fall through to the heuristics below. If it's // something else, we can just determine our action based on what we do with
diff --git a/components/omnibox/browser/autocomplete_input_unittest.cc b/components/omnibox/browser/autocomplete_input_unittest.cc index 00bbc9a..5315f56 100644 --- a/components/omnibox/browser/autocomplete_input_unittest.cc +++ b/components/omnibox/browser/autocomplete_input_unittest.cc
@@ -109,8 +109,17 @@ // { ASCIIToUTF16("mailto:abuse@foo.com"), metrics::OmniboxInputType::URL }, {ASCIIToUTF16("view-source:http://www.foo.com/"), metrics::OmniboxInputType::URL}, + {ASCIIToUTF16("javascript"), metrics::OmniboxInputType::UNKNOWN}, {ASCIIToUTF16("javascript:alert(\"Hi there\");"), metrics::OmniboxInputType::URL}, + {ASCIIToUTF16("javascript:alert%28\"Hi there\"%29;"), + metrics::OmniboxInputType::URL}, + {ASCIIToUTF16("javascript:foo;"), metrics::OmniboxInputType::URL}, + {ASCIIToUTF16("javascript:"), metrics::OmniboxInputType::QUERY}, + {ASCIIToUTF16("javascript:the cromulent parts"), + metrics::OmniboxInputType::QUERY}, + {ASCIIToUTF16("javascript:foo.getter"), metrics::OmniboxInputType::URL}, + {ASCIIToUTF16("JavaScript:Tutorials"), metrics::OmniboxInputType::QUERY}, #if defined(OS_WIN) {ASCIIToUTF16("C:\\Program Files"), metrics::OmniboxInputType::URL}, {ASCIIToUTF16("\\\\Server\\Folder\\File"), metrics::OmniboxInputType::URL},
diff --git a/components/omnibox/browser/location_bar_model_delegate.cc b/components/omnibox/browser/location_bar_model_delegate.cc index 4f01f6c1..1ed20e6 100644 --- a/components/omnibox/browser/location_bar_model_delegate.cc +++ b/components/omnibox/browser/location_bar_model_delegate.cc
@@ -12,9 +12,14 @@ return true; } -void LocationBarModelDelegate::GetSecurityInfo( - security_state::SecurityInfo* result) const { - return; +security_state::SecurityLevel LocationBarModelDelegate::GetSecurityLevel() + const { + return security_state::NONE; +} + +std::unique_ptr<security_state::VisibleSecurityState> +LocationBarModelDelegate::GetVisibleSecurityState() const { + return std::make_unique<security_state::VisibleSecurityState>(); } scoped_refptr<net::X509Certificate> LocationBarModelDelegate::GetCertificate()
diff --git a/components/omnibox/browser/location_bar_model_delegate.h b/components/omnibox/browser/location_bar_model_delegate.h index 7de779b..fc5f6085 100644 --- a/components/omnibox/browser/location_bar_model_delegate.h +++ b/components/omnibox/browser/location_bar_model_delegate.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_OMNIBOX_BROWSER_LOCATION_BAR_MODEL_DELEGATE_H_ #define COMPONENTS_OMNIBOX_BROWSER_LOCATION_BAR_MODEL_DELEGATE_H_ +#include <memory> #include <string> #include "base/memory/ref_counted.h" @@ -44,9 +45,14 @@ // in the location bar. virtual bool ShouldDisplayURL() const; - // Returns the underlying security info of the page without regard to any + // Returns the underlying security level of the page without regard to any // user edits that may be in progress. - virtual void GetSecurityInfo(security_state::SecurityInfo* result) const; + virtual security_state::SecurityLevel GetSecurityLevel() const; + + // Returns the underlying security state of the page without regard to any + // user edits that may be in progress. Should never return nullptr. + virtual std::unique_ptr<security_state::VisibleSecurityState> + GetVisibleSecurityState() const; // Returns the certificate for the current navigation entry. virtual scoped_refptr<net::X509Certificate> GetCertificate() const;
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc index 232032f4..0e359fd1 100644 --- a/components/omnibox/browser/location_bar_model_impl.cc +++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -102,9 +102,7 @@ if ((input_in_progress() && !ignore_editing) || !ShouldDisplayURL()) return security_state::NONE; - security_state::SecurityInfo info; - delegate_->GetSecurityInfo(&info); - return info.security_level; + return delegate_->GetSecurityLevel(); } bool LocationBarModelImpl::GetDisplaySearchTerms(base::string16* search_terms) { @@ -114,11 +112,12 @@ // Only show the search terms if the site is secure. However, make an // exception before the security state is initialized to prevent a UI flicker. - security_state::SecurityInfo info; - delegate_->GetSecurityInfo(&info); - if (info.connection_info_initialized && - info.security_level != security_state::SecurityLevel::SECURE && - info.security_level != security_state::SecurityLevel::EV_SECURE) { + std::unique_ptr<security_state::VisibleSecurityState> visible_security_state = + delegate_->GetVisibleSecurityState(); + security_state::SecurityLevel security_level = delegate_->GetSecurityLevel(); + if (visible_security_state->connection_info_initialized && + security_level != security_state::SecurityLevel::SECURE && + security_level != security_state::SecurityLevel::EV_SECURE) { return false; } @@ -220,12 +219,12 @@ return SecureChipText( l10n_util::GetStringUTF16(IDS_SECURE_VERBOSE_STATE)); case security_state::DANGEROUS: { - security_state::SecurityInfo security_info; - delegate_->GetSecurityInfo(&security_info); + std::unique_ptr<security_state::VisibleSecurityState> + visible_security_state = delegate_->GetVisibleSecurityState(); // Don't show any text in the security indicator for sites on the billing // interstitial list. - if (security_info.malicious_content_status == + if (visible_security_state->malicious_content_status == security_state::MALICIOUS_CONTENT_STATUS_BILLING) { #if defined(OS_IOS) // On iOS, we never expect this status, because there are no billing @@ -235,8 +234,9 @@ return SecureChipText(base::string16()); } - bool fails_malware_check = security_info.malicious_content_status != - security_state::MALICIOUS_CONTENT_STATUS_NONE; + bool fails_malware_check = + visible_security_state->malicious_content_status != + security_state::MALICIOUS_CONTENT_STATUS_NONE; return SecureChipText(l10n_util::GetStringUTF16( fails_malware_check ? IDS_DANGEROUS_VERBOSE_STATE : IDS_NOT_SECURE_VERBOSE_STATE));
diff --git a/components/omnibox/browser/location_bar_model_impl_unittest.cc b/components/omnibox/browser/location_bar_model_impl_unittest.cc index 2f987f4..3c0ab686 100644 --- a/components/omnibox/browser/location_bar_model_impl_unittest.cc +++ b/components/omnibox/browser/location_bar_model_impl_unittest.cc
@@ -21,8 +21,11 @@ void SetShouldPreventElision(bool should_prevent_elision) { should_prevent_elision_ = should_prevent_elision; } - void SetSecurityInfo(const security_state::SecurityInfo& info) { - security_info_ = info; + void SetSecurityLevel(security_state::SecurityLevel level) { + security_level_ = level; + } + void SetVisibleSecurityStateConnectionInfoUninitialized() { + connection_info_initialized_ = false; } // LocationBarModelDelegate: @@ -39,8 +42,16 @@ bool ShouldPreventElision() const override { return should_prevent_elision_; } - void GetSecurityInfo(security_state::SecurityInfo* result) const override { - *result = security_info_; + security_state::SecurityLevel GetSecurityLevel() const override { + return security_level_; + } + + std::unique_ptr<security_state::VisibleSecurityState> + GetVisibleSecurityState() const override { + std::unique_ptr<security_state::VisibleSecurityState> state = + std::make_unique<security_state::VisibleSecurityState>(); + state->connection_info_initialized = connection_info_initialized_; + return state; } AutocompleteClassifier* GetAutocompleteClassifier() override { @@ -53,9 +64,10 @@ private: GURL url_; - security_state::SecurityInfo security_info_; + security_state::SecurityLevel security_level_; TestOmniboxClient omnibox_client_; bool should_prevent_elision_ = false; + bool connection_info_initialized_ = true; }; class LocationBarModelImplTest : public testing::Test { @@ -107,19 +119,13 @@ model()->GetURLForDisplay()); // Verify that query in omnibox is turned off. - security_state::SecurityInfo info; - info.connection_info_initialized = true; - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); EXPECT_FALSE(model()->GetDisplaySearchTerms(nullptr)); } TEST_F(LocationBarModelImplTest, QueryInOmniboxFeatureFlagWorks) { delegate()->SetURL(kValidSearchResultsPage); - security_state::SecurityInfo info; - info.connection_info_initialized = true; - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); EXPECT_FALSE(model()->GetDisplaySearchTerms(nullptr)); @@ -135,30 +141,22 @@ delegate()->SetURL(kValidSearchResultsPage); - security_state::SecurityInfo info; - info.connection_info_initialized = true; - - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); EXPECT_TRUE(model()->GetDisplaySearchTerms(nullptr)); - info.security_level = security_state::SecurityLevel::EV_SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::EV_SECURE); EXPECT_TRUE(model()->GetDisplaySearchTerms(nullptr)); // Insecure levels should not be allowed to display search terms. - info.security_level = security_state::SecurityLevel::NONE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::NONE); EXPECT_FALSE(model()->GetDisplaySearchTerms(nullptr)); - info.security_level = security_state::SecurityLevel::DANGEROUS; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::DANGEROUS); EXPECT_FALSE(model()->GetDisplaySearchTerms(nullptr)); // But ignore the level if the connection info has not been initialized. - info.connection_info_initialized = false; - info.security_level = security_state::SecurityLevel::NONE; - delegate()->SetSecurityInfo(info); + delegate()->SetVisibleSecurityStateConnectionInfoUninitialized(); + delegate()->SetSecurityLevel(security_state::SecurityLevel::NONE); EXPECT_TRUE(model()->GetDisplaySearchTerms(nullptr)); } @@ -166,11 +164,7 @@ QueryInOmniboxDefaultSearchProviderWithAndWithoutQuery) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(omnibox::kQueryInOmnibox); - - security_state::SecurityInfo info; - info.connection_info_initialized = true; - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); delegate()->SetURL(kValidSearchResultsPage); base::string16 result; @@ -192,10 +186,7 @@ const GURL kNonDefaultSearchProvider( "https://search.yahoo.com/search?ei=UTF-8&fr=crmas&p=foo+query"); delegate()->SetURL(kNonDefaultSearchProvider); - security_state::SecurityInfo info; - info.connection_info_initialized = true; - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); base::string16 result; EXPECT_FALSE(model()->GetDisplaySearchTerms(&result)); @@ -206,10 +197,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(omnibox::kQueryInOmnibox); - security_state::SecurityInfo info; - info.connection_info_initialized = true; - info.security_level = security_state::SecurityLevel::SECURE; - delegate()->SetSecurityInfo(info); + delegate()->SetSecurityLevel(security_state::SecurityLevel::SECURE); const GURL kLookalikeURLQuery( "https://www.google.com/search?q=lookalike.com");
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index e983645..b6852b7 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -186,6 +186,7 @@ "//third_party/boringssl", "//third_party/brotli:dec", "//third_party/icu", + "//third_party/inspector_protocol:encoding", "//third_party/libyuv", "//third_party/re2", "//third_party/sqlite", @@ -660,6 +661,8 @@ "devtools/devtools_renderer_channel.h", "devtools/devtools_session.cc", "devtools/devtools_session.h", + "devtools/devtools_session_encoding.cc", + "devtools/devtools_session_encoding.h", "devtools/devtools_stream_blob.cc", "devtools/devtools_stream_blob.h", "devtools/devtools_stream_file.cc",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 1ac6a2d..c964fa6 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -962,8 +962,11 @@ int BrowserMainLoop::PreMainMessageLoopRun() { #if defined(OS_ANDROID) + bool use_display_wide_color_gamut = + GetContentClient()->browser()->GetWideColorGamutHeuristic() == + ContentBrowserClient::WideColorGamutHeuristic::kUseDisplay; // Let screen instance be overridable by parts. - ui::SetScreenAndroid(); + ui::SetScreenAndroid(use_display_wide_color_gamut); #endif if (parts_) {
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index f14e719..2250166 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -129,3 +129,16 @@ "devtools_background_services.proto", ] } + +source_set("inspector_protocol_encoding_test") { + testonly = true + sources = [ + "../../../third_party/inspector_protocol/encoding/encoding_test.cc", + ] + deps = [ + "//base", + "//testing/gmock", + "//testing/gtest", + "//third_party/inspector_protocol:encoding", + ] +}
diff --git a/content/browser/devtools/DEPS b/content/browser/devtools/DEPS index 93bf7150..962e548 100644 --- a/content/browser/devtools/DEPS +++ b/content/browser/devtools/DEPS
@@ -3,4 +3,7 @@ "+content/shell/browser/shell.h", # for access to web contents from devtools_protocol_test_support.cc # V8 version info "+v8/include/v8-version-string.h", + + # For converting between JSON and CBOR in devtools_session_encoding.cc. + "+third_party/inspector_protocol/encoding", ]
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc index 2862801..e491560 100644 --- a/content/browser/devtools/browser_devtools_agent_host.cc +++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -88,7 +88,7 @@ socket_callback_, tethering_task_runner_)); } session->AddHandler(std::make_unique<protocol::TracingHandler>( - nullptr, GetIOContext(), session->client()->UsesBinaryProtocol())); + nullptr, GetIOContext(), session->UsesBinaryProtocol())); return true; }
diff --git a/content/browser/devtools/devtools_session.cc b/content/browser/devtools/devtools_session.cc index 75d2d42..c88086c 100644 --- a/content/browser/devtools/devtools_session.cc +++ b/content/browser/devtools/devtools_session.cc
@@ -4,10 +4,11 @@ #include "content/browser/devtools/devtools_session.h" +#include <vector> + #include "base/bind.h" -#include "base/json/json_reader.h" -#include "base/strings/stringprintf.h" #include "content/browser/devtools/devtools_manager.h" +#include "content/browser/devtools/devtools_session_encoding.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/protocol.h" #include "content/browser/devtools/render_frame_devtools_agent_host.h" @@ -34,7 +35,6 @@ static const char kMethod[] = "method"; static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger"; static const char kSessionId[] = "sessionId"; - } // namespace DevToolsSession::DevToolsSession(DevToolsAgentHostClient* client) @@ -73,6 +73,11 @@ return root_session_ ? root_session_ : this; } +bool DevToolsSession::UsesBinaryProtocol() const { + return client_->UsesBinaryProtocol() || + EnableInternalDevToolsBinaryProtocol(); +} + void DevToolsSession::AddHandler( std::unique_ptr<protocol::DevToolsDomainHandler> handler) { DCHECK(agent_host_); @@ -133,10 +138,27 @@ io_session_ptr_.reset(); } +// The client of the devtools session will call this method to send a message +// to handlers / agents that the session is connected with. bool DevToolsSession::DispatchProtocolMessage(const std::string& message) { + std::string converted_cbor_message; + const std::string* message_to_send = &message; + if (EnableInternalDevToolsBinaryProtocol()) { + if (client_->UsesBinaryProtocol()) { + // If the client uses the binary protocol, then |message| is already + // CBOR (it comes from the client). + DCHECK(IsCBOR(message)); + } else { + converted_cbor_message = ConvertJSONToCBOR(message); + message_to_send = &converted_cbor_message; + } + } if (proxy_delegate_) { - // Note: we assume that child sessions are not forwarding. - proxy_delegate_->SendMessageToBackend(this, message); + // TODO(dgozman): revisit the proxy delegate. + // TODO(johannes): Should we send CBOR to an external backend? Maybe not! + // Revisit this when EnableInternalDevToolsBinaryProtocol() is on + // unconditionally. Note: we assume that child sessions are not forwarding. + proxy_delegate_->SendMessageToBackend(this, *message_to_send); return true; } @@ -146,14 +168,15 @@ std::string session_id; if (!value || !value->getString(kSessionId, &session_id)) - return DispatchProtocolMessageInternal(message, std::move(value)); + return DispatchProtocolMessageInternal(*message_to_send, std::move(value)); auto it = child_sessions_.find(session_id); if (it == child_sessions_.end()) return false; DevToolsSession* session = it->second; DCHECK(!session->proxy_delegate_); - return session->DispatchProtocolMessageInternal(message, std::move(value)); + return session->DispatchProtocolMessageInternal(*message_to_send, + std::move(value)); } bool DevToolsSession::DispatchProtocolMessageInternal( @@ -242,34 +265,73 @@ suspended_messages_.clear(); } +// The following methods handle responses or notifications coming from +// the browser to the client. +static void SendProtocolResponseOrNotification( + DevToolsAgentHostClient* client, + DevToolsAgentHostImpl* agent_host, + std::unique_ptr<protocol::Serializable> message) { + if (!EnableInternalDevToolsBinaryProtocol()) { + bool binary = client->UsesBinaryProtocol(); + client->DispatchProtocolMessage(agent_host, message->serialize(binary)); + return; + } + std::string cbor = message->serialize(/*binary=*/true); + DCHECK(IsCBOR(cbor)); + client->DispatchProtocolMessage(agent_host, client->UsesBinaryProtocol() + ? cbor + : ConvertCBORToJSON(cbor)); +} + void DevToolsSession::sendProtocolResponse( int call_id, std::unique_ptr<protocol::Serializable> message) { - bool binary = client_->UsesBinaryProtocol(); - client_->DispatchProtocolMessage(agent_host_, message->serialize(binary)); + SendProtocolResponseOrNotification(client_, agent_host_, std::move(message)); // |this| may be deleted at this point. } void DevToolsSession::sendProtocolNotification( std::unique_ptr<protocol::Serializable> message) { - bool binary = client_->UsesBinaryProtocol(); - client_->DispatchProtocolMessage(agent_host_, message->serialize(binary)); + SendProtocolResponseOrNotification(client_, agent_host_, std::move(message)); // |this| may be deleted at this point. } void DevToolsSession::flushProtocolNotifications() { } +// The following methods handle responses or notifications coming from +// the renderer (blink) to the client. +static void DispatchProtocolResponseOrNotification( + DevToolsAgentHostClient* client, + DevToolsAgentHostImpl* agent_host, + blink::mojom::DevToolsMessagePtr message) { + // TODO(johannes): When eliminating the + // --enable-internal-devtools-binary-protocol flag, reconsider the similarity + // with SendProtocolResponseOrNotification above and either merge the methods + // or inline them again. + if (!EnableInternalDevToolsBinaryProtocol()) { + client->DispatchProtocolMessage( + agent_host, + std::string(reinterpret_cast<const char*>(message->data.data()), + message->data.size())); + return; + } + std::string cbor(reinterpret_cast<const char*>(message->data.data()), + message->data.size()); + DCHECK(IsCBOR(cbor)); + client->DispatchProtocolMessage(agent_host, client->UsesBinaryProtocol() + ? cbor + : ConvertCBORToJSON(cbor)); +} + void DevToolsSession::DispatchProtocolResponse( blink::mojom::DevToolsMessagePtr message, int call_id, blink::mojom::DevToolsSessionStatePtr updates) { ApplySessionStateUpdates(std::move(updates)); waiting_for_response_messages_.erase(call_id); - client_->DispatchProtocolMessage( - agent_host_, - std::string(reinterpret_cast<const char*>(message->data.data()), - message->data.size())); + DispatchProtocolResponseOrNotification(client_, agent_host_, + std::move(message)); // |this| may be deleted at this point. } @@ -277,10 +339,8 @@ blink::mojom::DevToolsMessagePtr message, blink::mojom::DevToolsSessionStatePtr updates) { ApplySessionStateUpdates(std::move(updates)); - client_->DispatchProtocolMessage( - agent_host_, - std::string(reinterpret_cast<const char*>(message->data.data()), - message->data.size())); + DispatchProtocolResponseOrNotification(client_, agent_host_, + std::move(message)); // |this| may be deleted at this point. }
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h index 413d757..619c96e 100644 --- a/content/browser/devtools/devtools_session.h +++ b/content/browser/devtools/devtools_session.h
@@ -42,6 +42,11 @@ DevToolsAgentHostClient* client() { return client_; } DevToolsSession* GetRootSession(); + // Whether this session uses binary protocol. This is true if + // |client()->UsesBinaryProtocol()| or if the + // --enable-devtools-binary-protocol flag is set. + bool UsesBinaryProtocol() const; + // Browser-only sessions do not talk to mojom::DevToolsAgent, but instead // handle all protocol messages locally in the browser process. void SetBrowserOnly(bool browser_only);
diff --git a/content/browser/devtools/devtools_session_encoding.cc b/content/browser/devtools/devtools_session_encoding.cc new file mode 100644 index 0000000..a297b78e0 --- /dev/null +++ b/content/browser/devtools/devtools_session_encoding.cc
@@ -0,0 +1,94 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/devtools/devtools_session_encoding.h" + +#include <memory> +#include <vector> + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "content/public/common/content_switches.h" +#include "third_party/inspector_protocol/encoding/encoding.h" + +using inspector_protocol_encoding::span; +using inspector_protocol_encoding::Status; +using inspector_protocol_encoding::StreamingParserHandler; +using inspector_protocol_encoding::cbor::NewCBOREncoder; +using inspector_protocol_encoding::cbor::ParseCBOR; +using inspector_protocol_encoding::json::NewJSONEncoder; +using inspector_protocol_encoding::json::ParseJSON; +using inspector_protocol_encoding::json::Platform; + +namespace content { +namespace { +// ContentShellPlatform allows us to inject the string<->double conversion +// routines from base:: into the inspector_protocol JSON parser / serializer. +class ContentShellPlatform : public Platform { + public: + bool StrToD(const char* str, double* result) const override { + return base::StringToDouble(str, result); + } + + // Prints |value| in a format suitable for JSON. + std::unique_ptr<char[]> DToStr(double value) const override { + std::string str = base::NumberToString(value); + std::unique_ptr<char[]> result(new char[str.size() + 1]); + memcpy(result.get(), str.c_str(), str.size() + 1); + return result; + } +}; +} // namespace +bool EnableInternalDevToolsBinaryProtocol() { + static bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableInternalDevToolsBinaryProtocol); + return enabled; +} + +// TODO(johannes): Move this into the cbor library. Don't want to +// do this just yet to first gain more experience about the most +// appropriate API, including how to propagate errors. +std::string ConvertCBORToJSON(const std::string& cbor) { + ContentShellPlatform platform; + std::string json_message; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(&platform, &json_message, &status); + ParseCBOR( + span<uint8_t>(reinterpret_cast<const uint8_t*>(cbor.data()), cbor.size()), + json_writer.get()); + if (!status.ok()) { + LOG(ERROR) << "ConvertCBORToJSON error " + << static_cast<uint32_t>(status.error) << " position " + << static_cast<uint32_t>(status.pos); + return ""; + } + return json_message; +} + +std::string ConvertJSONToCBOR(const std::string& json) { + ContentShellPlatform platform; + std::vector<uint8_t> cbor; + Status status; + std::unique_ptr<StreamingParserHandler> encoder = + NewCBOREncoder(&cbor, &status); + ParseJSON( + &platform, + span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), + encoder.get()); + if (!status.ok()) { + LOG(ERROR) << "ConvertJSONToCBOR error " + << static_cast<uint32_t>(status.error) << " position " + << static_cast<uint32_t>(status.pos); + return ""; + } + return std::string(cbor.begin(), cbor.end()); +} + +bool IsCBOR(const std::string& serialized) { + return serialized.size() >= 6 && + reinterpret_cast<const uint8_t&>(serialized[0]) == 0xd8 && + reinterpret_cast<const uint8_t&>(serialized[1]) == 0x5a; +} +} // namespace content
diff --git a/content/browser/devtools/devtools_session_encoding.h b/content/browser/devtools/devtools_session_encoding.h new file mode 100644 index 0000000..f4bb1ef --- /dev/null +++ b/content/browser/devtools/devtools_session_encoding.h
@@ -0,0 +1,29 @@ +// 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_ + +#include <string> + +namespace content { + +// Whether --enable-internal-devtools-binary-parotocol was passed on the command +// line. If so, the DevtoolsSession will convert all outgoing traffic to agents +// / handlers / etc. to the CBOR-based binary protocol. +bool EnableInternalDevToolsBinaryProtocol(); + +// Conversion routines between the inspector protocol binary wire format +// (based on CBOR RFC 7049) and JSON. +std::string ConvertCBORToJSON(const std::string& cbor); +std::string ConvertJSONToCBOR(const std::string& json); + +// Whether |serialized| is CBOR produced by the inspector protocol. +// We always enclose messages with an envelope, that is, the 0xd8 tag +// followed by the indicator for the byte string, followed by a 32 bit +// length value (4 bytes). +bool IsCBOR(const std::string& serialized); +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_SESSION_ENCODING_H_
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index d88e0a5..b4d72bc 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -306,8 +306,7 @@ session->AddHandler(std::make_unique<protocol::SecurityHandler>()); if (!frame_tree_node_ || !frame_tree_node_->parent()) { session->AddHandler(std::make_unique<protocol::TracingHandler>( - frame_tree_node_, GetIOContext(), - session->client()->UsesBinaryProtocol())); + frame_tree_node_, GetIOContext(), session->UsesBinaryProtocol())); } if (sessions().empty()) {
diff --git a/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/content/browser/frame_host/render_frame_message_filter_browsertest.cc index 1eb2cb7c..a061357 100644 --- a/content/browser/frame_host/render_frame_message_filter_browsertest.cc +++ b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -312,7 +312,7 @@ class WaitingCookieStore : public net::CookieMonster { public: - WaitingCookieStore() : CookieMonster(nullptr, nullptr, nullptr) {} + WaitingCookieStore() : CookieMonster(nullptr, nullptr) {} void GetCookieListWithOptionsAsync(const GURL& url, const net::CookieOptions& options,
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index efc38bbf..81622e8 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -569,6 +569,8 @@ // an otherwise healthy backing store. leveldb::Status RevertSchemaToV2(); + bool is_incognito() const { return !indexed_db_factory_; } + base::WeakPtr<IndexedDBBackingStore> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -579,7 +581,6 @@ friend class base::RefCounted<IndexedDBBackingStore>; virtual ~IndexedDBBackingStore(); - bool is_incognito() const { return !indexed_db_factory_; } leveldb::Status AnyDatabaseContainsBlobs(LevelDBTransaction* transaction, bool* blobs_exist);
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index 1306df4..9013eae 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -92,7 +92,9 @@ failure_class, failure_method, fail_on_instance_num, fail_on_call_num); } - void SimpleTest(const GURL& test_url, bool incognito = false) { + void SimpleTest(const GURL& test_url, + bool incognito = false, + Shell** shell_out = nullptr) { // The test page will perform tests on IndexedDB, then navigate to either // a #pass or #fail ref. Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell(); @@ -109,6 +111,8 @@ &js_result)); FAIL() << "Failed: " << js_result; } + if (shell_out) + *shell_out = the_browser; } void NavigateAndWaitForTitle(Shell* shell, @@ -309,6 +313,21 @@ NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1); } +IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug941965Test) { + // Double-open an incognito window to test that saving & reading a blob from + // indexeddb works. + Shell* incognito_browser = nullptr; + SimpleTest(GetTestUrl("indexeddb", "simple_blob_read.html"), true, + &incognito_browser); + ASSERT_TRUE(incognito_browser); + incognito_browser->Close(); + incognito_browser = nullptr; + SimpleTest(GetTestUrl("indexeddb", "simple_blob_read.html"), true, + &incognito_browser); + ASSERT_TRUE(incognito_browser); + incognito_browser->Close(); +} + class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest { public: IndexedDBBrowserTestWithLowQuota() {}
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index 8dc8432..f994f8cb 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -717,9 +717,14 @@ if (!s.ok()) return {std::move(backing_store), s, data_loss_info, disk_full}; - backing_store = CreateBackingStore(origin, blob_path, std::move(database), - context_->TaskRunner()); - + if (data_directory.empty()) { + backing_store = base::MakeRefCounted<IndexedDBBackingStore>( + nullptr, origin, base::FilePath(), std::move(database), + context_->TaskRunner()); + } else { + backing_store = CreateBackingStore(origin, blob_path, std::move(database), + context_->TaskRunner()); + } bool first_open_since_startup = backends_opened_since_startup_.insert(origin).second; s = backing_store->Initialize(
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc index 6cd3bf72..7f6b1e9 100644 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -386,6 +386,20 @@ loop.Run(); } +TEST_F(IndexedDBFactoryTest, MemoryBackingStoreDetectedAsIncognito) { + base::RunLoop loop; + context()->TaskRunner()->PostTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + auto factory = base::MakeRefCounted<MockIDBFactory>(context()); + const Origin origin1 = Origin::Create(GURL("http://localhost:81")); + auto mem_store1 = + factory->TestOpenBackingStore(origin1, base::FilePath()); + EXPECT_TRUE(mem_store1->is_incognito()); + loop.Quit(); + })); + loop.Run(); +} + TEST_F(IndexedDBFactoryTest, RejectLongOrigins) { base::RunLoop loop; context()->TaskRunner()->PostTask(
diff --git a/content/browser/net/quota_policy_cookie_store.cc b/content/browser/net/quota_policy_cookie_store.cc index 7416a86..bad8555 100644 --- a/content/browser/net/quota_policy_cookie_store.cc +++ b/content/browser/net/quota_policy_cookie_store.cc
@@ -74,8 +74,8 @@ if (config.path.empty()) { // Empty path means in-memory store. - cookie_monster = std::make_unique<net::CookieMonster>( - nullptr /* store */, nullptr /* channel_id_service */, net_log); + cookie_monster = + std::make_unique<net::CookieMonster>(nullptr /* store */, net_log); } else { scoped_refptr<base::SequencedTaskRunner> client_task_runner = config.client_task_runner; @@ -103,8 +103,8 @@ sqlite_store.get(), config.storage_policy.get()); - cookie_monster = std::make_unique<net::CookieMonster>( - persistent_store, config.channel_id_service, net_log); + cookie_monster = + std::make_unique<net::CookieMonster>(persistent_store, net_log); if (config.persist_session_cookies) cookie_monster->SetPersistSessionCookies(true); }
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index e7d260d..fbdbf2d6 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -27,7 +27,6 @@ #include "components/viz/service/surfaces/surface_hittest.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/gpu/compositor_util.h" -#include "content/common/tab_switching_time_callback.h" #include "content/public/common/content_switches.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/skia/include/core/SkColor.h" @@ -93,14 +92,18 @@ void DelegatedFrameHost::WasShown( const viz::LocalSurfaceId& new_local_surface_id, const gfx::Size& new_dip_size, - bool record_presentation_time) { + bool record_presentation_time, + base::TimeTicks tab_switch_start_time) { // Cancel any pending frame eviction and unpause it if paused. frame_eviction_state_ = FrameEvictionState::kNotStarted; frame_evictor_->SetVisible(true); - if (record_presentation_time && compositor_) { + if (record_presentation_time && compositor_ && + !tab_switch_start_time.is_null()) { compositor_->RequestPresentationTimeForNextFrame( - CreateTabSwitchingTimeRecorder(base::TimeTicks::Now())); + tab_switch_time_recorder_.BeginTimeRecording( + tab_switch_start_time, true /* has_saved_frames */, + base::TimeTicks::Now())); } // Use the default deadline to synchronize web content with browser UI.
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index a765488..9accab42 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "components/viz/client/frame_evictor.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" @@ -21,6 +22,7 @@ #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/renderer_host/dip_util.h" #include "content/common/content_export.h" +#include "content/common/tab_switch_time_recorder.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h" #include "ui/compositor/compositor.h" @@ -110,7 +112,8 @@ // TODO(ccameron): Include device scale factor here. void WasShown(const viz::LocalSurfaceId& local_surface_id, const gfx::Size& dip_size, - bool record_presentation_time); + bool record_presentation_time, + base::TimeTicks tab_switch_start_time = base::TimeTicks()); void EmbedSurface(const viz::LocalSurfaceId& local_surface_id, const gfx::Size& dip_size, cc::DeadlinePolicy deadline_policy); @@ -254,6 +257,8 @@ // compositor frame is submitted. std::unique_ptr<ui::Layer> stale_content_layer_; + TabSwitchTimeRecorder tab_switch_time_recorder_; + base::WeakPtrFactory<DelegatedFrameHost> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHost);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 77882c7c2..798c104 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2833,7 +2833,7 @@ if (!SiteInstanceImpl::IsOriginLockASite(lock_url)) return; - GetRendererInterface()->SetIsLockedToSite(lock_url); + GetRendererInterface()->SetIsLockedToSite(); } bool RenderProcessHostImpl::IsForGuestsOnly() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 098fbaa..4e3f74dd 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -792,7 +792,8 @@ observer.RenderWidgetHostVisibilityChanged(this, false); } -void RenderWidgetHostImpl::WasShown(bool record_presentation_time) { +void RenderWidgetHostImpl::WasShown(bool record_presentation_time, + base::TimeTicks tab_switch_start_time) { if (!is_hidden_) return; @@ -810,7 +811,7 @@ Send(new WidgetMsg_WasShown( routing_id_, record_presentation_time ? base::TimeTicks::Now() : base::TimeTicks(), - view_->is_evicted())); + view_->is_evicted(), tab_switch_start_time)); view_->reset_is_evicted(); process_->UpdateClientPriority(this);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 5a73c4db..ce8bfd8 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -308,7 +308,8 @@ // Called to notify the RenderWidget that it has been hidden or restored from // having been hidden. void WasHidden(); - void WasShown(bool record_presentation_time); + void WasShown(bool record_presentation_time, + base::TimeTicks tab_switch_start_time = base::TimeTicks()); #if defined(OS_ANDROID) // Set the importance of widget. The importance is passed onto
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index 1492a21..78ae46d6c 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -688,7 +688,8 @@ std::make_unique<TestImageTransportFactory>()); #endif #if defined(OS_ANDROID) - ui::SetScreenAndroid(); // calls display::Screen::SetScreenInstance(). + // calls display::Screen::SetScreenInstance(). + ui::SetScreenAndroid(false /* use_display_wide_color_gamut */); #endif #if defined(USE_AURA) screen_.reset(aura::TestScreen::Create(gfx::Size()));
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index e605555..b72093a 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -65,9 +65,11 @@ #include "content/public/browser/android/compositor.h" #include "content/public/browser/android/synchronous_compositor_client.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_iterator.h" +#include "content/public/common/content_client.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/use_zoom_for_dsf_policy.h" @@ -2405,8 +2407,11 @@ } void RenderWidgetHostViewAndroid::GetScreenInfo(ScreenInfo* screen_info) const { + bool use_window_wide_color_gamut = + GetContentClient()->browser()->GetWideColorGamutHeuristic() == + ContentBrowserClient::WideColorGamutHeuristic::kUseWindow; auto* window = view_.GetWindowAndroid(); - if (!window) { + if (!window || !use_window_wide_color_gamut) { RenderWidgetHostViewBase::GetScreenInfo(screen_info); return; }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 5ffcf79..71044d1 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -676,11 +676,13 @@ if (!host_->is_hidden()) return; + auto tab_switch_start_time = GetAndResetLastTabChangeStartTime(); bool has_saved_frame = delegated_frame_host_ ? delegated_frame_host_->HasSavedFrame() : false; const bool renderer_should_record_presentation_time = !has_saved_frame; - host()->WasShown(renderer_should_record_presentation_time); + host()->WasShown(renderer_should_record_presentation_time, + tab_switch_start_time); aura::Window* root = window_->GetRootWindow(); if (root) { @@ -696,7 +698,8 @@ const bool record_presentation_time = has_saved_frame; delegated_frame_host_->WasShown( GetLocalSurfaceIdAllocation().local_surface_id(), - window_->bounds().size(), record_presentation_time); + window_->bounds().size(), record_presentation_time, + tab_switch_start_time); } #if defined(OS_WIN)
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index e93471a..be38173 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -817,6 +817,17 @@ return nullptr; } +void RenderWidgetHostViewBase::SetLastTabChangeStartTime( + base::TimeTicks start_time) { + last_tab_switch_start_time_ = start_time; +} + +base::TimeTicks RenderWidgetHostViewBase::GetAndResetLastTabChangeStartTime() { + auto stored_time = last_tab_switch_start_time_; + last_tab_switch_start_time_ = base::TimeTicks(); + return stored_time; +} + #if defined(USE_AURA) void RenderWidgetHostViewBase::EmbedChildFrameRendererWindowTreeClient( RenderWidgetHostViewBase* root_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 104be412..6aa5e70 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -141,6 +141,7 @@ float GetDeviceScaleFactor() const final; TouchSelectionControllerClientManager* GetTouchSelectionControllerClientManager() override; + void SetLastTabChangeStartTime(base::TimeTicks start_time) final; // This only needs to be overridden by RenderWidgetHostViewBase subclasses // that handle content embedded within other RenderWidgetHostViews. @@ -200,6 +201,11 @@ virtual viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties( const cc::RenderFrameMetadata& metadata); + // Returns the time set by SetLastTabChangeStartTime. If this was not + // preceded by a call to SetLastTabChangeStartTime, this will return null. + // Calling this will reset the stored time to null. + base::TimeTicks GetAndResetLastTabChangeStartTime(); + base::WeakPtr<RenderWidgetHostViewBase> GetWeakPtr(); //---------------------------------------------------------------------------- @@ -740,6 +746,11 @@ base::Optional<blink::WebGestureEvent> pending_touchpad_pinch_begin_; + // The last tab switch processing start time. This should only be set and + // retrieved using SetLastTabChangeStartTime and + // GetAndResetLastTabChangeStartTime. + base::TimeTicks last_tab_switch_start_time_; + // True when StopFlingingIfNecessary() calls StopFling(). bool view_stopped_flinging_for_test_ = false;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc index 5340e6c..694b1f1 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -212,7 +212,8 @@ // Hide the frame and make it visible again, to force it to record the // tab-switch time, which is generated from presentation-feedback. child_rwh_impl->WasHidden(); - child_rwh_impl->WasShown(true /* record_presentation_time */); + child_rwh_impl->WasShown(true /* record_presentation_time */, + base::TimeTicks::Now()); // Force the child to submit a new frame. ASSERT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), "document.write('Force a new frame.');"));
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index f6937e3..cb067c0 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -471,8 +471,11 @@ bool has_saved_frame = delegated_frame_host ? delegated_frame_host->HasSavedFrame() : false; + auto tab_switch_start_time = GetAndResetLastTabChangeStartTime(); + const bool renderer_should_record_presentation_time = !has_saved_frame; - host()->WasShown(renderer_should_record_presentation_time); + host()->WasShown(renderer_should_record_presentation_time, + tab_switch_start_time); if (delegated_frame_host) { // If the frame for the renderer is already available, then the @@ -481,7 +484,8 @@ delegated_frame_host->WasShown( browser_compositor_->GetRendererLocalSurfaceIdAllocation() .local_surface_id(), - browser_compositor_->GetRendererSize(), record_presentation_time); + browser_compositor_->GetRendererSize(), record_presentation_time, + tab_switch_start_time); } }
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc index fa59552..0fbce527 100644 --- a/content/browser/service_worker/embedded_worker_test_helper.cc +++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -132,7 +132,7 @@ } void SetSchedulerKeepActive(bool keep_active) override { NOTREACHED(); } void ProcessPurgeAndSuspend() override { NOTREACHED(); } - void SetIsLockedToSite(const GURL& lock_url) override { NOTREACHED(); } + void SetIsLockedToSite() override { NOTREACHED(); } void EnableV8LowMemoryMode() override { NOTREACHED(); } EmbeddedWorkerTestHelper* helper_;
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index 83e4425..6b79a2b9 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -71,13 +71,6 @@ public: WebContentsViewAuraTest() = default; - // Executes the javascript synchronously and makes sure the returned value is - // freed properly. - void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) { - std::unique_ptr<base::Value> value = - content::ExecuteScriptAndGetValue(rfh, jscript); - } - // Starts the test server and navigates to the given url. Sets a large enough // size to the root window. Returns after the navigation to the url is // complete. @@ -115,10 +108,10 @@ EXPECT_EQ(0, index); if (touch_handler) - ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); + content::ExecuteScriptAndGetValue(main_frame, "install_touch_handler()"); - ExecuteSyncJSFunction(main_frame, "navigate_next()"); - ExecuteSyncJSFunction(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); ASSERT_TRUE(value->GetAsInteger(&index)); EXPECT_EQ(2, index); @@ -323,7 +316,7 @@ ASSERT_TRUE(value->GetAsInteger(&index)); EXPECT_EQ(0, index); - ExecuteSyncJSFunction(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); ASSERT_TRUE(value->GetAsInteger(&index)); EXPECT_EQ(1, index); @@ -400,9 +393,9 @@ ui::ScopedAnimationDurationScaleMode::FAST_DURATION); // Make sure the page has both back/forward history. - ExecuteSyncJSFunction(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); EXPECT_EQ(1, GetCurrentIndex()); - ExecuteSyncJSFunction(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); EXPECT_EQ(2, GetCurrentIndex()); web_contents->GetController().GoBack(); EXPECT_EQ(1, GetCurrentIndex()); @@ -485,7 +478,8 @@ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); - ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); + content::ExecuteScriptAndGetValue(web_contents->GetMainFrame(), + "navigate_next()"); EXPECT_EQ(1, GetCurrentIndex()); aura::Window* content = web_contents->GetContentNativeView(); @@ -505,7 +499,8 @@ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); - ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); + content::ExecuteScriptAndGetValue(web_contents->GetMainFrame(), + "navigate_next()"); EXPECT_EQ(1, GetCurrentIndex()); aura::Window* content = web_contents->GetContentNativeView(); @@ -540,11 +535,11 @@ static_cast<WebContentsImpl*>(shell()->web_contents()); NavigationController& controller = web_contents->GetController(); RenderFrameHost* main_frame = web_contents->GetMainFrame(); - ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); + content::ExecuteScriptAndGetValue(main_frame, "install_touch_handler()"); // Navigate twice, then navigate back in history once. - ExecuteSyncJSFunction(main_frame, "navigate_next()"); - ExecuteSyncJSFunction(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); + content::ExecuteScriptAndGetValue(main_frame, "navigate_next()"); EXPECT_EQ(2, GetCurrentIndex()); EXPECT_TRUE(controller.CanGoBack()); EXPECT_FALSE(controller.CanGoForward()); @@ -630,16 +625,17 @@ gfx::Rect bounds = content->GetBoundsInRootWindow(); const int dx = 20; - ExecuteSyncJSFunction(web_contents->GetMainFrame(), - "install_touchmove_handler()"); + content::ExecuteScriptAndGetValue(web_contents->GetMainFrame(), + "install_touchmove_handler()"); WaitAFrame(); for (int navigated = 0; navigated <= 1; ++navigated) { if (navigated) { - ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); - ExecuteSyncJSFunction(web_contents->GetMainFrame(), - "reset_touchmove_count()"); + content::ExecuteScriptAndGetValue(web_contents->GetMainFrame(), + "navigate_next()"); + content::ExecuteScriptAndGetValue(web_contents->GetMainFrame(), + "reset_touchmove_count()"); } InputEventAckWaiter touch_start_waiter( GetRenderWidgetHost(),
diff --git a/content/browser/webrtc/webrtc_video_capture_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_browsertest.cc index 9e38210..a9eb78c 100644 --- a/content/browser/webrtc/webrtc_video_capture_browsertest.cc +++ b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
@@ -22,16 +22,6 @@ namespace content { -#if defined(OS_ANDROID) -// Mojo video capture is currently not supported on Android -// TODO(chfremer): Enable as soon as https://crbug.com/720500 is resolved. -#define MAYBE_RecoverFromCrashInVideoCaptureProcess \ - DISABLED_RecoverFromCrashInVideoCaptureProcess -#else -#define MAYBE_RecoverFromCrashInVideoCaptureProcess \ - RecoverFromCrashInVideoCaptureProcess -#endif // defined(OS_ANDROID) - namespace { static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html"; @@ -63,6 +53,7 @@ void SetUp() override { ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); EnablePixelOutput(); + embedded_test_server()->StartAcceptingConnections(); ContentBrowserTest::SetUp(); } @@ -73,8 +64,12 @@ }; IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureBrowserTest, - MAYBE_RecoverFromCrashInVideoCaptureProcess) { - embedded_test_server()->StartAcceptingConnections(); + RecoverFromCrashInVideoCaptureProcess) { + // This test only makes sense if the video capture service runs in a + // separate process. + if (!features::IsVideoCaptureServiceEnabledForOutOfProcess()) + return; + GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile)); NavigateToURL(shell(), url);
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 573ac8a..b2edd8c 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -234,8 +234,8 @@ "skia_utils.h", "swapped_out_messages.cc", "swapped_out_messages.h", - "tab_switching_time_callback.cc", - "tab_switching_time_callback.h", + "tab_switch_time_recorder.cc", + "tab_switch_time_recorder.h", "task_scheduler.cc", "task_scheduler.h", "text_input_client_messages.h",
diff --git a/content/common/origin_util.cc b/content/common/origin_util.cc index 422c62e2..5869274 100644 --- a/content/common/origin_util.cc +++ b/content/common/origin_util.cc
@@ -9,43 +9,31 @@ #include "base/stl_util.h" #include "base/strings/pattern.h" #include "content/common/url_schemes.h" -#include "net/base/url_util.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "url/gurl.h" #include "url/url_util.h" -namespace { - -// This function partially reflects the result from SecurityOrigin::isUnique, -// not its actual implementation. It takes into account how -// SecurityOrigin::create might return unique origins for URLs whose schemes are -// included in SchemeRegistry::shouldTreatURLSchemeAsNoAccess. -bool IsOriginUnique(const url::Origin& origin) { - return origin.opaque() || - base::ContainsValue(url::GetNoAccessSchemes(), origin.scheme()); -} - -} // namespace - namespace content { bool IsOriginSecure(const GURL& url) { - if (url.SchemeIsCryptographic() || url.SchemeIsFile()) + // TODO(lukasza): data: URLs (and opaque origins associated with them) should + // be considered insecure according to + // https://www.w3.org/TR/powerful-features/#is-url-trustworthy. + // Unfortunately, changing this behavior of content::IsOriginSecure breaks + // quite a few tests for now (e.g. considering data: insecure makes us think + // that https + data = mixed content), so fixing this is postponed to a + // follow-up CL. WIP CL @ https://crrev.com/c/1505897. + if (url.SchemeIs(url::kDataScheme)) return true; - if (url.SchemeIsFileSystem() && url.inner_url() && - IsOriginSecure(*url.inner_url())) { - return true; - } + // TODO(lukasza): trustworthiness of blob: URLs should depend on their inner + // origin (just as it does for filesystem: URLs). Changing this behavior of + // content::IsOriginSecure breaks some tests, so fixing this is postponed to a + // follow-up CL. WIP CL @ https://crrev.com/c/1506941. + if (url.SchemeIs(url::kBlobScheme)) + return false; - if (net::IsLocalhost(url)) - return true; - - if (base::ContainsValue(url::GetSecureSchemes(), url.scheme())) - return true; - - return network::IsAllowlistedAsSecureOrigin( - url::Origin::Create(url), network::GetSecureOriginAllowlist()); + return network::IsUrlPotentiallyTrustworthy(url); } bool OriginCanAccessServiceWorkers(const GURL& url) { @@ -60,22 +48,7 @@ } bool IsPotentiallyTrustworthyOrigin(const url::Origin& origin) { - // Note: Considering this mirrors SecurityOrigin::isPotentiallyTrustworthy, it - // assumes m_isUniqueOriginPotentiallyTrustworthy is set to false. This - // implementation follows Blink's default behavior but in the renderer it can - // be changed per instance by calls to - // SecurityOrigin::setUniqueOriginIsPotentiallyTrustworthy. - if (IsOriginUnique(origin)) - return false; - - if (base::ContainsValue(url::GetSecureSchemes(), origin.scheme()) || - base::ContainsValue(url::GetLocalSchemes(), origin.scheme()) || - net::IsLocalhost(origin.GetURL())) { - return true; - } - - return network::IsAllowlistedAsSecureOrigin( - origin, network::GetSecureOriginAllowlist()); + return network::IsOriginPotentiallyTrustworthy(origin); } } // namespace content
diff --git a/content/common/origin_util_unittest.cc b/content/common/origin_util_unittest.cc index 3c2328b..365b937b 100644 --- a/content/common/origin_util_unittest.cc +++ b/content/common/origin_util_unittest.cc
@@ -8,7 +8,7 @@ namespace content { -TEST(URLSchemesTest, IsOriginSecure) { +TEST(OriginUtilTest, IsOriginSecure) { EXPECT_TRUE(IsOriginSecure(GURL("file:///test/fun.html"))); EXPECT_TRUE(IsOriginSecure(GURL("file:///test/"))); @@ -45,6 +45,42 @@ EXPECT_TRUE(IsOriginSecure(GURL("filesystem:ftp://127.0.0.1/temporary/"))); EXPECT_TRUE( IsOriginSecure(GURL("filesystem:https://www.example.com/temporary/"))); + + EXPECT_TRUE(IsOriginSecure(GURL("about:blank"))); + EXPECT_TRUE(IsOriginSecure(GURL("about:blank#ref"))); + EXPECT_TRUE(IsOriginSecure(GURL("about:srcdoc"))); + + EXPECT_FALSE(IsOriginSecure(GURL("javascript:alert('blah')"))); + + // TODO(lukasza): data: URLs (and opaque origins associated with them) should + // be considered insecure according to + // https://www.w3.org/TR/powerful-features/#is-url-trustworthy. + // Unfortunately, changing the behavior of content::IsOriginSecure breaks + // quite a few tests for now (e.g. considering data: insecure makes us think + // that https + data = mixed content). + EXPECT_TRUE(IsOriginSecure(GURL("data:test/plain;blah"))); + + // TODO(lukasza): trustworthiness of blob: URLs should depend on their inner + // origin (just as it does for filesystem: URLs). Changing this behavior of + // content::IsOriginSecure breaks some tests, so fixing this is postponed to a + // follow-up CL. + EXPECT_FALSE( + IsOriginSecure(GURL("blob:https://www.example.com/guid-goes-here"))); +} + +TEST(OriginUtilTest, IsPotentiallyTrustworthyOrigin) { + EXPECT_FALSE( + IsPotentiallyTrustworthyOrigin(url::Origin::Create(GURL("about:blank")))); + EXPECT_FALSE(IsPotentiallyTrustworthyOrigin( + url::Origin::Create(GURL("about:blank#ref")))); + EXPECT_FALSE(IsPotentiallyTrustworthyOrigin( + url::Origin::Create(GURL("about:srcdoc")))); + + EXPECT_FALSE(IsPotentiallyTrustworthyOrigin( + url::Origin::Create(GURL("javascript:alert('blah')")))); + + EXPECT_FALSE(IsPotentiallyTrustworthyOrigin( + url::Origin::Create(GURL("data:test/plain;blah")))); } } // namespace content
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 8bb126ba..2796abe 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -15,7 +15,6 @@ import "third_party/blink/public/mojom/service_worker/embedded_worker.mojom"; import "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; -import "url/mojom/url.mojom"; struct CreateViewParams { // Renderer-wide preferences. @@ -268,9 +267,7 @@ // Tells the renderer process that it has been locked to a site (i.e., a // scheme plus eTLD+1, such as https://google.com), or to a more specific // origin. - // TODO(nasko): Remove |lock_url| after we've gathered enough information to - // debug issues with browser-side security checks. https://crbug.com/931895. - SetIsLockedToSite(url.mojom.Url lock_url); + SetIsLockedToSite(); // Tells the renderer to enable V8's memory saving mode when possible. // This is only used when site-per-process is enabled. If the process
diff --git a/content/common/tab_switch_time_recorder.cc b/content/common/tab_switch_time_recorder.cc new file mode 100644 index 0000000..c404d4d --- /dev/null +++ b/content/common/tab_switch_time_recorder.cc
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/tab_switch_time_recorder.h" + +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/metrics/histogram_macros.h" +#include "base/trace_event/trace_event.h" +#include "ui/gfx/presentation_feedback.h" + +namespace content { + +TabSwitchTimeRecorder::TabSwitchTimeRecorder() : weak_ptr_factory_(this) {} + +TabSwitchTimeRecorder::~TabSwitchTimeRecorder() {} + +base::OnceCallback<void(const gfx::PresentationFeedback&)> +TabSwitchTimeRecorder::BeginTimeRecording( + const base::TimeTicks tab_switch_start_time, + bool has_saved_frames, + const base::TimeTicks render_widget_visibility_request_timestamp) { + TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency", + TRACE_ID_LOCAL(this)); + + // Reset all previously generated callbacks to enforce matching + // BeginTimeRecording and DidPresentFrame calls. The reason to do this is + // because sometimes, we could generate the callback on a tab switch, but no + // frame submission occurs, potentially causing wrong metric to be uploaded on + // the next tab switch. See crbug.com/936858 for more detail. + weak_ptr_factory_.InvalidateWeakPtrs(); + if (tab_switch_start_time.is_null()) + return base::DoNothing(); + else + return base::BindOnce(&TabSwitchTimeRecorder::DidPresentFrame, GetWeakPtr(), + has_saved_frames, tab_switch_start_time, + render_widget_visibility_request_timestamp); +} + +void TabSwitchTimeRecorder::DidPresentFrame( + bool has_saved_frames, + base::TimeTicks tab_switch_start_time, + base::TimeTicks render_widget_visibility_request_timestamp, + const gfx::PresentationFeedback& feedback) { + const auto delta = feedback.timestamp - tab_switch_start_time; + + if (has_saved_frames) { + UMA_HISTOGRAM_TIMES("Browser.Tabs.TotalSwitchDuration.WithSavedFrames", + delta); + } else { + UMA_HISTOGRAM_TIMES("Browser.Tabs.TotalSwitchDuration.NoSavedFrames", + delta); + } + + if (!render_widget_visibility_request_timestamp.is_null()) { + TRACE_EVENT_ASYNC_END1("latency", "TabSwitching::Latency", + TRACE_ID_LOCAL(this), "latency", + delta.InMillisecondsF()); + UMA_HISTOGRAM_TIMES( + "MPArch.RWH_TabSwitchPaintDuration", + feedback.timestamp - render_widget_visibility_request_timestamp); + } +} + +} // namespace content
diff --git a/content/common/tab_switch_time_recorder.h b/content/common/tab_switch_time_recorder.h new file mode 100644 index 0000000..e5cf3a1 --- /dev/null +++ b/content/common/tab_switch_time_recorder.h
@@ -0,0 +1,55 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_TAB_SWITCH_TIME_RECORDER_H_ +#define CONTENT_COMMON_TAB_SWITCH_TIME_RECORDER_H_ + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "content/common/content_export.h" + +namespace gfx { +struct PresentationFeedback; +} + +namespace content { + +// Generates UMA metric to track the duration of tab switching from when the +// active tab is changed until the frame presentation time. The metric will be +// separated into two whether the tab switch has saved frames or not. +class CONTENT_EXPORT TabSwitchTimeRecorder { + public: + TabSwitchTimeRecorder(); + ~TabSwitchTimeRecorder(); + + // Begin recording time, ends when DidPresentFrame is called. Returns a + // matching callback to end the time recording that will call DidPresentFrame. + base::OnceCallback<void(const gfx::PresentationFeedback&)> BeginTimeRecording( + const base::TimeTicks tab_switch_start_time, + bool has_saved_frames, + const base::TimeTicks render_widget_visibility_request_timestamp = + base::TimeTicks()); + + private: + // End the time recording, and upload the result to histogram if it has a + // correct matching BeginTimeRecording preceding this call. + void DidPresentFrame( + bool has_saved_frame, + base::TimeTicks tab_switch_start_time, + base::TimeTicks render_widget_visibility_request_timestamp, + const gfx::PresentationFeedback& feedback); + + base::WeakPtr<TabSwitchTimeRecorder> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + base::WeakPtrFactory<TabSwitchTimeRecorder> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(TabSwitchTimeRecorder); +}; + +} // namespace content + +#endif // CONTENT_COMMON_TAB_SWITCH_TIME_RECORDER_H_
diff --git a/content/common/tab_switch_time_recorder_unittest.cc b/content/common/tab_switch_time_recorder_unittest.cc new file mode 100644 index 0000000..8f03eba --- /dev/null +++ b/content/common/tab_switch_time_recorder_unittest.cc
@@ -0,0 +1,104 @@ +// Copyright 2019 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 <utility> + +#include "base/test/metrics/histogram_tester.h" +#include "content/common/tab_switch_time_recorder.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/presentation_feedback.h" + +namespace content { + +class TabSwitchTimeRecorderTest : public testing::Test { + public: + ~TabSwitchTimeRecorderTest() override {} + + void SetUp() override { + EXPECT_EQ( + histogram_tester + .GetAllSamples("Browser.Tabs.TotalSwitchDuration.WithSavedFrames") + .size(), + 0ULL); + EXPECT_EQ( + histogram_tester + .GetAllSamples("Browser.Tabs.TotalSwitchDuration.NoSavedFrames") + .size(), + 0ULL); + } + + protected: + size_t GetHistogramSampleSize(bool has_saved_frames) { + if (has_saved_frames) { + return histogram_tester + .GetAllSamples("Browser.Tabs.TotalSwitchDuration.WithSavedFrames") + .size(); + } else { + return histogram_tester + .GetAllSamples("Browser.Tabs.TotalSwitchDuration.NoSavedFrames") + .size(); + } + } + + TabSwitchTimeRecorder tab_switch_time_recorder_; + base::HistogramTester histogram_tester; +}; + +// Time is properly recorded to histogram when we have saved frames and if we +// have a proper matching BeginTimeRecording and callback execution. +TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedWithSavedFrames) { + const auto start = base::TimeTicks::Now(); + auto callback = tab_switch_time_recorder_.BeginTimeRecording( + start, true /* has_saved_frames */); + const auto end = base::TimeTicks::Now(); + auto presentation_feedback = gfx::PresentationFeedback( + end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion); + std::move(callback).Run(presentation_feedback); + EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 1ULL); + EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 0ULL); +} + +// Time is properly recorded to histogram when we have no saved frame and if we +// have a proper matching BeginTimeRecording and callback execution. +TEST_F(TabSwitchTimeRecorderTest, TimeIsRecordedNoSavedFrame) { + const auto start = base::TimeTicks::Now(); + auto callback = tab_switch_time_recorder_.BeginTimeRecording( + start, false /* has_saved_frames */); + const auto end = base::TimeTicks::Now(); + auto presentation_feedback = gfx::PresentationFeedback( + end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion); + std::move(callback).Run(presentation_feedback); + EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL); + EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 1ULL); +} + +// Two consecutive calls to BeginTimeRecording will invalidate the first +// returned callback. +TEST_F(TabSwitchTimeRecorderTest, InvalidateCallback) { + const auto start1 = base::TimeTicks::Now(); + auto callback1 = tab_switch_time_recorder_.BeginTimeRecording( + start1, false /* has_saved_frames */); + + const auto start2 = base::TimeTicks::Now(); + auto callback2 = tab_switch_time_recorder_.BeginTimeRecording( + start2, false /* has_saved_frames */); + + // callback1 should be invalid. Running it should not upload anything to + // histogram. + const auto end = base::TimeTicks::Now(); + auto presentation_feedback1 = gfx::PresentationFeedback( + end, end - start1, gfx::PresentationFeedback::Flags::kHWCompletion); + std::move(callback1).Run(presentation_feedback1); + EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL); + EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 0ULL); + + // callback2 should still be valid. + auto presentation_feedback2 = gfx::PresentationFeedback( + end, end - start2, gfx::PresentationFeedback::Flags::kHWCompletion); + std::move(callback2).Run(presentation_feedback2); + EXPECT_EQ(GetHistogramSampleSize(true /* has_saved_frames */), 0ULL); + EXPECT_EQ(GetHistogramSampleSize(false /* has_saved_frames */), 1ULL); +} + +} // namespace content
diff --git a/content/common/tab_switching_time_callback.cc b/content/common/tab_switching_time_callback.cc deleted file mode 100644 index b15c4950..0000000 --- a/content/common/tab_switching_time_callback.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/common/tab_switching_time_callback.h" - -#include "base/bind.h" -#include "base/metrics/histogram_macros.h" -#include "base/trace_event/trace_event.h" -#include "ui/gfx/presentation_feedback.h" - -namespace content { - -base::OnceCallback<void(const gfx::PresentationFeedback&)> -CreateTabSwitchingTimeRecorder(base::TimeTicks request_time) { - static uint32_t trace_id = 0; - TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency", - TRACE_ID_LOCAL(trace_id)); - return base::BindOnce( - [](base::TimeTicks request_timestamp, uint32_t trace_id, - const gfx::PresentationFeedback& feedback) { - const auto delta = feedback.timestamp - request_timestamp; - UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta); - TRACE_EVENT_ASYNC_END1("latency", "TabSwitching::Latency", - TRACE_ID_LOCAL(trace_id), "latency", - delta.InMillisecondsF()); - }, - request_time, trace_id); - ++trace_id; -} - -} // namespace content
diff --git a/content/common/tab_switching_time_callback.h b/content/common/tab_switching_time_callback.h deleted file mode 100644 index 913e5cb..0000000 --- a/content/common/tab_switching_time_callback.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_COMMON_TAB_SWITCHING_TIME_CALLBACK_H_ -#define CONTENT_COMMON_TAB_SWITCHING_TIME_CALLBACK_H_ - -#include "base/callback_forward.h" -#include "base/time/time.h" - -namespace gfx { -struct PresentationFeedback; -} - -namespace content { - -base::OnceCallback<void(const gfx::PresentationFeedback&)> -CreateTabSwitchingTimeRecorder(base::TimeTicks request_time); - -} // namespace content - -#endif // CONTENT_COMMON_TAB_SWITCHING_TIME_CALLBACK_H_
diff --git a/content/common/throttling_url_loader_unittest.cc b/content/common/throttling_url_loader_unittest.cc index f8507ff..3a589e4 100644 --- a/content/common/throttling_url_loader_unittest.cc +++ b/content/common/throttling_url_loader_unittest.cc
@@ -503,6 +503,40 @@ EXPECT_EQ(1u, throttle_->will_redirect_request_called()); } +// Regression test for crbug.com/933538 +TEST_F(ThrottlingURLLoaderTest, ModifyURLAndDeferRedirect) { + throttle_->set_modify_url_in_will_start(GURL("http://example.org/foo")); + throttle_->set_will_start_request_callback( + base::BindRepeating([](URLLoaderThrottle::Delegate* /* delegate */, + bool* defer) { *defer = true; })); + throttle_->set_will_redirect_request_callback(base::BindRepeating( + [](URLLoaderThrottle::Delegate* /* delegate */, bool* defer, + std::vector<std::string>* /* removed_headers */, + net::HttpRequestHeaders* /* modified_headers */) { *defer = true; })); + + CreateLoaderAndStart(); + + EXPECT_EQ(1u, throttle_->will_start_request_called()); + EXPECT_EQ(0u, throttle_->will_redirect_request_called()); + + throttle_->delegate()->Resume(); + + EXPECT_EQ(1u, throttle_->will_start_request_called()); + EXPECT_EQ(1u, throttle_->will_redirect_request_called()); + EXPECT_EQ(0u, client_.on_received_redirect_called()); + + throttle_->delegate()->Resume(); + + EXPECT_EQ(1u, throttle_->will_start_request_called()); + EXPECT_EQ(1u, throttle_->will_redirect_request_called()); + EXPECT_EQ(0u, throttle_->before_will_process_response_called()); + EXPECT_EQ(0u, throttle_->will_process_response_called()); + EXPECT_EQ(0u, factory_.create_loader_and_start_called()); + EXPECT_EQ(0u, client_.on_received_response_called()); + EXPECT_EQ(1u, client_.on_received_redirect_called()); + EXPECT_EQ(0u, client_.on_complete_called()); +} + TEST_F(ThrottlingURLLoaderTest, CancelBeforeRedirect) { throttle_->set_will_redirect_request_callback(base::BindRepeating( [](URLLoaderThrottle::Delegate* delegate, bool* /* defer */,
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h index 8895b6f..84f6662a 100644 --- a/content/common/widget_messages.h +++ b/content/common/widget_messages.h
@@ -156,9 +156,10 @@ IPC_MESSAGE_ROUTED0(WidgetMsg_WasHidden) // Tells the render view that it is no longer hidden (see WasHidden). -IPC_MESSAGE_ROUTED2(WidgetMsg_WasShown, +IPC_MESSAGE_ROUTED3(WidgetMsg_WasShown, base::TimeTicks /* show_request_timestamp */, - bool /* was_evicted */) + bool /* was_evicted */, + base::TimeTicks /* tab_switch_start_time */) // Activate/deactivate the RenderWidget (i.e., set its controls' tint // accordingly, etc.).
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java index af36aed..1ec506c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
@@ -5,7 +5,6 @@ package org.chromium.content.browser; import android.content.Context; -import android.os.Handler; import android.os.StrictMode; import android.support.annotation.IntDef; @@ -373,7 +372,7 @@ // Queue the callbacks to run. Since running the callbacks clears the list it is safe to call // this more than once. private void enqueueCallbackExecution(final int startupFailure) { - new Handler().post(new Runnable() { + PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, new Runnable() { @Override public void run() { executeEnqueuedCallbacks(startupFailure); @@ -382,7 +381,7 @@ } private void postStartupCompleted(final StartupCallback callback) { - new Handler().post(new Runnable() { + PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, new Runnable() { @Override public void run() { if (mStartupSuccess) {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 48d7499..2f68bc4e 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -975,4 +975,11 @@ return BrowserAccessibilityState::GetInstance()->GetAccessibilityMode(); } +#if defined(OS_ANDROID) +ContentBrowserClient::WideColorGamutHeuristic +ContentBrowserClient::GetWideColorGamutHeuristic() const { + return WideColorGamutHeuristic::kNone; +} +#endif + } // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index a657403..81583161 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1529,6 +1529,18 @@ // Returns the default accessibility mode for the given browser context. virtual ui::AXMode GetAXModeForBrowserContext( BrowserContext* browser_context); + +#if defined(OS_ANDROID) + // Defines the heuristics we can use to enable wide color gamut (WCG). + enum class WideColorGamutHeuristic { + kUseDisplay, // Use WCG if display supports it. + kUseWindow, // Use WCG if window is WCG. + kNone, // Never use WCG. + }; + + // Returns kNone by default. + virtual WideColorGamutHeuristic GetWideColorGamutHeuristic() const; +#endif }; } // namespace content
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h index d02f832..300222fd 100644 --- a/content/public/browser/render_widget_host_view.h +++ b/content/public/browser/render_widget_host_view.h
@@ -260,6 +260,10 @@ // Indicates that this view should show the contents of |view| if it doesn't // have anything to show. virtual void TakeFallbackContentFrom(RenderWidgetHostView* view) = 0; + + // Set the last time a tab change starts to be processed for this + // RenderWidgetHostView. Will overwrite any previously stored value. + virtual void SetLastTabChangeStartTime(base::TimeTicks start_time) = 0; }; } // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 17465e8..13f529dd 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -5,10 +5,6 @@ #include "content/public/common/content_features.h" #include "build/build_config.h" -#if defined(OS_CHROMEOS) -#include "media/capture/video/chromeos/public/cros_features.h" -#endif - namespace features { // All features in alphabetical order. @@ -772,12 +768,11 @@ if (!ShouldEnableVideoCaptureService()) return VideoCaptureServiceConfiguration::kDisabled; -#if defined(OS_ANDROID) +// On ChromeOS the service must run in the browser process, because parts of the +// code depend on global objects that are only available in the Browser process. +// See https://crbug.com/891961. +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) return VideoCaptureServiceConfiguration::kEnabledForBrowserProcess; -#elif defined(OS_CHROMEOS) - return media::ShouldUseCrosCameraService() - ? VideoCaptureServiceConfiguration::kEnabledForBrowserProcess - : VideoCaptureServiceConfiguration::kEnabledForOutOfProcess; #else return base::FeatureList::IsEnabled( features::kRunVideoCaptureServiceInBrowserProcess)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index a6e748b..6f34b5b 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -220,6 +220,12 @@ // the use of persistent gpu memory buffers. const char kDisablePartialRaster[] = "disable-partial-raster"; +// Internally (in devtools_session.cc) switches the protocol to binary format +// (CBOR). This setting is temporary; we plan to remove it after transition to +// binary is sufficiently complete (2019-04-01). +const char kEnableInternalDevToolsBinaryProtocol[] = + "enable-internal-devtools-binary-protocol"; + // Enable partial raster in the renderer. const char kEnablePartialRaster[] = "enable-partial-raster";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index b298c312..69ad632 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -75,6 +75,7 @@ CONTENT_EXPORT extern const char kDisableNotifications[]; CONTENT_EXPORT extern const char kDisableOriginTrialControlledBlinkFeatures[]; CONTENT_EXPORT extern const char kDisablePartialRaster[]; +CONTENT_EXPORT extern const char kEnableInternalDevToolsBinaryProtocol[]; CONTENT_EXPORT extern const char kEnablePartialRaster[]; extern const char kDisablePepper3d[]; CONTENT_EXPORT extern const char kDisablePepper3DImageChromium[];
diff --git a/content/public/common/origin_util.h b/content/public/common/origin_util.h index bb4a389a..8f2a8a3 100644 --- a/content/public/common/origin_util.h +++ b/content/public/common/origin_util.h
@@ -21,6 +21,9 @@ // Note that this is not equivalent to checking if an entire site is secure // (i.e. no degraded security state UI is displayed to the user), since there // may be insecure iframes present even if this method returns true. +// +// TODO(lukasza): Remove this function and use +// network::IsUrlPotentiallyTrustworthy instead. bool CONTENT_EXPORT IsOriginSecure(const GURL& url); // Returns true if the origin can register a service worker. Scheme must be @@ -29,6 +32,9 @@ // This is based on SecurityOrigin::isPotentiallyTrustworthy and tries to mimic // its behavior. +// +// TODO(lukasza): Remove this function and use +// network::IsOriginPotentiallyTrustworthy instead. bool CONTENT_EXPORT IsPotentiallyTrustworthyOrigin(const url::Origin& origin); } // namespace content
diff --git a/content/public/test/web_test_support.h b/content/public/test/web_test_support.h index 282725e7..0d76b43e 100644 --- a/content/public/test/web_test_support.h +++ b/content/public/test/web_test_support.h
@@ -56,11 +56,6 @@ // Turn a renderer into web test mode. void EnableRendererWebTestMode(); -// "Casts" |render_view| to |WebViewTestProxy|. Caller has to ensure that -// prior to construction of |render_view|, EnableWebTestProxyCreation was -// called. -test_runner::WebViewTestProxy* GetWebViewTestProxy(RenderView* render_view); - // Gets WebWidgetTestProxy associated with |frame| (either the view's widget // or the local root's frame widget). Caller has to ensure that prior to // construction of |render_frame|, EnableWebTestProxyCreation was called.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1741f151..18749bd4 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -6038,48 +6038,11 @@ DCHECK(!(was_within_same_document && interface_params)); UpdateStateForCommit(item, commit_type, transition); - auto params = MakeDidCommitProvisionalLoadParams(commit_type, transition); - - // If this is a regular commit, not an error page, the URL that was just - // committed must match the process lock, if there is one. Verify it here, to - // get a stack trace for a bug where this seems to be occurring. - // TODO(nasko): Remove this check after we've gathered enough information to - // debug issues with browser-side security checks. https://crbug.com/931895. - RenderThreadImpl* render_thread = RenderThreadImpl::current(); - const GURL* lock_url = - render_thread ? render_thread->site_lock_url() : nullptr; - if (frame_->GetDocumentLoader()->ErrorCode() != net::ERR_BLOCKED_BY_CLIENT && - lock_url && lock_url->scheme() == params->url.scheme() && - lock_url->SchemeIsHTTPOrHTTPS()) { - std::string lock_domain = - net::registry_controlled_domains::GetDomainAndRegistry( - lock_url->host(), - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - std::string commit_domain = - net::registry_controlled_domains::GetDomainAndRegistry( - params->url.host(), - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - if (lock_domain != commit_domain) { - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( - "lock_domain", base::debug::CrashKeySize::Size64), - lock_domain); - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( - "commit_domain", base::debug::CrashKeySize::Size64), - commit_domain); - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( - "is_subframe", base::debug::CrashKeySize::Size32), - is_main_frame_ ? "true" : "false"); - CHECK(false); - } - } - // This invocation must precede any calls to allowScripts(), allowImages(), or // allowPlugins() for the new page. This ensures that when these functions // send ViewHostMsg_ContentBlocked messages, those arrive after the browser // process has already been informed of the provisional load committing. + auto params = MakeDidCommitProvisionalLoadParams(commit_type, transition); if (was_within_same_document) { GetFrameHost()->DidCommitSameDocumentNavigation(std::move(params)); } else {
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc index 70ad855..a4bb697 100644 --- a/content/renderer/render_frame_impl_browsertest.cc +++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -228,8 +228,9 @@ TEST_F(RenderFrameImplTest, FrameWasShown) { RenderFrameTestObserver observer(frame()); - WidgetMsg_WasShown was_shown_message(0, base::TimeTicks(), - false /* was_evicted */); + WidgetMsg_WasShown was_shown_message( + 0, base::TimeTicks(), false /* was_evicted */, + base::TimeTicks() /* tab_switch_start_time */); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden()); @@ -266,8 +267,9 @@ RenderFrameTestObserver observer(grandchild); - WidgetMsg_WasShown was_shown_message(0, base::TimeTicks(), - false /* was_evicted */); + WidgetMsg_WasShown was_shown_message( + 0, base::TimeTicks(), false /* was_evicted */, + base::TimeTicks() /* tab_switch_start_time */); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden());
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index c33da733..c899a26 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1711,10 +1711,9 @@ base::TimeDelta::FromMinutes(90)); } -void RenderThreadImpl::SetIsLockedToSite(const GURL& lock_url) { +void RenderThreadImpl::SetIsLockedToSite() { DCHECK(blink_platform_impl_); blink_platform_impl_->SetIsLockedToSite(); - site_lock_url_ = std::make_unique<GURL>(lock_url); } void RenderThreadImpl::EnableV8LowMemoryMode() {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 11d7639..afa96183 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -494,10 +494,6 @@ video_frame_compositor_task_runner_ = task_runner; } - // TODO(nasko): Remove after we've gathered enough information to debug issues - // with browser-side security checks. https://crbug.com/931895. - const GURL* site_lock_url() { return site_lock_url_.get(); } - private: friend class RenderThreadImplBrowserTest; @@ -555,7 +551,7 @@ void SetProcessState(mojom::RenderProcessState process_state) override; void SetSchedulerKeepActive(bool keep_active) override; void ProcessPurgeAndSuspend() override; - void SetIsLockedToSite(const GURL& lock_url) override; + void SetIsLockedToSite() override; void EnableV8LowMemoryMode() override; void OnMemoryPressure( @@ -756,11 +752,6 @@ mojo::Binding<viz::mojom::CompositingModeWatcher> compositing_mode_watcher_binding_; - // TODO(nasko): Temporary diagnostic member, holding the site URL this process - // is locked to. Remove after we've gathered enough information to - // debug issues with browser-side security checks. https://crbug.com/931895. - std::unique_ptr<GURL> site_lock_url_; - base::WeakPtrFactory<RenderThreadImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index ca5e59c..7b063b1 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1080,10 +1080,6 @@ return frame_widget_; } -blink::WebWidgetClient* RenderViewImpl::GetWebWidgetClientForWidget() { - return WidgetClient(); -} - bool RenderViewImpl::RenderWidgetWillHandleMouseEventForWidget( const blink::WebMouseEvent& event) { // If the mouse is locked, only the current owner of the mouse lock can
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 4b18b2f..9e388f03 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -395,7 +395,6 @@ // RenderWidgetDelegate implementation ---------------------------------- blink::WebWidget* GetWebWidgetForWidget() const override; - blink::WebWidgetClient* GetWebWidgetClientForWidget() override; bool RenderWidgetWillHandleMouseEventForWidget( const blink::WebMouseEvent& event) override; void SetActiveForWidget(bool active) override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index fe8a598..0f18c93 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -43,7 +43,6 @@ #include "content/common/render_frame_metadata.mojom.h" #include "content/common/render_message_filter.mojom.h" #include "content/common/swapped_out_messages.h" -#include "content/common/tab_switching_time_callback.h" #include "content/common/text_input_state.h" #include "content/common/widget_messages.h" #include "content/public/common/content_client.h" @@ -939,7 +938,8 @@ } void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp, - bool was_evicted) { + bool was_evicted, + base::TimeTicks tab_switch_start_time) { // A frozen main frame widget does not become shown, since it has no frame // associated with it. It must be thawed before changing visibility. DCHECK(!is_frozen_); @@ -952,7 +952,9 @@ SetHidden(false); if (!show_request_timestamp.is_null()) { layer_tree_view_->layer_tree_host()->RequestPresentationTimeForNextFrame( - CreateTabSwitchingTimeRecorder(show_request_timestamp)); + tab_switch_time_recorder_.BeginTimeRecording( + tab_switch_start_time, false /* has_saved_frames */, + show_request_timestamp)); } for (auto& observer : render_frames_) @@ -1007,11 +1009,7 @@ } void RenderWidget::SetNeedsMainFrame() { - // The WebWidgetClient is not |this| if tests override it for the WebView and - // WebViewClient. - blink::WebWidgetClient* client = - delegate() ? delegate()->GetWebWidgetClientForWidget() : this; - client->ScheduleAnimation(); + ScheduleAnimation(); } scoped_refptr<MainThreadEventQueue> RenderWidget::GetInputEventQueue() { @@ -1219,8 +1217,8 @@ CHECK(!for_child_local_root_frame_ && !delegate_); } // This call is not needed in single thread mode for tests without a - // scheduler, but they need to override the WebWidgetClient and replace this - // method in order to schedule a synchronous composite task themselves. + // scheduler, but they override this method in order to schedule a synchronous + // composite task themselves. layer_tree_view_->SetNeedsBeginFrame(); }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 8d55faf..d79f871 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -34,6 +34,7 @@ #include "content/common/cursors/webcursor.h" #include "content/common/drag_event_source_info.h" #include "content/common/edit_command.h" +#include "content/common/tab_switch_time_recorder.h" #include "content/common/widget.mojom.h" #include "content/public/common/drop_data.h" #include "content/public/common/screen_info.h" @@ -705,7 +706,9 @@ void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params); void OnDisableDeviceEmulation(); void OnWasHidden(); - void OnWasShown(base::TimeTicks show_request_timestamp, bool was_evicted); + void OnWasShown(base::TimeTicks show_request_timestamp, + bool was_evicted, + base::TimeTicks tab_switch_start_time); void OnCreateVideoAck(int32_t video_id); void OnUpdateVideoAck(int32_t video_id); void OnRequestSetBoundsAck(); @@ -1093,6 +1096,9 @@ bool first_update_visual_state_after_hidden_; base::TimeTicks was_shown_time_; + // Object to record tab switch time into this RenderWidget + TabSwitchTimeRecorder tab_switch_time_recorder_; + // Whether or not Blink's viewport size should be shrunk by the height of the // URL-bar. bool browser_controls_shrink_blink_size_ = false;
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h index 12293e9..9e70d3e2 100644 --- a/content/renderer/render_widget_delegate.h +++ b/content/renderer/render_widget_delegate.h
@@ -29,10 +29,6 @@ // and RenderWidget will fall back to its own WebWidget. virtual blink::WebWidget* GetWebWidgetForWidget() const = 0; - // Returns the WebWidgetClient being provided from the delegate. Usually this - // is the RenderWidget itself, but tests can override and change it. - virtual blink::WebWidgetClient* GetWebWidgetClientForWidget() = 0; - // As in RenderWidgetInputHandlerDelegate. Return true if the event was // handled. virtual bool RenderWidgetWillHandleMouseEventForWidget(
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 16be558..d0008a82 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -518,9 +518,6 @@ class StubRenderWidgetDelegate : public RenderWidgetDelegate { public: blink::WebWidget* GetWebWidgetForWidget() const override { return nullptr; } - blink::WebWidgetClient* GetWebWidgetClientForWidget() override { - return nullptr; - } bool RenderWidgetWillHandleMouseEventForWidget( const blink::WebMouseEvent& event) override { return false;
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc index 3d2b7ee..ee210da 100644 --- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc +++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -30,7 +30,6 @@ #include "content/shell/test_runner/web_frame_test_proxy.h" #include "content/shell/test_runner/web_test_interfaces.h" #include "content/shell/test_runner/web_test_runner.h" -#include "content/shell/test_runner/web_view_test_proxy.h" #include "media/base/audio_latency.h" #include "media/base/mime_util.h" #include "media/media_buildflags.h" @@ -77,12 +76,6 @@ void WebTestContentRendererClient::RenderViewCreated(RenderView* render_view) { new ShellRenderViewObserver(render_view); - // TODO(https://crbug.com/545684): Does this function need to exist? Can - // this all just be in the CreateWebViewTestProxy() or does - // RenderViewCreated() get manually invoked by the test runner? - test_runner::WebViewTestProxy* proxy = GetWebViewTestProxy(render_view); - proxy->Reset(); - BlinkTestRunner* test_runner = BlinkTestRunner::Get(render_view); test_runner->Reset(false /* for_new_test */); }
diff --git a/content/shell/test_runner/web_test_delegate.h b/content/shell/test_runner/web_test_delegate.h index 8b9a30b..7eb368e 100644 --- a/content/shell/test_runner/web_test_delegate.h +++ b/content/shell/test_runner/web_test_delegate.h
@@ -43,6 +43,8 @@ class WebTestDelegate { public: + virtual ~WebTestDelegate() = default; + // Set and clear the edit command to execute on the next call to // WebViewClient::handleCurrentKeyboardEvent(). virtual void ClearEditCommand() = 0; @@ -253,9 +255,6 @@ // Forces a text input state update for the client of WebFrameWidget // associated with |frame|. virtual void ForceTextInputStateUpdate(blink::WebLocalFrame* frame) = 0; - - protected: - virtual ~WebTestDelegate() {} }; } // namespace test_runner
diff --git a/content/shell/test_runner/web_view_test_proxy.cc b/content/shell/test_runner/web_view_test_proxy.cc index 3039b3b..2c3eefc0 100644 --- a/content/shell/test_runner/web_view_test_proxy.cc +++ b/content/shell/test_runner/web_view_test_proxy.cc
@@ -24,8 +24,8 @@ namespace test_runner { void WebViewTestProxy::Initialize(WebTestInterfaces* interfaces, - WebTestDelegate* delegate) { - delegate_ = delegate; + std::unique_ptr<WebTestDelegate> delegate) { + delegate_ = std::move(delegate); test_interfaces_ = interfaces->GetTestInterfaces(); test_interfaces()->WindowOpened(this); } @@ -112,10 +112,8 @@ WebViewTestProxy::~WebViewTestProxy() { test_interfaces_->WindowClosed(this); - if (test_interfaces_->GetDelegate() == delegate_) + if (test_interfaces_->GetDelegate() == delegate_.get()) test_interfaces_->SetDelegate(nullptr); - // TODO(https://crbug.com/545684): This delegate seems unnecessarily leaked. - // Make |delegate_| a std::unique_ptr<>? } TestRunner* WebViewTestProxy::GetTestRunner() {
diff --git a/content/shell/test_runner/web_view_test_proxy.h b/content/shell/test_runner/web_view_test_proxy.h index b56bd9c..5ddf1a3 100644 --- a/content/shell/test_runner/web_view_test_proxy.h +++ b/content/shell/test_runner/web_view_test_proxy.h
@@ -67,7 +67,8 @@ template <typename... Args> explicit WebViewTestProxy(Args&&... args) : RenderViewImpl(std::forward<Args>(args)...) {} - void Initialize(WebTestInterfaces* interfaces, WebTestDelegate* delegate); + void Initialize(WebTestInterfaces* interfaces, + std::unique_ptr<WebTestDelegate> delegate); // WebViewClient implementation. blink::WebView* CreateView(blink::WebLocalFrame* creator, @@ -88,7 +89,7 @@ // Exposed for our TestRunner harness. using RenderViewImpl::ApplyPageHidden; - WebTestDelegate* delegate() { return delegate_; } + WebTestDelegate* delegate() { return delegate_.get(); } TestInterfaces* test_interfaces() { return test_interfaces_; } AccessibilityController* accessibility_controller() { return &accessibility_controller_; @@ -107,7 +108,7 @@ TestRunner* GetTestRunner(); TestInterfaces* test_interfaces_ = nullptr; - WebTestDelegate* delegate_ = nullptr; + std::unique_ptr<WebTestDelegate> delegate_; AccessibilityController accessibility_controller_{this}; TextInputController text_input_controller_{this};
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 659dd0c..2380506 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1744,6 +1744,7 @@ "../common/service_manager/service_manager_connection_impl_unittest.cc", "../common/service_worker/service_worker_types_unittest.cc", "../common/service_worker/service_worker_utils_unittest.cc", + "../common/tab_switch_time_recorder_unittest.cc", "../common/throttling_url_loader_unittest.cc", "../common/unique_name_helper_unittest.cc", "../common/webplugininfo_unittest.cc", @@ -1921,6 +1922,7 @@ "//content/browser/background_fetch:background_fetch_proto", "//content/browser/cache_storage:cache_storage_proto", "//content/browser/devtools:devtools_background_services_proto", + "//content/browser/devtools:inspector_protocol_encoding_test", "//content/browser/dom_storage:local_storage_proto", "//content/browser/notifications:notification_proto", "//content/browser/service_worker:service_worker_proto",
diff --git a/content/test/data/indexeddb/simple_blob_read.html b/content/test/data/indexeddb/simple_blob_read.html new file mode 100644 index 0000000..970600f --- /dev/null +++ b/content/test/data/indexeddb/simple_blob_read.html
@@ -0,0 +1,10 @@ +<html> + <head> + <title>IndexedDB simple blob reading test</title> + <script type="text/javascript" src="common.js"></script> + <script type="text/javascript" src="simple_blob_read.js"></script> + </head> + <body onLoad="test()"> + <div id="status">Starting...</div> + </body> +</html>
diff --git a/content/test/data/indexeddb/simple_blob_read.js b/content/test/data/indexeddb/simple_blob_read.js new file mode 100644 index 0000000..e15eba5 --- /dev/null +++ b/content/test/data/indexeddb/simple_blob_read.js
@@ -0,0 +1,68 @@ +// Copyright 2019 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. + +const DB = 'db'; +const STORE = 'store'; +const DATA = 'blob value'; +run(); + +function run() { + Object.assign(indexedDB.open(DB), { + unexpectedErrorCallback, + onupgradeneeded(e) { + debug("Created object store."); + e.target.result.createObjectStore(STORE, { + keyPath: 'id', + }); + }, + onsuccess(e) { + debug("Opened database."); + const idb = /** @type IDBDatabase */ e.target.result; + const op = idb + .transaction(STORE, 'readwrite') + .objectStore(STORE) + .put({ + id: 'foo', + blob: new Blob([DATA]), + }); + op.onerror = onerror; + op.onsuccess = () => { + debug("Wrote blob."); + idb.close(); + setTimeout(verify); + } + }, + }); +} + +function verify(e) { + debug("Reading blob."); + Object.assign(indexedDB.open(DB), { + onerror, + onsuccess(e) { + const idb = /** @type IDBDatabase */ e.target.result; + const op = idb + .transaction(STORE, 'readonly') + .objectStore(STORE) + .get('foo'); + op.onerror = onerror; + op.onsuccess = async e => { + debug("Got blob."); + idb.close(); + const entry = e.target.result; + if (!entry) { + fail('BAD: nothing was written'); + } else { + const text = await ( + await fetch(URL.createObjectURL(entry.blob))).text(); + if (text === DATA) { + done(); + } else { + fail(`BAD: written "${DATA}", got "${text}"`) + } + } + } + }, + }); +} \ No newline at end of file
diff --git a/content/test/data/media/image_capture_test.html b/content/test/data/media/image_capture_test.html index 23cdff3..66e0e12 100644 --- a/content/test/data/media/image_capture_test.html +++ b/content/test/data/media/image_capture_test.html
@@ -21,10 +21,8 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - return capturer.getPhotoCapabilities(); + let imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { // There's nothing to check here since |capabilities| vary per device. @@ -40,10 +38,8 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - return capturer.getPhotoSettings(); + let imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); + return imageCapturer.getPhotoSettings(); }) .then(settings => { // There's nothing to check here since |settings| vary per device. @@ -59,10 +55,8 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - return capturer.takePhoto(); + let imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); + return imageCapturer.takePhoto(); }) .then(blob => { assertTrue(blob.type != undefined); @@ -80,10 +74,8 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - return capturer.takePhoto(); + let imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); + return imageCapturer.takePhoto(); }) .then(blob => { failTest('Expected promise to get rejected but it was fulfilled'); @@ -100,10 +92,8 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - return capturer.grabFrame(); + let imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); + return imageCapturer.grabFrame(); }) .then(imageBitmap => { // On Android, depending on the device orientation, |imageBitmap| might @@ -123,13 +113,10 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - imageCapturer = capturer; + imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); // TODO(mcasas): Before accesing synchronous track APIs we need a delay, // use instead a round trip of capabilities: https://crbug.com/711524. - return capturer.getPhotoCapabilities(); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { imageCapturer.track.getCapabilities(); @@ -147,13 +134,10 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - imageCapturer = capturer; + imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); // TODO(mcasas): Before accesing synchronous track APIs we need a delay, // use instead a round trip of capabilities: https://crbug.com/711524. - return capturer.getPhotoCapabilities(); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { imageCapturer.track.getSettings(); @@ -173,13 +157,10 @@ navigator.mediaDevices.getUserMedia({"video" : CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - imageCapturer = capturer; + imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); // TODO(mcasas): Before accesing synchronous track APIs we need a delay, // use instead a round trip of capabilities: https://crbug.com/711524. - return capturer.getPhotoCapabilities(); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { const trackCapabilities = imageCapturer.track.getCapabilities(); @@ -217,13 +198,10 @@ navigator.mediaDevices.getUserMedia({"video": CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - imageCapturer = capturer; + imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); // TODO(mcasas): Before accesing synchronous track APIs we need a delay, // use instead a round trip of capabilities: https://crbug.com/711524. - return capturer.getPhotoCapabilities(); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { const trackCapabilities = imageCapturer.track.getCapabilities(); @@ -279,13 +257,10 @@ navigator.mediaDevices.getUserMedia({"video": CONSTRAINTS}) .then(stream => { assertEquals('video', stream.getVideoTracks()[0].kind); - return new ImageCapture(stream.getVideoTracks()[0]); - }) - .then(capturer => { - imageCapturer = capturer; + imageCapturer = new ImageCapture(stream.getVideoTracks()[0]); // TODO(mcasas): Before accesing synchronous track APIs we need a delay, // use instead a round trip of capabilities: https://crbug.com/711524. - return capturer.getPhotoCapabilities(); + return imageCapturer.getPhotoCapabilities(); }) .then(capabilities => { const trackCapabilities = imageCapturer.track.getCapabilities();
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 4a757c5..80455c2 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -311,6 +311,19 @@ self.Flaky('deqp/functional/gles3/textureformat/unsized_3d.html', ['win', 'intel', 'd3d11'], bug=614418) + # This is an OpenGL driver bug on Intel platform and it is fixed in + # Intel Driver 25.20.100.6444. + # Case no-over-optimization-on-uniform-array-09 always fail if run + # case biuDepthRange_001_to_002 first. + # Temporarily skip these two cases now because this issue blocks + # WEBGL_video_texture implementation. + self.Skip( + 'conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html', + ['win', 'intel', 'opengl', 'passthrough'], bug=907195) + self.Skip( + 'conformance/uniforms/no-over-optimization-on-uniform-array-09.html', + ['win', 'intel', 'opengl', 'passthrough'], bug=907195) + # It's unfortunate that these suppressions need to be so broad, but it # looks like the D3D11 device can be lost spontaneously on this # configuration while running basically any test.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 0f6bbda4..fb6e43f 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -259,6 +259,19 @@ self.Fail('conformance/rendering/rendering-stencil-large-viewport.html', ['win', 'intel', 'd3d11'], bug=782317) + # This is an OpenGL driver bug on Intel platform and it is fixed in + # Intel Driver 25.20.100.6444. + # Case no-over-optimization-on-uniform-array-09 always fail if run + # case biuDepthRange_001_to_002 first. + # Temporarily skip these two cases now because this issue blocks + # WEBGL_video_texture implementation. + self.Skip( + 'conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html', + ['win', 'intel', 'opengl', 'passthrough'], bug=907195) + self.Skip( + 'conformance/uniforms/no-over-optimization-on-uniform-array-09.html', + ['win', 'intel', 'opengl', 'passthrough'], bug=907195) + # Win7 / Intel failures self.Fail('conformance/textures/misc/' + 'copy-tex-image-and-sub-image-2d.html', @@ -404,6 +417,11 @@ ['win', 'passthrough', 'vulkan'], bug=2708) # ANGLE bug ID self.Fail('conformance/canvas/canvas-test.html', ['win', 'passthrough', 'vulkan'], bug=2929) # ANGLE bug ID + self.Fail('conformance/canvas/' + + 'draw-static-webgl-to-multiple-canvas-test.html', + ['win', 'passthrough', 'vulkan'], bug=2918) # ANGLE bug ID + self.Fail('conformance/canvas/draw-webgl-to-canvas-test.html', + ['win', 'passthrough', 'vulkan'], bug=2918) # ANGLE bug ID self.Fail('conformance/context/' + 'context-attribute-preserve-drawing-buffer.html', ['win', 'passthrough', 'vulkan'], bug=2913) # ANGLE bug ID @@ -489,11 +507,6 @@ ['win', 'passthrough', 'vulkan'], bug=3111) # ANGLE bug ID # Vulkan / Win / NVIDIA / Passthough command decoder - self.Fail('conformance/canvas/' + - 'draw-static-webgl-to-multiple-canvas-test.html', - ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2918) # ANGLE bug ID - self.Fail('conformance/canvas/draw-webgl-to-canvas-test.html', - ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2918) # ANGLE bug ID self.Fail('conformance/canvas/to-data-url-test.html', ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2918) # ANGLE bug ID self.Fail('conformance/context/premultiplyalpha-test.html',
diff --git a/content/test/web_test_support.cc b/content/test/web_test_support.cc index bd92504..f0a0d6a3c 100644 --- a/content/test/web_test_support.cc +++ b/content/test/web_test_support.cc
@@ -90,7 +90,7 @@ auto* render_view_proxy = new test_runner::WebViewTestProxy(compositor_deps, params); - BlinkTestRunner* test_runner = new BlinkTestRunner(render_view_proxy); + auto test_runner = std::make_unique<BlinkTestRunner>(render_view_proxy); // TODO(lukasza): Using the 1st BlinkTestRunner as the main delegate is wrong, // but it is difficult to change because this behavior has been baked for a // long time into test assumptions (i.e. which PrintMessage gets delivered to @@ -98,10 +98,10 @@ static bool first_test_runner = true; if (first_test_runner) { first_test_runner = false; - interfaces->SetDelegate(test_runner); + interfaces->SetDelegate(test_runner.get()); } - render_view_proxy->Initialize(interfaces, test_runner); + render_view_proxy->Initialize(interfaces, std::move(test_runner)); return render_view_proxy; } @@ -151,10 +151,6 @@ } // namespace -test_runner::WebViewTestProxy* GetWebViewTestProxy(RenderView* render_view) { - return static_cast<test_runner::WebViewTestProxy*>(render_view); -} - test_runner::WebWidgetTestProxy* GetWebWidgetTestProxy( blink::WebLocalFrame* frame) { DCHECK(frame);
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 17cf3299..b71a53f 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -563,6 +563,7 @@ "api/declarative/deduping_factory_unittest.cc", "api/declarative/rules_registry_unittest.cc", "api/declarative_net_request/composite_matcher_unittest.cc", + "api/declarative_net_request/file_sequence_helper_unittest.cc", "api/declarative_net_request/flat_ruleset_indexer_unittest.cc", "api/declarative_net_request/indexed_rule_unittest.cc", "api/declarative_net_request/indexed_ruleset_format_version_unittest.cc",
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc index 1dad27d9..60b00d6 100644 --- a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc +++ b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
@@ -19,6 +19,108 @@ namespace extensions { namespace declarative_net_request { +namespace { + +// A class to help in re-indexing multiple rulesets. +class ReindexHelper { + public: + // Starts re-indexing rulesets. Must be called on the extension file task + // runner. + using ReindexCallback = base::OnceCallback<void(LoadRequestData)>; + static void Start(service_manager::Connector* connector, + LoadRequestData data, + ReindexCallback callback) { + auto* helper = new ReindexHelper(std::move(data), std::move(callback)); + helper->Start(connector); + } + + private: + // We manage our own lifetime. + ReindexHelper(LoadRequestData data, ReindexCallback callback) + : data_(std::move(data)), callback_(std::move(callback)) {} + ~ReindexHelper() = default; + + void Start(service_manager::Connector* connector) { + DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); + + base::Token token = base::Token::CreateRandom(); + + // Post tasks to reindex individual rulesets. + bool did_post_task = false; + for (auto& ruleset : data_.rulesets) { + if (ruleset.did_load_successfully()) + continue; + + // Using Unretained is safe since this class manages its own lifetime and + // |this| won't be deleted until the |callback| returns. + auto callback = base::BindOnce(&ReindexHelper::OnReindexCompleted, + base::Unretained(this), &ruleset); + callback_count_++; + did_post_task = true; + ruleset.source().IndexAndPersistRules(connector, token, + std::move(callback)); + } + + // It's possible that the callbacks return synchronously and we are deleted + // at this point. Hence don't use any member variables here. Also, if we + // don't post any task, we'll leak. Ensure that's not the case. + DCHECK(did_post_task); + } + + // Callback invoked when a single ruleset is re-indexed. + void OnReindexCompleted(RulesetInfo* ruleset, + IndexAndPersistRulesResult result) { + DCHECK(ruleset); + + // The checksum of the reindexed ruleset should have been the same as the + // expected checksum obtained from prefs, in all cases except when the + // ruleset version changes. If this is not the case, then there is some + // other issue (like the JSON rules file has been modified from the one used + // during installation or preferences are corrupted). But taking care of + // these is beyond our scope here, so simply signal a failure. + bool reindexing_success = result.success && ruleset->expected_checksum() == + result.ruleset_checksum; + + // In case of updates to the ruleset version, the change of ruleset checksum + // is expected. + if (result.success && + ruleset->load_ruleset_result() == + RulesetMatcher::LoadRulesetResult::kLoadErrorVersionMismatch) { + ruleset->set_new_checksum(result.ruleset_checksum); + + // Also change the |expected_checksum| so that any subsequent load + // succeeds. + ruleset->set_expected_checksum(result.ruleset_checksum); + reindexing_success = true; + } + + ruleset->set_reindexing_successful(reindexing_success); + + // TODO(karandeepb): Update this histogram once we start supporting multiple + // rulesets per extension. + UMA_HISTOGRAM_BOOLEAN( + "Extensions.DeclarativeNetRequest.RulesetReindexSuccessful", + reindexing_success); + + callback_count_--; + DCHECK_GE(callback_count_, 0); + + if (callback_count_ == 0) { + // Our job is done. + std::move(callback_).Run(std::move(data_)); + delete this; + } + } + + LoadRequestData data_; + ReindexCallback callback_; + int callback_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(ReindexHelper); +}; + +} // namespace + RulesetInfo::RulesetInfo(RulesetSource source) : source_(std::move(source)) {} RulesetInfo::~RulesetInfo() = default; RulesetInfo::RulesetInfo(RulesetInfo&&) = default; @@ -48,8 +150,8 @@ load_ruleset_result(), RulesetMatcher::kLoadResultMax); } -LoadRequestData::LoadRequestData(ExtensionId extension_id, RulesetInfo ruleset) - : extension_id(std::move(extension_id)), ruleset(std::move(ruleset)) {} +LoadRequestData::LoadRequestData(ExtensionId extension_id) + : extension_id(std::move(extension_id)) {} LoadRequestData::~LoadRequestData() = default; LoadRequestData::LoadRequestData(LoadRequestData&&) = default; LoadRequestData& LoadRequestData::operator=(LoadRequestData&&) = default; @@ -64,73 +166,49 @@ DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); } -void FileSequenceHelper::LoadRuleset(LoadRequestData load_data, - LoadRulesetUICallback ui_callback) const { +void FileSequenceHelper::LoadRulesets( + LoadRequestData load_data, + LoadRulesetsUICallback ui_callback) const { DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); + DCHECK(!load_data.rulesets.empty()); - load_data.ruleset.CreateVerifiedMatcher(); + bool success = true; + for (auto& ruleset : load_data.rulesets) { + ruleset.CreateVerifiedMatcher(); + success &= ruleset.did_load_successfully(); + } - if (load_data.ruleset.did_load_successfully()) { + if (success) { base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(std::move(ui_callback), std::move(load_data))); return; } - // Clone the RulesetSource before moving |load_data|. - RulesetSource source_copy = load_data.ruleset.source().Clone(); + // Loading one or more rulesets failed. Re-index them. - // Attempt to reindex the extension ruleset. - // Using a weak pointer here is safe since |ruleset_reindexed_callback| will - // be called on this sequence itself. - RulesetSource::IndexAndPersistRulesCallback ruleset_reindexed_callback = - base::BindOnce(&FileSequenceHelper::OnRulesetReindexed, - weak_factory_.GetWeakPtr(), std::move(load_data), - std::move(ui_callback)); - source_copy.IndexAndPersistRules(connector_.get(), - base::nullopt /* decoder_batch_id */, - std::move(ruleset_reindexed_callback)); + // Using a WeakPtr is safe since |reindex_callback| will be called on this + // sequence itself. + auto reindex_callback = + base::BindOnce(&FileSequenceHelper::OnRulesetsReindexed, + weak_factory_.GetWeakPtr(), std::move(ui_callback)); + ReindexHelper::Start(connector_.get(), std::move(load_data), + std::move(reindex_callback)); } -void FileSequenceHelper::OnRulesetReindexed( - LoadRequestData load_data, - LoadRulesetUICallback ui_callback, - IndexAndPersistRulesResult result) const { +void FileSequenceHelper::OnRulesetsReindexed(LoadRulesetsUICallback ui_callback, + LoadRequestData load_data) const { DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); - // Only ruleset which can't be loaded are reindexed. - DCHECK(!load_data.ruleset.did_load_successfully()); - - // The checksum of the reindexed ruleset should have been the same as the - // expected checksum obtained from prefs, in all cases except when the - // ruleset version changes. If this is not the case, then there is some - // other issue (like the JSON rules file has been modified from the one used - // during installation or preferences are corrupted). But taking care of - // these is beyond our scope here, so simply signal a failure. - bool reindexing_success = - result.success && - load_data.ruleset.expected_checksum() == result.ruleset_checksum; - - // In case of updates to the ruleset version, the change of ruleset checksum - // is expected. - if (result.success && - load_data.ruleset.load_ruleset_result() == - RulesetMatcher::LoadRulesetResult::kLoadErrorVersionMismatch) { - load_data.ruleset.set_new_checksum(result.ruleset_checksum); - // Also change the |expected_checksum| so that the subsequent load - // succeeds. - load_data.ruleset.set_expected_checksum(result.ruleset_checksum); - reindexing_success = true; + // Load rulesets for which reindexing succeeded. + for (auto& ruleset : load_data.rulesets) { + if (ruleset.reindexing_successful().value_or(false)) { + // Only rulesets which can't be loaded are re-indexed. + DCHECK(!ruleset.did_load_successfully()); + ruleset.CreateVerifiedMatcher(); + } } - UMA_HISTOGRAM_BOOLEAN( - "Extensions.DeclarativeNetRequest.RulesetReindexSuccessful", - reindexing_success); - - // If the reindexing was successful, try to load the ruleset again. - if (reindexing_success) - load_data.ruleset.CreateVerifiedMatcher(); - // The UI thread will handle success or failure. base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI},
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper.h b/extensions/browser/api/declarative_net_request/file_sequence_helper.h index 3809f874..cf4a2ab1 100644 --- a/extensions/browser/api/declarative_net_request/file_sequence_helper.h +++ b/extensions/browser/api/declarative_net_request/file_sequence_helper.h
@@ -6,6 +6,7 @@ #define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_FILE_SEQUENCE_HELPER_H_ #include <memory> +#include <vector> #include "base/callback_forward.h" #include "base/macros.h" @@ -45,6 +46,12 @@ void set_expected_checksum(int checksum) { expected_checksum_ = checksum; } base::Optional<int> expected_checksum() const { return expected_checksum_; } + // Whether re-indexing of the ruleset was successful. + void set_reindexing_successful(bool val) { reindexing_successful_ = val; } + base::Optional<bool> reindexing_successful() const { + return reindexing_successful_; + } + // Must be called after CreateVerifiedMatcher. RulesetMatcher::LoadRulesetResult load_ruleset_result() const; @@ -71,18 +78,21 @@ // set in case of flatbuffer version mismatch. base::Optional<int> new_checksum_; + // Whether the reindexing of this ruleset was successful. + base::Optional<bool> reindexing_successful_; + DISALLOW_COPY_AND_ASSIGN(RulesetInfo); }; // Helper to pass information related to the ruleset being loaded. struct LoadRequestData { - LoadRequestData(ExtensionId extension_id, RulesetInfo ruleset); + explicit LoadRequestData(ExtensionId extension_id); ~LoadRequestData(); LoadRequestData(LoadRequestData&&); LoadRequestData& operator=(LoadRequestData&&); ExtensionId extension_id; - RulesetInfo ruleset; + std::vector<RulesetInfo> rulesets; private: DISALLOW_COPY_AND_ASSIGN(LoadRequestData); @@ -96,17 +106,16 @@ FileSequenceHelper(); ~FileSequenceHelper(); - // Loads ruleset for |load_data|. Invokes |ui_callback| on the UI thread once + // Loads rulesets for |load_data|. Invokes |ui_callback| on the UI thread once // loading is done. - using LoadRulesetUICallback = base::OnceCallback<void(LoadRequestData)>; - void LoadRuleset(LoadRequestData load_data, - LoadRulesetUICallback ui_callback) const; + using LoadRulesetsUICallback = base::OnceCallback<void(LoadRequestData)>; + void LoadRulesets(LoadRequestData load_data, + LoadRulesetsUICallback ui_callback) const; private: - // Callback invoked when the JSON ruleset is reindexed. - void OnRulesetReindexed(LoadRequestData load_data, - LoadRulesetUICallback ui_callback, - IndexAndPersistRulesResult result) const; + // Callback invoked when the JSON rulesets are reindexed. + void OnRulesetsReindexed(LoadRulesetsUICallback ui_callback, + LoadRequestData load_data) const; const std::unique_ptr<service_manager::Connector> connector_;
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc new file mode 100644 index 0000000..48a3da45 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
@@ -0,0 +1,189 @@ +// Copyright 2019 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 "extensions/browser/api/declarative_net_request/file_sequence_helper.h" + +#include <functional> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "base/run_loop.h" +#include "base/task/post_task.h" +#include "components/crx_file/id_util.h" +#include "components/version_info/version_info.h" +#include "content/public/test/test_service_manager_context.h" +#include "extensions/browser/api/declarative_net_request/ruleset_source.h" +#include "extensions/browser/api/declarative_net_request/test_utils.h" +#include "extensions/browser/api/declarative_net_request/utils.h" +#include "extensions/browser/extension_file_task_runner.h" +#include "extensions/browser/extensions_test.h" +#include "extensions/common/api/declarative_net_request/test_utils.h" +#include "extensions/common/features/feature_channel.h" +#include "services/data_decoder/public/cpp/testing_json_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { +namespace declarative_net_request { +namespace { + +struct LoadRulesetResult { + bool has_new_checksum = false; + base::Optional<bool> reindexing_successful; + RulesetMatcher::LoadRulesetResult load_result = + RulesetMatcher::kLoadResultMax; +}; + +struct TestCase { + explicit TestCase(RulesetSource source) : source(std::move(source)) {} + int checksum; + RulesetSource source; + LoadRulesetResult expected_result; +}; + +class FileSequenceHelperTest : public ExtensionsTest { + public: + FileSequenceHelperTest() : channel_(::version_info::Channel::UNKNOWN) {} + + // ExtensonsTest overrides: + void SetUp() override { + ExtensionsTest::SetUp(); + helper_ = std::make_unique<FileSequenceHelper>(); + } + void TearDown() override { + GetExtensionFileTaskRunner()->DeleteSoon(FROM_HERE, std::move(helper_)); + base::RunLoop().RunUntilIdle(); + ExtensionsTest::TearDown(); + } + + void TestLoadRulesets(const std::vector<TestCase>& test_cases) { + ExtensionId extension_id = crx_file::id_util::GenerateId("dummy_extension"); + + LoadRequestData data(extension_id); + for (const auto& test_case : test_cases) { + data.rulesets.emplace_back(test_case.source.Clone()); + data.rulesets.back().set_expected_checksum(test_case.checksum); + } + + base::RunLoop run_loop; + auto load_ruleset_callback = base::BindOnce( + [](base::RunLoop* run_loop, const std::vector<TestCase>& test_cases, + LoadRequestData data) { + // Verify |data| is as expected. + ASSERT_EQ(data.rulesets.size(), test_cases.size()); + + for (size_t i = 0; i < data.rulesets.size(); i++) { + const RulesetInfo& ruleset = data.rulesets[i]; + const LoadRulesetResult& expected_result = + test_cases[i].expected_result; + + EXPECT_EQ(expected_result.has_new_checksum, + ruleset.new_checksum().has_value()); + EXPECT_EQ(expected_result.reindexing_successful, + ruleset.reindexing_successful()); + EXPECT_EQ(expected_result.load_result, + ruleset.load_ruleset_result()); + } + + run_loop->Quit(); + }, + &run_loop, std::cref(test_cases)); + + // Unretained is safe because |helper_| outlives the |load_ruleset_task|. + auto load_ruleset_task = base::BindOnce( + &FileSequenceHelper::LoadRulesets, base::Unretained(helper_.get()), + std::move(data), std::move(load_ruleset_callback)); + GetExtensionFileTaskRunner()->PostTask(FROM_HERE, + std::move(load_ruleset_task)); + run_loop.Run(); + } + + private: + // Run this on the trunk channel to ensure the API is available. + ScopedCurrentChannel channel_; + + std::unique_ptr<FileSequenceHelper> helper_; + + // Required to use SafeJSONParser for re-indexing. + content::TestServiceManagerContext service_manager_context_; + data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_; + + DISALLOW_COPY_AND_ASSIGN(FileSequenceHelperTest); +}; + +// Tests loading and reindexing multiple rulesets. +TEST_F(FileSequenceHelperTest, MultipleRulesets) { + const int kNumRulesets = 3; + std::vector<TestCase> test_cases; + + // First create |kNumRulesets| indexed rulesets. + for (size_t i = 0; i < kNumRulesets; i++) { + test_cases.emplace_back(CreateTemporarySource()); + + auto& test_case = test_cases.back(); + + std::unique_ptr<RulesetMatcher> matcher; + ASSERT_TRUE(CreateVerifiedMatcher({CreateGenericRule()}, test_case.source, + &matcher, &test_case.checksum)); + + // Initially loading all the rulesets should succeed. + test_case.expected_result.load_result = RulesetMatcher::kLoadSuccess; + } + + TestLoadRulesets(test_cases); + + // Now delete the first and third indexed rulesets. This would cause a + // re-index. + base::DeleteFile(test_cases[0].source.indexed_path(), false /* recursive */); + base::DeleteFile(test_cases[2].source.indexed_path(), false /* recursive */); + test_cases[0].expected_result.reindexing_successful = true; + test_cases[2].expected_result.reindexing_successful = true; + + TestLoadRulesets(test_cases); + + // The files should have been re-indexed. + EXPECT_TRUE(base::PathExists(test_cases[0].source.indexed_path())); + EXPECT_TRUE(base::PathExists(test_cases[2].source.indexed_path())); + + // Reset state. + test_cases[0].expected_result.reindexing_successful = base::nullopt; + test_cases[2].expected_result.reindexing_successful = base::nullopt; + + // Change the expected checksum for rulesets 2 and 3. Loading both of the + // rulesets should now fail due to a checksum mismatch. + test_cases[1].checksum--; + test_cases[2].checksum--; + test_cases[1].expected_result.load_result = + RulesetMatcher::kLoadErrorChecksumMismatch; + test_cases[2].expected_result.load_result = + RulesetMatcher::kLoadErrorChecksumMismatch; + test_cases[1].expected_result.reindexing_successful = false; + test_cases[2].expected_result.reindexing_successful = false; + + TestLoadRulesets(test_cases); + + // Reset checksums. + test_cases[1].checksum++; + test_cases[2].checksum++; + + // Now simulate a flatbuffer version mismatch. + const int kIndexedRulesetFormatVersion = 100; + std::string old_version_header = GetVersionHeaderForTesting(); + SetIndexedRulesetFormatVersionForTesting(kIndexedRulesetFormatVersion); + ASSERT_NE(old_version_header, GetVersionHeaderForTesting()); + + // Version mismatch will cause reindexing and updated checksums. + for (auto& test_case : test_cases) { + test_case.expected_result.reindexing_successful = true; + test_case.expected_result.has_new_checksum = true; + test_case.expected_result.load_result = RulesetMatcher::kLoadSuccess; + } + + TestLoadRulesets(test_cases); +} + +} // namespace +} // namespace declarative_net_request +} // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc index 424d5eae..e1c41ba 100644 --- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc +++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -105,16 +105,16 @@ file_task_runner_->DeleteSoon(FROM_HERE, std::move(file_sequence_helper_)); } - void LoadRuleset( + void LoadRulesets( LoadRequestData load_data, - FileSequenceHelper::LoadRulesetUICallback load_ruleset_callback) const { + FileSequenceHelper::LoadRulesetsUICallback ui_callback) const { // base::Unretained is safe here because we trigger the destruction of // |file_sequence_helper_| on |file_task_runner_| from our destructor. Hence // it is guaranteed to be alive when |load_ruleset_task| is run. base::OnceClosure load_ruleset_task = - base::BindOnce(&FileSequenceHelper::LoadRuleset, + base::BindOnce(&FileSequenceHelper::LoadRulesets, base::Unretained(file_sequence_helper_.get()), - std::move(load_data), std::move(load_ruleset_callback)); + std::move(load_data), std::move(ui_callback)); file_task_runner_->PostTask(FROM_HERE, std::move(load_ruleset_task)); } @@ -167,14 +167,15 @@ RulesetInfo ruleset(RulesetSource::Create(*extension)); ruleset.set_expected_checksum(expected_ruleset_checksum); - LoadRequestData load_data(extension->id(), std::move(ruleset)); + // TODO(crbug.com/930961): Currently we only support a single ruleset per + // extension. + LoadRequestData load_data(extension->id()); + load_data.rulesets.push_back(std::move(ruleset)); - FileSequenceHelper::LoadRulesetUICallback load_ruleset_callback = - base::BindOnce(&RulesMonitorService::OnRulesetLoaded, - weak_factory_.GetWeakPtr()); - - file_sequence_bridge_->LoadRuleset(std::move(load_data), - std::move(load_ruleset_callback)); + auto load_ruleset_callback = base::BindOnce( + &RulesMonitorService::OnRulesetLoaded, weak_factory_.GetWeakPtr()); + file_sequence_bridge_->LoadRulesets(std::move(load_data), + std::move(load_ruleset_callback)); } void RulesMonitorService::OnExtensionUnloaded( @@ -194,10 +195,15 @@ } void RulesMonitorService::OnRulesetLoaded(LoadRequestData load_data) { - // Update the ruleset checksum if needed. - if (load_data.ruleset.new_checksum()) { + // TODO(crbug.com/930961): Currently we only support a single ruleset per + // extension. + DCHECK_EQ(1u, load_data.rulesets.size()); + RulesetInfo& ruleset = load_data.rulesets[0]; + + // Update the ruleset checksums if needed. + if (ruleset.new_checksum()) { prefs_->SetDNRRulesetChecksum(load_data.extension_id, - *load_data.ruleset.new_checksum()); + *(ruleset.new_checksum())); } // It's possible that the extension has been disabled since the initial load @@ -206,7 +212,7 @@ load_data.extension_id)) return; - if (!load_data.ruleset.did_load_successfully()) { + if (!ruleset.did_load_successfully()) { // The ruleset failed to load. Notify the user. warning_service_->AddWarnings( {Warning::CreateRulesetFailedToLoadWarning(load_data.extension_id)}); @@ -217,11 +223,10 @@ for (auto& observer : observers_) observer.OnRulesetLoaded(); - base::OnceClosure load_ruleset_on_io = - base::BindOnce(&LoadRulesetOnIOThread, load_data.extension_id, - load_data.ruleset.TakeMatcher(), - prefs_->GetDNRAllowedPages(load_data.extension_id), - base::RetainedRef(info_map_)); + base::OnceClosure load_ruleset_on_io = base::BindOnce( + &LoadRulesetOnIOThread, load_data.extension_id, ruleset.TakeMatcher(), + prefs_->GetDNRAllowedPages(load_data.extension_id), + base::RetainedRef(info_map_)); base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, std::move(load_ruleset_on_io)); }
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc index c64516f0..0beb4e7 100644 --- a/extensions/browser/url_loader_factory_manager.cc +++ b/extensions/browser/url_loader_factory_manager.cc
@@ -65,22 +65,27 @@ "072D729E856B1F2C9894AEEC3A5DF65E519D6BEE", "07333481B7B8D7F57A9BA64FB98CF86EA87455FC", "086E69ED9071DCB20C93A081A68360963AB09385", + "0CB16BAEE070B7617E9188B387C44964FB705D79", "0EAEA2FDEE025D95B3ABB37014EFF5A98AC4BEAE", "109A37B889E7C8AEA7B0103559C3EB6AF73B7832", "16A81AEA09A67B03F7AEA5B957D24A4095E764BE", "177508B365CBF1610CC2B53707749D79272F2F0B", "1AB9CC404876117F49135E67BAD813F935AAE9BA", + "1CDDF7436E5F891E1D5E37164F7EB992AECA0E2D", "1DB115A4344B58C0B7CC1595662E86C9E92C0848", "1E37F1A19C1C528E616637B105CFC4838ECF52B4", "260871EABEDE6F2D07D0D9450096093EDAFCBF34", "29427534E31BB1820714C7CAEDF9C54B47BE154F", "2AA94E2D3F4DA33F0D3BCF5DD48F69B8BDB26F52", + "2C116B242B7425D359E188AB053B3F88DB78F78D", "2E2D8A405430172AB15ADCC09740F3EEE990D605", "31E6100DC7B4EAB4ABF6CA2A4E191D3945D3C731", "3230014EA01150A27C1887B700E019B27A6DBA08", "3334952C8387B357A41DD8349D39AD9E7C423943", "34FB670464B5F16EF5ABD6CD53E26030E97C26B3", "360D8A88545D0C21CBDE2B55EA9E4E4285282B4C", + "37AC33A3A46D271CCE57DD6CB3FACE6B01F5A347", + "3CD98763C80D86E00CB1C4CAA56CEA8F3B0BA4F1", "3EB17C39F8B6B28FAF34E2406E57A76013A2E066", "3FDD3DB17F3B686F5A05204700ABA13DF20AE957", "41536C3554CD9458EB2F05F1B58CF84BB7BF83BC", @@ -91,26 +96,36 @@ "505F2C1E723731B2C8C9182FEAA73D00525B2048", "50DDD8734521B61564FCE273F8E60547F88BBCBE", "52865B2087D0ABCD195A83DFD4BD041A3B4EBC34", + "52C94AC7680C3A03CCB6EA31445DD42BD0D5CA8E", "58BCF05A42C8ECED4E6D76F51E2E1A64AC4F7E7C", + "5E052881B4847F68CFC8ED1A00C341FC14009C1E", "5F0C47BC039BEDC1B29B68918F75370C292076A6", "61E581B10D83C0AEF8366BB64C18C6615884B3D2", "6357533CAFFB94A9EA5268ED110079E15561E469", + "65C20C06ED10E6F39EED527AC736D87B0390DE70", "67528F9B47BE454EC46809C33D24F2C199BE408D", "6AE81EF3B13B15080A2DDB23A205A24C65CCC10B", "6BA5F75FFF75B69507BC4B09B7094926EF93DBD2", "6E49449D56D031B87835CC767734AF5A064E1A13", + "71CB78C3334D5122E7F23C8525AD24100CDE7D4A", "71EE66C0F71CD89BEE340F8568A44101D4C3A9A7", "77D83E0A4157A0E77B51AD60BAB69A346CD4FEA3", + "7879DB88205D880B64D55E51B9726E1D12F7261F", "7BFE588B209A15260DE12777B4BBB738DE98FE6C", "808FA9BB3CD501D7801D1CD6D5A3DBA088FDD46F", "82FDBBF79F3517C3946BD89EAAF90C46DFDA4681", + "83B6C75264D5D2F81FDEFD681EDD2076DD8F0B9B", "88C372CE52E21560C17BFD52556E60D694E12CAC", "88F5F459139892C0F5DF3022676726BB3F01FB5C", + "89C9B32115F19A18E9BE4906DC59F24A934CB9F0", "89F40D84C0C72C6B02B320716E877FB1671218E9", + "8A0634388BCBB6D073E1C97B14C024396ED32D12", "8CDD303D6C341D9CAB16713C3CD7587B90A7A84A", "8CE6227B4E53DF42FF93B24F49D15EDE31E97E79", "934B8F5753A3E5A276FC7D0EE5E575B335A0CC76", "973E35633030AD27DABEC99609424A61386C7309", + "97E04C5632954E778306CAC40B3F95C470B463B6", + "98EF7B1601119AEE1FCC28EE5CE247DED5676539", "99E06C364BBB2D1F82A9D20BC1645BF21E478259", "A30E526CF62131BFBFD7CD9B56253A8F3F171777", "A3660FA31A0DBF07C9F80D5342FF215DBC962719", @@ -125,11 +140,15 @@ "BF5224FB246A6B67EA986EFF77A43F6C1BCA9672", "C5539F4EBECABA792CC40D03A56144AAD3BF9D19", "C5BCB9E2E47C3F6FD3F7F83ED982872F77852BA7", + "C86D546CA47034163C12DC2C912910C3A12C3B07", + "C940F83135D9612865F4A44391DDDFE3B7BE1393", "CA89BD35059845F2DB4B4398FD339B9F210E9337", "CC74B2408753932B5D49C81EC073E3E4CA766EE6", "CD8AF9C47DDE6327F8D9A3EFA81F34C6B6C26EBB", "CF40F6289951CBFA3B83B792EFA774E2EA06E4C0", "D0537B1BADCE856227CE76E31B3772F6B68F653C", + "D9A97CD75380C697C65D37512E53DBECDFA45FB9", + "DDA21167F058A65D878DF84C3CF3FCC60B053E80", "E178D4F4D6617C0B880C36F192DA3B18422C5064", "E6B12430B6166B31BE20E13941C22569EA75B0F2", "E7036E906DBFB77C46EDDEB003A72C0B5CC9BE7F", @@ -143,7 +162,9 @@ "F59AB261280AB3AE9826D9359507838B90B07431", "F73F9EF0207603992CA3C00A7A0CB223D5571B3F", "F9287A33E15038F2591F23E6E9C486717C7202DD", + "FEE3DC8C722657A4A5B0F72CA48CF950DC956148", "FF0DA4BD87A88469B10709B99E79D4B0E11C0CA6", + "FF8257C73304BA655E10F324C962504BA6691DF2", }; constexpr size_t kHashedExtensionIdLength = base::kSHA1Length * 2;
diff --git a/extensions/common/api/test.json b/extensions/common/api/test.json index 7e046cf3..5772972 100644 --- a/extensions/common/api/test.json +++ b/extensions/common/api/test.json
@@ -61,11 +61,6 @@ "minimum": 0, "maximum": 65535 }, - "nativeCrxBindingsEnabled": { - "type": "boolean", - "optional": true, - "description": "Whether native extension bindings are enabled." - }, "loginStatus": { "type": "object", "optional": true,
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index d29dd5b..d98ea1d 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -110,8 +110,6 @@ "extension_injection_host.h", "extension_js_runner.cc", "extension_js_runner.h", - "extension_port.cc", - "extension_port.h", "extension_throttle_entry.cc", "extension_throttle_entry.h", "extension_throttle_manager.cc", @@ -158,8 +156,6 @@ "injection_host.h", "ipc_message_sender.cc", "ipc_message_sender.h", - "js_renderer_messaging_service.cc", - "js_renderer_messaging_service.h", "lazy_background_page_native_handler.cc", "lazy_background_page_native_handler.h", "logging_native_handler.cc",
diff --git a/extensions/renderer/extension_port.cc b/extensions/renderer/extension_port.cc deleted file mode 100644 index 05cd0e5..0000000 --- a/extensions/renderer/extension_port.cc +++ /dev/null
@@ -1,58 +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. - -#include "extensions/renderer/extension_port.h" - -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/worker_thread.h" -#include "extensions/common/api/messaging/message.h" -#include "extensions/common/api/messaging/port_context.h" -#include "extensions/common/api/messaging/port_id.h" -#include "extensions/common/extension_messages.h" -#include "extensions/renderer/extension_bindings_system.h" -#include "extensions/renderer/ipc_message_sender.h" -#include "extensions/renderer/script_context.h" -#include "extensions/renderer/worker_thread_dispatcher.h" -#include "extensions/renderer/worker_thread_util.h" - -namespace extensions { - -ExtensionPort::ExtensionPort(ScriptContext* script_context, - const PortId& id, - int js_id) - : script_context_(script_context), id_(id), js_id_(js_id) {} - -ExtensionPort::~ExtensionPort() {} - -void ExtensionPort::PostExtensionMessage(std::unique_ptr<Message> message) { - if (worker_thread_util::IsWorkerThread()) { - DCHECK(!script_context_->GetRenderFrame()); - WorkerThreadDispatcher::GetBindingsSystem() - ->GetIPCMessageSender() - ->SendPostMessageToPort(id_, *message); - } else { - content::RenderFrame* render_frame = script_context_->GetRenderFrame(); - if (!render_frame) - return; - render_frame->Send(new ExtensionHostMsg_PostMessage(id_, *message)); - } -} - -void ExtensionPort::Close(bool close_channel) { - if (worker_thread_util::IsWorkerThread()) { - DCHECK(!script_context_->GetRenderFrame()); - WorkerThreadDispatcher::GetBindingsSystem() - ->GetIPCMessageSender() - ->SendCloseMessagePort(MSG_ROUTING_NONE, id_, close_channel); - } else { - content::RenderFrame* render_frame = script_context_->GetRenderFrame(); - if (!render_frame) - return; - render_frame->Send(new ExtensionHostMsg_CloseMessagePort( - PortContext::ForFrame(render_frame->GetRoutingID()), id_, - close_channel)); - } -} - -} // namespace extensions
diff --git a/extensions/renderer/extension_port.h b/extensions/renderer/extension_port.h deleted file mode 100644 index aa584a9..0000000 --- a/extensions/renderer/extension_port.h +++ /dev/null
@@ -1,56 +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 EXTENSIONS_RENDERER_EXTENSION_PORT_H_ -#define EXTENSIONS_RENDERER_EXTENSION_PORT_H_ - -#include <memory> -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "extensions/common/api/messaging/port_id.h" - -namespace extensions { -struct Message; -struct PortId; -class ScriptContext; - -// A class representing information about a specific extension message port that -// handles sending related IPCs to the browser. This consists of a port id and -// a separate js_id which is exposed only to the JavaScript context. -class ExtensionPort { - public: - ExtensionPort(ScriptContext* script_context, const PortId& id, int js_id); - ~ExtensionPort(); - - // Posts a new message to the port. If the port is not initialized, the - // message will be queued until it is. - void PostExtensionMessage(std::unique_ptr<Message> message); - - // Closes the port. If there are pending messages, they will still be sent - // assuming initialization completes (after which, the port will close). - void Close(bool close_channel); - - const PortId& id() const { return id_; } - int js_id() const { return js_id_; } - - private: - // The associated ScriptContext for this port. Since these objects are owned - // by a NativeHandler, this should always be valid. - ScriptContext* script_context_ = nullptr; - - const PortId id_; - - // The id used in the JS bindings. If this is a receiver port, this is not the - // same as the port_number in the PortId. This should be used only as an - // identifier in the JS context this port is from. - int js_id_ = 0; - - DISALLOW_COPY_AND_ASSIGN(ExtensionPort); -}; - -} // namespace extensions - -#endif // EXTENSIONS_RENDERER_EXTENSION_PORT_H_
diff --git a/extensions/renderer/js_renderer_messaging_service.cc b/extensions/renderer/js_renderer_messaging_service.cc deleted file mode 100644 index 21aeabf..0000000 --- a/extensions/renderer/js_renderer_messaging_service.cc +++ /dev/null
@@ -1,189 +0,0 @@ -// 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 "extensions/renderer/js_renderer_messaging_service.h" - -#include <stdint.h> - -#include <string> - -#include "base/stl_util.h" -#include "content/public/common/child_process_host.h" -#include "content/public/renderer/v8_value_converter.h" -#include "extensions/common/api/messaging/message.h" -#include "extensions/common/api/messaging/messaging_endpoint.h" -#include "extensions/common/api/messaging/port_id.h" -#include "extensions/common/extension_messages.h" -#include "extensions/common/manifest_handlers/externally_connectable.h" -#include "extensions/renderer/extension_port.h" -#include "extensions/renderer/messaging_bindings.h" -#include "extensions/renderer/script_context.h" -#include "extensions/renderer/v8_helpers.h" -#include "v8/include/v8.h" - -namespace extensions { - -using v8_helpers::ToV8String; - -JSRendererMessagingService::JSRendererMessagingService( - ExtensionBindingsSystem* bindings_system) - : RendererMessagingService(bindings_system) {} -JSRendererMessagingService::~JSRendererMessagingService() {} - -bool JSRendererMessagingService::ContextHasMessagePort( - ScriptContext* script_context, - const PortId& port_id) { - MessagingBindings* bindings = MessagingBindings::ForContext(script_context); - DCHECK(bindings); - return bindings->GetPortWithId(port_id) != nullptr; -} - -void JSRendererMessagingService::DispatchOnConnectToListeners( - ScriptContext* script_context, - const PortId& target_port_id, - const ExtensionId& target_extension_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo* source, - const ExtensionMsg_ExternalConnectionInfo& info, - const std::string& event_name) { - MessagingBindings* bindings = MessagingBindings::ForContext(script_context); - ExtensionPort* port = bindings->CreateNewPortWithId(target_port_id); - - v8::Isolate* isolate = script_context->isolate(); - v8::HandleScope handle_scope(isolate); - - const std::string& source_url_spec = info.source_url.spec(); - const Extension* extension = script_context->extension(); - - v8::Local<v8::Value> tab = v8::Null(isolate); - v8::Local<v8::Value> tls_channel_id_value = v8::Undefined(isolate); - v8::Local<v8::Value> guest_process_id = v8::Undefined(isolate); - v8::Local<v8::Value> guest_render_frame_routing_id = v8::Undefined(isolate); - - if (extension) { - if (!source->tab.empty() && !extension->is_platform_app()) { - tab = content::V8ValueConverter::Create()->ToV8Value( - &source->tab, script_context->v8_context()); - } - - ExternallyConnectableInfo* externally_connectable = - ExternallyConnectableInfo::Get(extension); - - if (externally_connectable && - externally_connectable->accepts_tls_channel_id) { - tls_channel_id_value = v8::String::Empty(isolate); - } - - if (info.guest_process_id != content::ChildProcessHost::kInvalidUniqueID) { - guest_process_id = v8::Integer::New(isolate, info.guest_process_id); - guest_render_frame_routing_id = - v8::Integer::New(isolate, info.guest_render_frame_routing_id); - } - } - - v8::Local<v8::String> v8_channel_name; - v8::Local<v8::String> v8_source_extension_id; - v8::Local<v8::String> v8_source_native_app_name; - v8::Local<v8::String> v8_target_extension_id; - v8::Local<v8::String> v8_source_url_spec; - if (!ToV8String(isolate, channel_name.c_str(), &v8_channel_name) || - !ToV8String(isolate, - info.source_endpoint.extension_id - ? *info.source_endpoint.extension_id - : ExtensionId(), - &v8_source_extension_id) || - !ToV8String(isolate, - info.source_endpoint.native_app_name - ? *info.source_endpoint.native_app_name - : std::string(), - &v8_source_native_app_name) || - !ToV8String(isolate, target_extension_id.c_str(), - &v8_target_extension_id) || - !ToV8String(isolate, source_url_spec.c_str(), &v8_source_url_spec)) { - NOTREACHED() << "dispatchOnConnect() passed non-string argument"; - return; - } - - v8::Local<v8::Value> arguments[] = { - // portId - v8::Integer::New(isolate, port->js_id()), - // channelName - v8_channel_name, - // sourceTab - tab, - // source_frame_id - v8::Integer::New(isolate, source->frame_id), - // guestProcessId - guest_process_id, - // guestRenderFrameRoutingId - guest_render_frame_routing_id, - // sourceExtensionId - v8_source_extension_id, - // sourceNativeAppName - v8_source_native_app_name, - // targetExtensionId - v8_target_extension_id, - // sourceUrl - v8_source_url_spec, - // tlsChannelId - tls_channel_id_value, - }; - - // Note: this can execute asynchronously if JS is suspended. - script_context->module_system()->CallModuleMethodSafe( - "messaging", "dispatchOnConnect", base::size(arguments), arguments); -} - -void JSRendererMessagingService::DispatchOnMessageToListeners( - ScriptContext* script_context, - const Message& message, - const PortId& target_port_id) { - MessagingBindings* bindings = MessagingBindings::ForContext(script_context); - ExtensionPort* port = bindings->GetPortWithId(target_port_id); - DCHECK(port); - - v8::Isolate* isolate = script_context->isolate(); - v8::HandleScope handle_scope(isolate); - - v8::Local<v8::Value> port_id_handle = - v8::Integer::New(isolate, port->js_id()); - - v8::Local<v8::String> v8_data; - if (!ToV8String(isolate, message.data.c_str(), &v8_data)) - return; - std::vector<v8::Local<v8::Value>> arguments; - arguments.push_back(v8_data); - arguments.push_back(port_id_handle); - - script_context->module_system()->CallModuleMethodSafe( - "messaging", "dispatchOnMessage", &arguments); -} - -void JSRendererMessagingService::DispatchOnDisconnectToListeners( - ScriptContext* script_context, - const PortId& port_id, - const std::string& error_message) { - MessagingBindings* bindings = MessagingBindings::ForContext(script_context); - ExtensionPort* port = bindings->GetPortWithId(port_id); - DCHECK(port); - - v8::Isolate* isolate = script_context->isolate(); - v8::HandleScope handle_scope(isolate); - - std::vector<v8::Local<v8::Value>> arguments; - arguments.push_back(v8::Integer::New(isolate, port->js_id())); - v8::Local<v8::String> v8_error_message; - if (!error_message.empty()) - ToV8String(isolate, error_message.c_str(), &v8_error_message); - if (!v8_error_message.IsEmpty()) { - arguments.push_back(v8_error_message); - } else { - arguments.push_back(v8::Null(isolate)); - } - - script_context->module_system()->CallModuleMethodSafe( - "messaging", "dispatchOnDisconnect", &arguments); -} - -} // namespace extensions
diff --git a/extensions/renderer/js_renderer_messaging_service.h b/extensions/renderer/js_renderer_messaging_service.h deleted file mode 100644 index df10881..0000000 --- a/extensions/renderer/js_renderer_messaging_service.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef EXTENSIONS_RENDERER_JS_RENDERER_MESSAGING_SERVICE_H_ -#define EXTENSIONS_RENDERER_JS_RENDERER_MESSAGING_SERVICE_H_ - -#include <string> - -#include "base/macros.h" -#include "extensions/renderer/renderer_messaging_service.h" - -struct ExtensionMsg_ExternalConnectionInfo; -struct ExtensionMsg_TabConnectionInfo; - -namespace extensions { -struct Message; -struct PortId; - -// The messaging service to handle dispatching extension messages and connection -// events to different contexts. -class JSRendererMessagingService : public RendererMessagingService { - public: - explicit JSRendererMessagingService(ExtensionBindingsSystem* bindings_system); - ~JSRendererMessagingService() override; - - private: - // RendererMessagingService: - bool ContextHasMessagePort(ScriptContext* script_context, - const PortId& port_id) override; - void DispatchOnConnectToListeners( - ScriptContext* script_context, - const PortId& target_port_id, - const ExtensionId& target_extension_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo* source, - const ExtensionMsg_ExternalConnectionInfo& info, - const std::string& event_name) override; - void DispatchOnMessageToListeners(ScriptContext* script_context, - const Message& message, - const PortId& target_port_id) override; - void DispatchOnDisconnectToListeners(ScriptContext* script_context, - const PortId& port_id, - const std::string& error) override; - - DISALLOW_COPY_AND_ASSIGN(JSRendererMessagingService); -}; - -} // namespace extensions - -#endif // EXTENSIONS_RENDERER_JS_RENDERER_MESSAGING_SERVICE_H_
diff --git a/extensions/renderer/messaging_bindings.cc b/extensions/renderer/messaging_bindings.cc index 2f8d03e..6dd256b 100644 --- a/extensions/renderer/messaging_bindings.cc +++ b/extensions/renderer/messaging_bindings.cc
@@ -6,154 +6,26 @@ #include <stdint.h> -#include <map> -#include <string> - #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" #include "base/callback_helpers.h" -#include "base/lazy_instance.h" -#include "base/metrics/histogram_macros.h" -#include "base/values.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/worker_thread.h" -#include "extensions/common/api/messaging/message.h" -#include "extensions/common/api/messaging/messaging_endpoint.h" -#include "extensions/common/api/messaging/port_context.h" -#include "extensions/common/api/messaging/port_id.h" -#include "extensions/common/extension_messages.h" -#include "extensions/renderer/extension_bindings_system.h" -#include "extensions/renderer/extension_frame_helper.h" -#include "extensions/renderer/extension_port.h" #include "extensions/renderer/gc_callback.h" -#include "extensions/renderer/ipc_message_sender.h" -#include "extensions/renderer/message_target.h" -#include "extensions/renderer/messaging_util.h" #include "extensions/renderer/script_context.h" -#include "extensions/renderer/script_context_set.h" -#include "extensions/renderer/v8_helpers.h" -#include "extensions/renderer/worker_thread_dispatcher.h" -#include "extensions/renderer/worker_thread_util.h" -#include "gin/converter.h" -#include "third_party/blink/public/web/web_user_gesture_indicator.h" #include "v8/include/v8.h" -// Message passing API example (in a content script): -// var port = runtime.connect(); -// port.postMessage('Can you hear me now?'); -// port.onmessage.addListener(function(msg, port) { -// alert('response=' + msg); -// port.postMessage('I got your reponse'); -// }); - namespace extensions { -using v8_helpers::ToV8String; - -namespace { - -// A global map between ScriptContext and MessagingBindings. -base::LazyInstance<std::map<ScriptContext*, MessagingBindings*>>:: - DestructorAtExit g_messaging_map = LAZY_INSTANCE_INITIALIZER; - -} // namespace - MessagingBindings::MessagingBindings(ScriptContext* context) - : ObjectBackedNativeHandler(context), - weak_ptr_factory_(this) { - g_messaging_map.Get()[context] = this; -} + : ObjectBackedNativeHandler(context) {} -MessagingBindings::~MessagingBindings() { - g_messaging_map.Get().erase(context()); - if (num_extension_ports_ > 0) { - UMA_HISTOGRAM_COUNTS_1000( - "Extensions.Messaging.ExtensionPortsCreated.Total", next_js_id_); - } -} +MessagingBindings::~MessagingBindings() {} void MessagingBindings::AddRoutes() { - RouteHandlerFunction("CloseChannel", - base::BindRepeating(&MessagingBindings::CloseChannel, - base::Unretained(this))); - RouteHandlerFunction("PostMessage", - base::BindRepeating(&MessagingBindings::PostMessage, - base::Unretained(this))); // TODO(fsamuel, kalman): Move BindToGC out of messaging natives. RouteHandlerFunction("BindToGC", base::BindRepeating(&MessagingBindings::BindToGC, base::Unretained(this))); - RouteHandlerFunction( - "OpenChannelToExtension", "runtime.connect", - base::BindRepeating(&MessagingBindings::OpenChannelToExtension, - base::Unretained(this))); - RouteHandlerFunction( - "OpenChannelToNativeApp", "runtime.connectNative", - base::BindRepeating(&MessagingBindings::OpenChannelToNativeApp, - base::Unretained(this))); - RouteHandlerFunction("OpenChannelToTab", - base::BindRepeating(&MessagingBindings::OpenChannelToTab, - base::Unretained(this))); -} - -// static -MessagingBindings* MessagingBindings::ForContext(ScriptContext* context) { - return g_messaging_map.Get()[context]; -} - -ExtensionPort* MessagingBindings::GetPortWithId(const PortId& id) { - for (const auto& key_value : ports_) { - if (key_value.second->id() == id) - return key_value.second.get(); - } - return nullptr; -} - -ExtensionPort* MessagingBindings::CreateNewPortWithId(const PortId& id) { - int js_id = GetNextJsId(); - auto port = std::make_unique<ExtensionPort>(context(), id, js_id); - return ports_.insert(std::make_pair(js_id, std::move(port))) - .first->second.get(); -} - -void MessagingBindings::PostMessage( - const v8::FunctionCallbackInfo<v8::Value>& args) { - // Arguments are (int32_t port_id, string message). - CHECK(args.Length() == 2); - CHECK(args[0]->IsInt32()); - CHECK(args[1]->IsString()); - - int js_port_id = args[0].As<v8::Int32>()->Value(); - auto iter = ports_.find(js_port_id); - - if (iter == ports_.end()) - return; - - ExtensionPort& port = *iter->second; - - v8::Isolate* isolate = args.GetIsolate(); - std::string error; - std::unique_ptr<Message> message = messaging_util::MessageFromJSONString( - isolate, args[1].As<v8::String>(), &error, context()->web_frame()); - if (!message) { - args.GetReturnValue().Set(gin::StringToV8(isolate, error)); - return; - } - - port.PostExtensionMessage(std::move(message)); -} - -void MessagingBindings::CloseChannel( - const v8::FunctionCallbackInfo<v8::Value>& args) { - // Arguments are (int32_t port_id, bool force_close). - CHECK_EQ(2, args.Length()); - CHECK(args[0]->IsInt32()); - CHECK(args[1]->IsBoolean()); - - int js_port_id = args[0].As<v8::Int32>()->Value(); - bool force_close = args[1].As<v8::Boolean>()->Value(); - ClosePort(js_port_id, force_close); } void MessagingBindings::BindToGC( @@ -162,194 +34,12 @@ CHECK(args[0]->IsObject()); CHECK(args[1]->IsFunction()); CHECK(args[2]->IsInt32()); - int js_port_id = args[2].As<v8::Int32>()->Value(); + // TODO(devlin): Update callers to not pass a port ID. + // int js_port_id = args[2].As<v8::Int32>()->Value(); base::Closure fallback = base::DoNothing(); - if (js_port_id >= 0) { - // TODO(robwu): Falling back to closing the port shouldn't be needed. If - // the script context is destroyed, then the frame has navigated. But that - // is already detected by the browser, so this logic is redundant. Remove - // this fallback (and move BindToGC out of messaging because it is also - // used in other places that have nothing to do with messaging...). - fallback = base::Bind(&MessagingBindings::ClosePort, - weak_ptr_factory_.GetWeakPtr(), js_port_id, - false /* force_close */); - } // Destroys itself when the object is GC'd or context is invalidated. new GCCallback(context(), args[0].As<v8::Object>(), args[1].As<v8::Function>(), fallback); } -void MessagingBindings::OpenChannelToExtension( - const v8::FunctionCallbackInfo<v8::Value>& args) { - content::RenderFrame* render_frame = context()->GetRenderFrame(); - bool is_for_service_worker = false; - if (!render_frame && - !(is_for_service_worker = worker_thread_util::IsWorkerThread())) - return; - - // The Javascript code should validate/fill the arguments. - CHECK_EQ(args.Length(), 3); - CHECK(args[0]->IsString()); - CHECK(args[1]->IsString()); - CHECK(args[2]->IsBoolean()); - - int js_id = GetNextJsId(); - PortId port_id(context()->context_id(), js_id, true); - ports_[js_id] = std::make_unique<ExtensionPort>(context(), port_id, js_id); - - ExtensionMsg_ExternalConnectionInfo info; - - // For messaging APIs, hosted apps should be considered a web page so hide - // its extension ID. - const Extension* extension = context()->extension(); - if (extension && !extension->is_hosted_app()) { - info.source_endpoint = - context()->context_type() == Feature::CONTENT_SCRIPT_CONTEXT - ? MessagingEndpoint::ForContentScript(extension->id()) - : MessagingEndpoint::ForExtension(extension->id()); - } else { - info.source_endpoint = MessagingEndpoint::ForWebPage(); - } - - v8::Isolate* isolate = args.GetIsolate(); - info.target_id = *v8::String::Utf8Value(isolate, args[0]); - - info.source_url = context()->url(); - std::string channel_name = *v8::String::Utf8Value(isolate, args[1]); - - { - SCOPED_UMA_HISTOGRAM_TIMER( - "Extensions.Messaging.SetPortIdTime.Extension"); - if (is_for_service_worker) { - WorkerThreadDispatcher::GetBindingsSystem() - ->GetIPCMessageSender() - ->SendOpenMessageChannel( - context(), port_id, MessageTarget::ForExtension(info.target_id), - channel_name, false /* include_tls_channel_id */); - } else { - render_frame->Send(new ExtensionHostMsg_OpenChannelToExtension( - PortContext::ForFrame(render_frame->GetRoutingID()), info, - channel_name, port_id)); - } - } - - ++num_extension_ports_; - args.GetReturnValue().Set(static_cast<int32_t>(js_id)); -} - -void MessagingBindings::OpenChannelToNativeApp( - const v8::FunctionCallbackInfo<v8::Value>& args) { - // The Javascript code should validate/fill the arguments. - CHECK_EQ(args.Length(), 1); - CHECK(args[0]->IsString()); - // This should be checked by our function routing code. - CHECK(context()->GetAvailability("runtime.connectNative").is_available()); - - content::RenderFrame* render_frame = context()->GetRenderFrame(); - bool is_for_service_worker = false; - if (!render_frame && - !(is_for_service_worker = worker_thread_util::IsWorkerThread())) - return; - - std::string native_app_name = - *v8::String::Utf8Value(args.GetIsolate(), args[0]); - - int js_id = GetNextJsId(); - PortId port_id(context()->context_id(), js_id, true); - ports_[js_id] = std::make_unique<ExtensionPort>(context(), port_id, js_id); - - { - SCOPED_UMA_HISTOGRAM_TIMER( - "Extensions.Messaging.SetPortIdTime.NativeApp"); - if (is_for_service_worker) { - WorkerThreadDispatcher::GetBindingsSystem() - ->GetIPCMessageSender() - ->SendOpenMessageChannel(context(), port_id, - MessageTarget::ForNativeApp(native_app_name), - "", false /* include_tls_channel_id */); - } else { - render_frame->Send(new ExtensionHostMsg_OpenChannelToNativeApp( - PortContext::ForFrame(render_frame->GetRoutingID()), native_app_name, - port_id)); - } - } - - args.GetReturnValue().Set(static_cast<int32_t>(js_id)); -} - -void MessagingBindings::OpenChannelToTab( - const v8::FunctionCallbackInfo<v8::Value>& args) { - content::RenderFrame* render_frame = context()->GetRenderFrame(); - bool is_for_service_worker = false; - if (!render_frame && - !(is_for_service_worker = worker_thread_util::IsWorkerThread())) - return; - - DCHECK_NE(context()->context_type(), Feature::CONTENT_SCRIPT_CONTEXT); - - // tabs_custom_bindings.js unwraps arguments to tabs.connect/sendMessage and - // passes them to OpenChannelToTab, in the following order: - // - |tab_id| - Positive number that specifies the destination of the channel. - // - |frame_id| - Target frame(s) in the tab where onConnect is dispatched: - // -1 for all frames, 0 for the main frame, >0 for a child frame. - // - |extension_id| - ID of the initiating extension. - // - |channel_name| - A user-defined channel name. - CHECK(args.Length() == 4); - CHECK(args[0]->IsInt32()); - CHECK(args[1]->IsInt32()); - CHECK(args[2]->IsString()); - CHECK(args[3]->IsString()); - - int js_id = GetNextJsId(); - PortId port_id(context()->context_id(), js_id, true); - ports_[js_id] = std::make_unique<ExtensionPort>(context(), port_id, js_id); - - ExtensionMsg_TabTargetConnectionInfo info; - info.tab_id = args[0].As<v8::Int32>()->Value(); - info.frame_id = args[1].As<v8::Int32>()->Value(); - // TODO(devlin): Why is this not part of info? - v8::Isolate* isolate = args.GetIsolate(); - std::string extension_id = *v8::String::Utf8Value(isolate, args[2]); - std::string channel_name = *v8::String::Utf8Value(isolate, args[3]); - - if (!is_for_service_worker) { - ExtensionFrameHelper* frame_helper = - ExtensionFrameHelper::Get(render_frame); - DCHECK(frame_helper); - } - - { - SCOPED_UMA_HISTOGRAM_TIMER("Extensions.Messaging.SetPortIdTime.Tab"); - if (is_for_service_worker) { - WorkerThreadDispatcher::GetBindingsSystem() - ->GetIPCMessageSender() - ->SendOpenMessageChannel( - context(), port_id, - MessageTarget::ForTab(info.tab_id, info.frame_id), channel_name, - false /* include_tls_channel_id */); - } else { - render_frame->Send(new ExtensionHostMsg_OpenChannelToTab( - PortContext::ForFrame(render_frame->GetRoutingID()), info, - extension_id, channel_name, port_id)); - } - } - - args.GetReturnValue().Set(static_cast<int32_t>(js_id)); -} - -void MessagingBindings::ClosePort(int js_port_id, bool force_close) { - // TODO(robwu): Merge this logic with CloseChannel once the TODO in BindToGC - // has been addressed. - auto iter = ports_.find(js_port_id); - if (iter != ports_.end()) { - std::unique_ptr<ExtensionPort> port = std::move(iter->second); - ports_.erase(iter); - port->Close(force_close); - } -} - -int MessagingBindings::GetNextJsId() { - return next_js_id_++; -} - } // namespace extensions
diff --git a/extensions/renderer/messaging_bindings.h b/extensions/renderer/messaging_bindings.h index 3a2a599..d6d2ec1 100644 --- a/extensions/renderer/messaging_bindings.h +++ b/extensions/renderer/messaging_bindings.h
@@ -8,15 +8,14 @@ #include <string> #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "extensions/renderer/object_backed_native_handler.h" namespace extensions { -class ExtensionPort; class ScriptContext; -struct PortId; -// Manually implements JavaScript bindings for extension messaging. +// Provides the BindToGC native handler. +// TODO(devlin): Rename this from messaging bindings - it's no longer remotely +// messaging related. class MessagingBindings : public ObjectBackedNativeHandler { public: explicit MessagingBindings(ScriptContext* script_context); @@ -25,59 +24,9 @@ // ObjectBackedNativeHandler: void AddRoutes() override; - // Returns the MessagingBindings associated with the given |context|. - static MessagingBindings* ForContext(ScriptContext* context); - - // Returns an existing port with the given |id|, or null. - ExtensionPort* GetPortWithId(const PortId& id); - - // Creates a new port with the given |id|. MessagingBindings owns the - // returned port. - ExtensionPort* CreateNewPortWithId(const PortId& id); - private: - using PortMap = std::map<int, std::unique_ptr<ExtensionPort>>; - - // JS Exposed Function: Sends a message along the given channel. If an error - // occurs, returns the error, else returns nothing. - void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args); - - // JS Exposed Function: Close a port, optionally forcefully (i.e. close the - // whole channel instead of just the given port). - void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args); - - // JS Exposed Function: Binds |callback| to be invoked *sometime after* - // |object| is garbage collected. We don't call the method re-entrantly so as - // to avoid executing JS in some bizarro undefined mid-GC state, nor do we - // then call into the script context if it's been invalidated. void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args); - // JS Exposed Function: Opens a new channel to an extension. - void OpenChannelToExtension(const v8::FunctionCallbackInfo<v8::Value>& args); - - // JS Exposed Function: Opens a new channel to a native application. - void OpenChannelToNativeApp(const v8::FunctionCallbackInfo<v8::Value>& args); - - // JS Exposed Function: Opens a new channel to a tab. - void OpenChannelToTab(const v8::FunctionCallbackInfo<v8::Value>& args); - - // Helper function to close a port. See CloseChannel() for |force_close| - // documentation. - void ClosePort(int local_port_id, bool force_close); - - int GetNextJsId(); - - // Active ports, mapped by local port id. - PortMap ports_; - - // The next available js id for a port. - size_t next_js_id_ = 0; - - // The number of extension ports created. - size_t num_extension_ports_ = 0; - - base::WeakPtrFactory<MessagingBindings> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(MessagingBindings); };
diff --git a/extensions/renderer/renderer_messaging_service.cc b/extensions/renderer/renderer_messaging_service.cc index efcd2ca..e1a888ac 100644 --- a/extensions/renderer/renderer_messaging_service.cc +++ b/extensions/renderer/renderer_messaging_service.cc
@@ -20,7 +20,6 @@ #include "extensions/common/api/messaging/port_id.h" #include "extensions/common/extension_messages.h" #include "extensions/renderer/extension_bindings_system.h" -#include "extensions/renderer/extension_port.h" #include "extensions/renderer/ipc_message_sender.h" #include "extensions/renderer/messaging_util.h" #include "extensions/renderer/script_context.h"
diff --git a/extensions/renderer/renderer_messaging_service.h b/extensions/renderer/renderer_messaging_service.h index a18371f3..69d137d 100644 --- a/extensions/renderer/renderer_messaging_service.h +++ b/extensions/renderer/renderer_messaging_service.h
@@ -24,6 +24,8 @@ struct Message; struct PortId; +// TODO(devlin): There is now only one RendererMessagingService (the +// NativeRendererMessagingService); consolidate the classes. class RendererMessagingService { public: explicit RendererMessagingService(ExtensionBindingsSystem* bindings_system);
diff --git a/fuchsia/BUILD.gn b/fuchsia/BUILD.gn index 8096362..5b40e7b 100644 --- a/fuchsia/BUILD.gn +++ b/fuchsia/BUILD.gn
@@ -109,15 +109,22 @@ # Location where debug symbol tarballs are placed. _symbol_artifact_root = "$root_out_dir/symbol_artifacts" + # Create a manifest of symbol archives for downstream consumption. + _symbol_tarballs = [ + "$root_gen_dir/fuchsia/engine/chromium/chromium.symbols.tar.bz2", + "$root_gen_dir/fuchsia/http/http/http.symbols.tar.bz2", + "$root_gen_dir/fuchsia/runners/cast_runner/cast_runner.symbols.tar.bz2", + "$root_gen_dir/fuchsia/runners/web_runner/web_runner.symbols.tar.bz2", + ] + _symbol_manifest = "$target_gen_dir/debug_symbols.json" + write_file(_symbol_manifest, _symbol_tarballs, "json") + copy("symbol_tarballs") { sources = [ + _symbol_manifest, "$_release_artifact_root/build_id.txt", - "$root_gen_dir/fuchsia/engine/chromium/chromium.symbols.tar.bz2", - "$root_gen_dir/fuchsia/http/http/http.symbols.tar.bz2", - "$root_gen_dir/fuchsia/runners/cast_runner/cast_runner.symbols.tar.bz2", - "$root_gen_dir/fuchsia/runners/web_runner/web_runner.symbols.tar.bz2", _license_path, - ] + ] + _symbol_tarballs outputs = [ "$_symbol_artifact_root/{{source_file_part}}", ]
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc index f9ac8e2..1f1aa778 100644 --- a/fuchsia/engine/context_provider_impl_unittest.cc +++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -273,10 +273,7 @@ // Pass a handle data dir to the context. create_params.set_data_directory( - fidl::InterfaceHandle<fuchsia::io::Directory>( - zx::channel(base::fuchsia::GetHandleFromFile( - base::File(profile_temp_dir.GetPath(), - base::File::FLAG_OPEN | base::File::FLAG_READ))))); + base::fuchsia::OpenDirectory(profile_temp_dir.GetPath())); provider_ptr_->Create(std::move(create_params), context.NewRequest()); @@ -305,10 +302,7 @@ // Pass a handle data dir to the context. create_params.set_data_directory( - fidl::InterfaceHandle<fuchsia::io::Directory>( - zx::channel(base::fuchsia::GetHandleFromFile( - base::File(profile_temp_dir.GetPath(), - base::File::FLAG_OPEN | base::File::FLAG_READ))))); + base::fuchsia::OpenDirectory(profile_temp_dir.GetPath())); provider_ptr_->Create2(std::move(create_params), context.NewRequest()); @@ -329,10 +323,7 @@ // Pass in a handle to a file instead of a directory. CHECK(base::CreateTemporaryFile(&temp_file_path)); create_params.set_data_directory( - fidl::InterfaceHandle<fuchsia::io::Directory>( - zx::channel(base::fuchsia::GetHandleFromFile( - base::File(temp_file_path, - base::File::FLAG_OPEN | base::File::FLAG_READ))))); + base::fuchsia::OpenDirectory(temp_file_path)); provider_ptr_->Create(std::move(create_params), context.NewRequest());
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc index f5889f0..80b9a91 100644 --- a/fuchsia/runners/common/web_content_runner.cc +++ b/fuchsia/runners/common/web_content_runner.cc
@@ -23,11 +23,9 @@ namespace { -fidl::InterfaceHandle<fuchsia::io::Directory> OpenDirectory( +fidl::InterfaceHandle<fuchsia::io::Directory> OpenDirectoryOrFail( const base::FilePath& path) { - fidl::InterfaceHandle<fuchsia::io::Directory> directory( - zx::channel(base::fuchsia::GetHandleFromFile( - base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ)))); + auto directory = base::fuchsia::OpenDirectory(path); CHECK(directory) << "Failed to open " << path; return directory; } @@ -41,8 +39,8 @@ chromium::web::CreateContextParams2 create_params; // Pass /svc and /data to the context. - create_params.set_service_directory( - OpenDirectory(base::FilePath(base::fuchsia::kServiceDirectoryPath))); + create_params.set_service_directory(OpenDirectoryOrFail( + base::FilePath(base::fuchsia::kServiceDirectoryPath))); if (data_directory) create_params.set_data_directory(std::move(data_directory)); @@ -62,8 +60,8 @@ // static chromium::web::ContextPtr WebContentRunner::CreateDefaultWebContext() { - return CreateWebContextWithDataDirectory( - OpenDirectory(base::FilePath("/data"))); + return CreateWebContextWithDataDirectory(OpenDirectoryOrFail( + base::FilePath(base::fuchsia::kPersistedDataDirectoryPath))); } // static
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index bfb51bc..c269604 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -346,7 +346,14 @@ dawn_procs_, wire_serializer_.get())) {} -WebGPUDecoderImpl::~WebGPUDecoderImpl() {} +WebGPUDecoderImpl::~WebGPUDecoderImpl() { + // Reset the wire server first so all objects are destroyed before the device. + // TODO(enga): Handle Device/Context lost. + wire_server_ = nullptr; + if (dawn_device_ != nullptr) { + dawn_procs_.deviceRelease(dawn_device_); + } +} DawnDevice WebGPUDecoderImpl::CreateDefaultDevice() { dawn_instance_->DiscoverDefaultAdapters();
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc index 3fa7dad..32411622 100644 --- a/gpu/command_buffer/tests/fuzzer_main.cc +++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -422,6 +422,7 @@ config_.attrib_helper); if (result != gpu::ContextResult::kSuccess) return false; + decoder_initialized_ = true; command_buffer_->set_handler(decoder_.get()); InitializeInitialCommandBuffer(); @@ -430,7 +431,6 @@ #if !defined(GPU_FUZZER_USE_RASTER_DECODER) context_group->buffer_manager()->set_max_buffer_size(8 << 20); #endif - decoder_initialized_ = true; return decoder_->MakeCurrent(); } @@ -454,10 +454,16 @@ if (!context_lost) context_lost = decoder_initialized_ && decoder_->CheckResetStatus(); - shared_image_factory_->DestroyAllSharedImages(!context_lost); - decoder_->Destroy(!context_lost); + // If |decoder_->Initialize(...)| was unsuccessful, |decoder_| would have + // already called Destroy. + if (decoder_initialized_) + decoder_->Destroy(!context_lost); decoder_.reset(); + if (!context_lost) + context_state_->MakeCurrent(nullptr); + shared_image_factory_->DestroyAllSharedImages(!context_lost); + shared_image_factory_.reset(); shared_image_manager_.reset(); context_state_.reset();
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index fc78b4d4..c02208ca 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -3245,6 +3245,19 @@ "features": [ "disable_aimagereader" ] + }, + { + "id": 299, + "description": "Context lost recovery often fails on PowerVR Rogue GE8* GPUs on Android.", + "cr_bugs": [942106], + "os": { + "type": "android" + }, + "gl_vendor": "Imagination.*", + "gl_renderer": "PowerVR Rogue GE8.*", + "features": [ + "exit_on_context_lost" + ] } ] }
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc index e2b9183..d3c752c 100644 --- a/gpu/ipc/common/gpu_memory_buffer_support.cc +++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -95,7 +95,8 @@ case gfx::BufferUsage::GPU_READ: case gfx::BufferUsage::SCANOUT: return format == gfx::BufferFormat::RGBA_8888 || - format == gfx::BufferFormat::RGBX_8888; + format == gfx::BufferFormat::RGBX_8888 || + format == gfx::BufferFormat::BGR_565; case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE: case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE: case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index 6602352..b9fbbb3 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -783,6 +783,13 @@ } builders { + name: "Android FYI Release (Pixel 2)" + mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" + } + + builders { name: "Android Release (Nexus 5X)" mixins: "android-gpu-ci" } @@ -1049,6 +1056,14 @@ } builders { + name: "linux-chromeos-code-coverage" + mixins: "code-coverage" + mixins: "fyi-ci" + mixins: "linux" + dimensions: "cores:32" + } + + builders { name: "linux-chromeos-dbg" mixins: "chromeos-ci" } @@ -3164,6 +3179,10 @@ } builders { mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-2-32" + } + builders { + mixins: "android-gpu-manual-try" name: "gpu-manual-try-android-p-pixel-2-32-vk" } builders {
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index be523174..d16f2570 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -2489,6 +2489,11 @@ short_name: "vm" } builders { + name: "buildbucket/luci.chromium.ci/linux-chromeos-code-coverage" + category: "code_coverage" + short_name: "lcr" + } + builders { name: "buildbucket/luci.chromium.ci/mac-code-coverage-generation" category: "code_coverage" short_name: "mac" @@ -3327,6 +3332,11 @@ short_name: "STV" } builders { + name: "buildbucket/luci.chromium.ci/Android FYI Release (Pixel 2)" + category: "Android|P64|QCOM" + short_name: "P2" + } + builders { name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Nexus 5X)" category: "Android|vk|O32" short_name: "N5X" @@ -3900,6 +3910,9 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-android-n-nvidia-shield-tv-64" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32" + } + builders { name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-vk" } builders { @@ -4497,25 +4510,28 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-deqp" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-deqp-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32-deqp" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32-deqp-vk" } builders { - name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64-deqp" + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64-vk" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64-deqp-vk" } builders { name: "buildbucket/luci.chromium.try/gpu_manual_try_win7_nvidia_rel"
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg index d25de57..bfbcf49 100644 --- a/infra/config/luci-scheduler.cfg +++ b/infra/config/luci-scheduler.cfg
@@ -91,6 +91,7 @@ triggers: "Android FYI Release (Nexus 6)" triggers: "Android FYI Release (Nexus 6P)" triggers: "Android FYI Release (Nexus 9)" + triggers: "Android FYI Release (Pixel 2)" triggers: "Android FYI dEQP Release (Nexus 5X)" triggers: "Android Release (Nexus 5X)" triggers: "Android arm Builder (dbg)" @@ -333,6 +334,7 @@ triggers: "linux-blink-animation-use-time-delta" triggers: "linux-blink-heap-incremental-marking" triggers: "linux-blink-heap-verification" + triggers: "linux-chromeos-code-coverage" triggers: "linux-chromeos-dbg" triggers: "linux-chromeos-rel" triggers: "linux-chromium-tests-staging-builder" @@ -631,6 +633,16 @@ } job { + id: "Android FYI Release (Pixel 2)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Android FYI Release (Pixel 2)" + } +} + +job { id: "Android Release (Nexus 5X)" acl_sets: "default" buildbucket: { @@ -1161,6 +1173,16 @@ } job { + id: "linux-chromeos-code-coverage" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-chromeos-code-coverage" + } +} + +job { id: "linux-chromeos-dbg" acl_sets: "default" buildbucket: {
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 0e832685..6a98159 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -166,7 +166,9 @@ LOGGER.info( 'Process iossim is still alive! Xcodebuild process might block it.') xcodebuild_processes = [ - p for p in psutil.process_iter() if 'xcodebuild' == p.info['name']] + p for p in psutil.process_iter() + # Use as_dict() to avoid API changes across versions of psutil. + if 'xcodebuild' == p.as_dict(attrs=['name'])['name']] if not xcodebuild_processes: LOGGER.debug('There are no running xcodebuild processes.') break
diff --git a/ios/chrome/app/chrome_exe_main.mm b/ios/chrome/app/chrome_exe_main.mm index dff54905..a81cc5c2 100644 --- a/ios/chrome/app/chrome_exe_main.mm +++ b/ios/chrome/app/chrome_exe_main.mm
@@ -43,6 +43,18 @@ } } +void SetUILanguageIfLanguageIsSelected() { + @autoreleasepool { + NSUserDefaults* standard_defaults = [NSUserDefaults standardUserDefaults]; + NSString* language = [standard_defaults valueForKey:@"UILanguageOverride"]; + if (!language || [language length] == 0) { + [standard_defaults removeObjectForKey:@"AppleLanguages"]; + } else { + [standard_defaults setObject:@[ language ] forKey:@"AppleLanguages"]; + } + } +} + int RunUIApplicationMain(int argc, char* argv[]) { @autoreleasepool { // Fetch the name of the UIApplication delegate stored in the application @@ -64,6 +76,9 @@ // Set NSUserDefaults keys to force pseudo-RTL if needed. SetTextDirectionIfPseudoRTLEnabled(); + // Set NSUserDefaults keys to force the UI language if needed. + SetUILanguageIfLanguageIsSelected(); + // Create this here since it's needed to start the crash handler. base::AtExitManager at_exit;
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 185b7aa..d68a31c5 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -123,7 +123,6 @@ "//ios/chrome/browser/browsing_data:feature_flags", "//ios/chrome/browser/crash_report:flags", "//ios/chrome/browser/download", - "//ios/chrome/browser/download:features", "//ios/chrome/browser/drag_and_drop", "//ios/chrome/browser/find_in_page:feature_flags", "//ios/chrome/browser/itunes_urls",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index 0975282..5f25107 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -49,7 +49,6 @@ #include "ios/chrome/browser/browsing_data/browsing_data_features.h" #include "ios/chrome/browser/chrome_switches.h" #include "ios/chrome/browser/crash_report/crash_report_flags.h" -#include "ios/chrome/browser/download/features.h" #include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h" #include "ios/chrome/browser/find_in_page/features.h" #include "ios/chrome/browser/ios_chrome_flag_descriptions.h" @@ -233,9 +232,6 @@ feature_engagement::kIPHDemoMode, feature_engagement::kIPHDemoModeChoiceVariations, "IPH_DemoMode")}, - {"preview-usdz", flag_descriptions::kUsdzPreviewName, - flag_descriptions::kUsdzPreviewDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(download::kUsdzPreview)}, {"use-ddljson-api", flag_descriptions::kUseDdljsonApiName, flag_descriptions::kUseDdljsonApiDescription, flags_ui::kOsIos, MULTI_VALUE_TYPE(kUseDdljsonApiChoices)},
diff --git a/ios/chrome/browser/download/browser_download_service_unittest.mm b/ios/chrome/browser/download/browser_download_service_unittest.mm index 755fa5e..9e12991fa 100644 --- a/ios/chrome/browser/download/browser_download_service_unittest.mm +++ b/ios/chrome/browser/download/browser_download_service_unittest.mm
@@ -8,7 +8,6 @@ #include "base/macros.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/download/ar_quick_look_tab_helper.h" #import "ios/chrome/browser/download/download_manager_tab_helper.h" @@ -92,8 +91,6 @@ protected: BrowserDownloadServiceTest() : browser_state_(browser_state_builder_.Build()) { - scoped_feature_list_.InitAndEnableFeature(download::kUsdzPreview); - StubTabHelper<PassKitTabHelper>::CreateForWebState(&web_state_); TestARQuickLookTabHelper::CreateForWebState(&web_state_); StubTabHelper<DownloadManagerTabHelper>::CreateForWebState(&web_state_); @@ -140,7 +137,6 @@ std::unique_ptr<BrowserDownloadService> service_; web::TestWebState web_state_; base::HistogramTester histogram_tester_; - base::test::ScopedFeatureList scoped_feature_list_; }; // Tests that BrowserDownloadService downloads the task using
diff --git a/ios/chrome/browser/download/features.h b/ios/chrome/browser/download/features.h index aabd567..091010a 100644 --- a/ios/chrome/browser/download/features.h +++ b/ios/chrome/browser/download/features.h
@@ -5,12 +5,8 @@ #ifndef IOS_CHROME_BROWSER_DOWNLOAD_FEATURES_H_ #define IOS_CHROME_BROWSER_DOWNLOAD_FEATURES_H_ -#include "base/feature_list.h" - namespace download { -extern const base::Feature kUsdzPreview; - // Returns whether USDZ AR Quick Look is enabled. bool IsUsdzPreviewEnabled();
diff --git a/ios/chrome/browser/download/features.mm b/ios/chrome/browser/download/features.mm index f2701e21..97a0fa7 100644 --- a/ios/chrome/browser/download/features.mm +++ b/ios/chrome/browser/download/features.mm
@@ -12,14 +12,10 @@ namespace download { -// Controls previewing USDZ format 3D models in AR Quick Look. -const base::Feature kUsdzPreview{"USDZPreview", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Returns whether AR Quick Look in enabled. bool IsUsdzPreviewEnabled() { if (@available(iOS 12, *)) { - return base::FeatureList::IsEnabled(kUsdzPreview); + return true; } return false; }
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index f34b61c..3e771ce 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -410,10 +410,6 @@ const char kUseNSURLSessionForGaiaSigninRequestsDescription[] = "Use NSURLSession to make sign-in requests to Gaia"; -const char kUsdzPreviewName[] = "Preview USDZ format 3D models"; -const char kUsdzPreviewDescription[] = - "Enables previewing USDZ format 3D models in AR Quick Look."; - const char kUseDdljsonApiName[] = "Use new ddljson API for Doodles"; const char kUseDdljsonApiDescription[] = "Enables the new ddljson API to fetch Doodles for the NTP.";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index 06ca48d..ee15099 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -340,10 +340,6 @@ extern const char kUseNSURLSessionForGaiaSigninRequestsName[]; extern const char kUseNSURLSessionForGaiaSigninRequestsDescription[]; -// Title and description for the flag to enable previewing USDZ 3 model files. -extern const char kUsdzPreviewName[]; -extern const char kUsdzPreviewDescription[]; - // Title and description for the flag to enable the ddljson Doodle API. extern const char kUseDdljsonApiName[]; extern const char kUseDdljsonApiDescription[];
diff --git a/ios/chrome/browser/net/cookie_util.mm b/ios/chrome/browser/net/cookie_util.mm index 3192182..2e30e56 100644 --- a/ios/chrome/browser/net/cookie_util.mm +++ b/ios/chrome/browser/net/cookie_util.mm
@@ -58,8 +58,7 @@ net::NetLog* net_log) { if (config.path.empty()) { // Empty path means in-memory store. - return std::make_unique<net::CookieMonster>( - nullptr /* store */, nullptr /* channel_id_service */, net_log); + return std::make_unique<net::CookieMonster>(nullptr /* store */, net_log); } const bool restore_old_session_cookies = @@ -67,8 +66,8 @@ scoped_refptr<net::SQLitePersistentCookieStore> persistent_store = CreatePersistentCookieStore(config.path, restore_old_session_cookies, config.crypto_delegate); - std::unique_ptr<net::CookieMonster> cookie_monster(new net::CookieMonster( - persistent_store.get(), nullptr /* channel_id_service */, net_log)); + std::unique_ptr<net::CookieMonster> cookie_monster( + new net::CookieMonster(persistent_store.get(), net_log)); if (restore_old_session_cookies) cookie_monster->SetPersistSessionCookies(true); return cookie_monster;
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index 752b7a4..d4bc3147 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -54,6 +54,34 @@ </dict> <dict> <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Force Language</string> + <key>Key</key> + <string>UILanguageOverride</string> + <key>DefaultValue</key> + <string></string> + <key>Values</key> + <array> + <string></string> + <string>ar</string> + <string>en</string> + <string>fr</string> + <string>he</string> + <string>hi</string> + </array> + <key>Titles</key> + <array> + <string>Default</string> + <string>Arabic</string> + <string>English</string> + <string>French</string> + <string>Hebrew</string> + <string>Hindi</string> + </array> + </dict> + <dict> + <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Debug Settings</string>
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm index 7e3dd78..39aa1e6 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -270,10 +270,12 @@ - (void)focusOmniboxFromSearchButton { // TODO(crbug.com/931284): Temporary workaround for intermediate broken state // in the NTP. Remove this once crbug.com/899827 is fixed. - NewTabPageTabHelper* NTPHelper = - NewTabPageTabHelper::FromWebState(self.webState); - if (NTPHelper && NTPHelper->IsActive() && NTPHelper->IgnoreLoadRequests()) { - return; + if (self.webState) { + NewTabPageTabHelper* NTPHelper = + NewTabPageTabHelper::FromWebState(self.webState); + if (NTPHelper && NTPHelper->IsActive() && NTPHelper->IgnoreLoadRequests()) { + return; + } } [self.omniboxCoordinator setNextFocusSourceAsSearchButton]; [self focusOmnibox]; @@ -286,10 +288,12 @@ - (void)focusOmnibox { // TODO(crbug.com/931284): Temporary workaround for intermediate broken state // in the NTP. Remove this once crbug.com/899827 is fixed. - NewTabPageTabHelper* NTPHelper = - NewTabPageTabHelper::FromWebState(self.webState); - if (NTPHelper && NTPHelper->IsActive() && NTPHelper->IgnoreLoadRequests()) { - return; + if (self.webState) { + NewTabPageTabHelper* NTPHelper = + NewTabPageTabHelper::FromWebState(self.webState); + if (NTPHelper && NTPHelper->IsActive() && NTPHelper->IgnoreLoadRequests()) { + return; + } } // Dismiss the edit menu. [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h index 79970af..63d484a0 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h
@@ -29,7 +29,9 @@ const base::string16& formatted_url) const override; bool GetURL(GURL* url) const override; bool ShouldDisplayURL() const override; - void GetSecurityInfo(security_state::SecurityInfo* result) const override; + security_state::SecurityLevel GetSecurityLevel() const override; + std::unique_ptr<security_state::VisibleSecurityState> + GetVisibleSecurityState() const override; scoped_refptr<net::X509Certificate> GetCertificate() const override; const gfx::VectorIcon* GetVectorIconOverride() const override; bool IsOfflinePage() const override;
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm index 6c3002f..c3753085 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm
@@ -76,17 +76,28 @@ return true; } -void LocationBarModelDelegateIOS::GetSecurityInfo( - security_state::SecurityInfo* result) const { +security_state::SecurityLevel LocationBarModelDelegateIOS::GetSecurityLevel() + const { web::WebState* web_state = GetActiveWebState(); // If there is no active WebState (which can happen during toolbar // initialization), assume no security style. if (!web_state) { - *result = security_state::SecurityInfo(); - return; + return security_state::NONE; } auto* client = IOSSecurityStateTabHelper::FromWebState(web_state); - client->GetSecurityInfo(result); + return client->GetSecurityLevel(); +} + +std::unique_ptr<security_state::VisibleSecurityState> +LocationBarModelDelegateIOS::GetVisibleSecurityState() const { + web::WebState* web_state = GetActiveWebState(); + // If there is no active WebState (which can happen during toolbar + // initialization), assume no security style. + if (!web_state) { + return std::make_unique<security_state::VisibleSecurityState>(); + } + auto* client = IOSSecurityStateTabHelper::FromWebState(web_state); + return client->GetVisibleSecurityState(); } scoped_refptr<net::X509Certificate>
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm index a795a6a..2e85b7d 100644 --- a/ios/components/io_thread/ios_io_thread.mm +++ b/ios/components/io_thread/ios_io_thread.mm
@@ -258,9 +258,8 @@ globals_->http_server_properties.reset(new net::HttpServerPropertiesImpl()); // In-memory cookie store. // TODO(crbug.com/801910): Hook up logging by passing in a non-null netlog. - globals_->system_cookie_store.reset(new net::CookieMonster( - nullptr /* store */, nullptr /* channel_id_service */, - nullptr /* netlog */)); + globals_->system_cookie_store.reset( + new net::CookieMonster(nullptr /* store */, nullptr /* netlog */)); // In-memory channel ID store. globals_->system_channel_id_service.reset( new net::ChannelIDService(new net::DefaultChannelIDStore(nullptr)));
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm index 92df7be..5bc35f4 100644 --- a/ios/net/cookies/cookie_store_ios.mm +++ b/ios/net/cookies/cookie_store_ios.mm
@@ -501,7 +501,6 @@ std::unique_ptr<SystemCookieStore> system_store, NetLog* net_log) : cookie_monster_(new net::CookieMonster(persistent_store, - nullptr /* channel_id_service */, net_log)), system_store_(std::move(system_store)), metrics_enabled_(false),
diff --git a/ios/third_party/edo/BUILD.gn b/ios/third_party/edo/BUILD.gn index 3c136d4..ea2663b 100644 --- a/ios/third_party/edo/BUILD.gn +++ b/ios/third_party/edo/BUILD.gn
@@ -13,25 +13,48 @@ sources = [ "src/Channel/Sources/EDOChannel.h", + "src/Channel/Sources/EDOChannelPool.h", + "src/Channel/Sources/EDOChannelPool.m", + "src/Channel/Sources/EDOChannelUtil.h", + "src/Channel/Sources/EDOChannelUtil.m", + "src/Channel/Sources/EDOHostPort.h", + "src/Channel/Sources/EDOHostPort.m", "src/Channel/Sources/EDOListenSocket.h", "src/Channel/Sources/EDOListenSocket.m", "src/Channel/Sources/EDOSocket.h", "src/Channel/Sources/EDOSocket.m", "src/Channel/Sources/EDOSocketChannel.h", "src/Channel/Sources/EDOSocketChannel.m", - "src/Channel/Sources/EDOSocketChannelPool.h", - "src/Channel/Sources/EDOSocketChannelPool.m", "src/Channel/Sources/EDOSocketPort.h", "src/Channel/Sources/EDOSocketPort.m", + "src/Device/Sources/EDODeviceChannel.h", + "src/Device/Sources/EDODeviceChannel.m", + "src/Device/Sources/EDODeviceConnector.h", + "src/Device/Sources/EDODeviceConnector.m", + "src/Device/Sources/EDODeviceDetector.h", + "src/Device/Sources/EDODeviceDetector.m", + "src/Device/Sources/EDOUSBMuxUtil.h", + "src/Device/Sources/EDOUSBMuxUtil.m", + "src/Measure/Sources/EDONumericMeasure.h", + "src/Measure/Sources/EDONumericMeasure.m", "src/Service/Sources/EDOBlockObject.h", "src/Service/Sources/EDOBlockObject.m", "src/Service/Sources/EDOClassMessage.h", "src/Service/Sources/EDOClassMessage.m", + "src/Service/Sources/EDOClientService+Device.h", "src/Service/Sources/EDOClientService+Private.h", "src/Service/Sources/EDOClientService.h", "src/Service/Sources/EDOClientService.m", + "src/Service/Sources/EDOClientServiceStatsCollector.h", + "src/Service/Sources/EDOClientServiceStatsCollector.m", "src/Service/Sources/EDOExecutor.h", "src/Service/Sources/EDOExecutor.m", + "src/Service/Sources/EDOExecutorMessage.h", + "src/Service/Sources/EDOExecutorMessage.m", + "src/Service/Sources/EDOHostNamingService+Private.h", + "src/Service/Sources/EDOHostNamingService.h", + "src/Service/Sources/EDOHostNamingService.m", + "src/Service/Sources/EDOHostService+Device.h", "src/Service/Sources/EDOHostService+Handlers.h", "src/Service/Sources/EDOHostService+Handlers.m", "src/Service/Sources/EDOHostService+Private.h", @@ -66,11 +89,17 @@ "src/Service/Sources/EDOServicePort.m", "src/Service/Sources/EDOServiceRequest.h", "src/Service/Sources/EDOServiceRequest.m", + "src/Service/Sources/EDOTimingFunctions.h", + "src/Service/Sources/EDOTimingFunctions.m", "src/Service/Sources/EDOValueObject+EDOParameter.m", "src/Service/Sources/EDOValueObject.h", "src/Service/Sources/EDOValueObject.m", "src/Service/Sources/EDOValueType.m", "src/Service/Sources/NSBlock+EDOInvocation.m", + "src/Service/Sources/NSKeyedArchiver+EDOAdditions.h", + "src/Service/Sources/NSKeyedArchiver+EDOAdditions.m", + "src/Service/Sources/NSKeyedUnarchiver+EDOAdditions.h", + "src/Service/Sources/NSKeyedUnarchiver+EDOAdditions.m", "src/Service/Sources/NSObject+EDOParameter.h", "src/Service/Sources/NSObject+EDOParameter.m", "src/Service/Sources/NSObject+EDOValue.h",
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.mm b/ios/web/navigation/legacy_navigation_manager_impl.mm index 0fd6212..cdde8a6 100644 --- a/ios/web/navigation/legacy_navigation_manager_impl.mm +++ b/ios/web/navigation/legacy_navigation_manager_impl.mm
@@ -210,6 +210,9 @@ int last_committed_item_index, std::vector<std::unique_ptr<NavigationItem>> items) { WillRestore(items.size()); + for (size_t index = 0; index < items.size(); ++index) { + RewriteItemURLIfNecessary(items[index].get()); + } DCHECK(GetItemCount() == 0 && !GetPendingItem()); DCHECK_LT(last_committed_item_index, static_cast<int>(items.size()));
diff --git a/ios/web/public/origin_util.mm b/ios/web/public/origin_util.mm index 570d1560..47ad181 100644 --- a/ios/web/public/origin_util.mm +++ b/ios/web/public/origin_util.mm
@@ -19,6 +19,10 @@ if (url.SchemeIsCryptographic() || url.SchemeIsFile()) return true; + // TODO(crbug.com/939077): Also consider inner origins of blob: URLs + // (ideally, by deleting this function altogether and instead reusing + // //services/network/public/cpp/is_potentially_trustworthy.h (possibly after + // moving it to a location that can be consumed by //ios). if (url.SchemeIsFileSystem() && url.inner_url() && IsOriginSecure(*url.inner_url())) { return true;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 27dfc4732..2e6fb711 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -2049,6 +2049,10 @@ ProceduralBlock defaultNavigationBlock = ^{ web::NavigationItem* item = self.currentNavItem; GURL navigationURL = item ? item->GetURL() : GURL::EmptyGURL(); + GURL virtualURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); + // Set |item| to nullptr here to avoid any use-after-free issues, as it can + // be cleared by the call to -registerLoadRequestForURL below. + item = nullptr; GURL contextURL = IsPlaceholderUrl(navigationURL) ? ExtractUrlFromPlaceholderUrl(navigationURL) : navigationURL; @@ -2062,7 +2066,6 @@ placeholderNavigation:IsPlaceholderUrl(navigationURL)]; WKNavigation* navigation = nil; - GURL virtualURL = item ? item->GetVirtualURL() : GURL::EmptyGURL(); if (navigationURL.SchemeIsFile() && web::GetWebClient()->IsAppSpecificURL(virtualURL)) { // file:// URL navigations are allowed for app-specific URLs, which
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm index fa0e21a..934ddf2 100644 --- a/ios/web_view/internal/web_view_browser_state.mm +++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -124,6 +124,11 @@ #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) ActiveStateManager::FromBrowserState(this)->SetActive(false); #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) + + base::PostTaskWithTraits( + FROM_HERE, {web::WebThread::IO}, + base::BindOnce(&WebViewURLRequestContextGetter::ShutDown, + request_context_getter_)); } PrefService* WebViewBrowserState::GetPrefs() {
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.h b/ios/web_view/internal/web_view_url_request_context_getter.h index d1bed19..c893c6284 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.h +++ b/ios/web_view/internal/web_view_url_request_context_getter.h
@@ -36,6 +36,10 @@ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; + // Discard reference to URLRequestContext and inform observers of shutdown. + // Must be called before destruction. May only be called on IO thread. + void ShutDown(); + protected: ~WebViewURLRequestContextGetter() override; @@ -50,6 +54,9 @@ std::unique_ptr<net::TransportSecurityPersister> transport_security_persister_; + // Used to ensure GetURLRequestContext() returns nullptr during shut down. + bool is_shutting_down_; + DISALLOW_COPY_AND_ASSIGN(WebViewURLRequestContextGetter); };
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm index 3be9309..c0d482c7 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.mm +++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -51,13 +51,18 @@ network_task_runner_(network_task_runner), proxy_config_service_( new net::ProxyConfigServiceIOS(NO_TRAFFIC_ANNOTATION_YET)), - net_log_(new net::NetLog()) {} + net_log_(new net::NetLog()), + is_shutting_down_(false) {} WebViewURLRequestContextGetter::~WebViewURLRequestContextGetter() = default; net::URLRequestContext* WebViewURLRequestContextGetter::GetURLRequestContext() { DCHECK(network_task_runner_->BelongsToCurrentThread()); + if (is_shutting_down_) { + return nullptr; + } + if (!url_request_context_) { url_request_context_.reset(new net::URLRequestContext()); url_request_context_->set_net_log(net_log_.get()); @@ -173,4 +178,10 @@ return network_task_runner_; } +void WebViewURLRequestContextGetter::ShutDown() { + is_shutting_down_ = true; + url_request_context_.reset(); + net::URLRequestContextGetter::NotifyContextShuttingDown(); +} + } // namespace ios_web_view
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index 06b549af..5b72df5 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -81,8 +81,11 @@ void WebViewWebMainParts::PostMainMessageLoopRun() { WebViewTranslateService::GetInstance()->Shutdown(); - ApplicationContext::GetInstance()->SaveState(); + + // CWVWebViewConfiguration must destroy its WebViewBrowserStates before the + // threads are stopped by ApplicationContext. [CWVWebViewConfiguration shutDown]; + ApplicationContext::GetInstance()->SaveState(); } void WebViewWebMainParts::PostDestroyThreads() {
diff --git a/jingle/glue/network_service_async_socket_unittest.cc b/jingle/glue/network_service_async_socket_unittest.cc index eab01653..bb66f19 100644 --- a/jingle/glue/network_service_async_socket_unittest.cc +++ b/jingle/glue/network_service_async_socket_unittest.cc
@@ -390,9 +390,10 @@ } std::string ToString() const { - return base::StrCat( - {"(", base::IntToString(signal), ",", base::IntToString(state), ",", - base::IntToString(error), ",", base::IntToString(net_error), ")"}); + return base::StrCat({"(", base::NumberToString(signal), ",", + base::NumberToString(state), ",", + base::NumberToString(error), ",", + base::NumberToString(net_error), ")"}); } Signal signal;
diff --git a/jingle/notifier/listener/xml_element_util.cc b/jingle/notifier/listener/xml_element_util.cc index 63f4dff2..d058f90 100644 --- a/jingle/notifier/listener/xml_element_util.cc +++ b/jingle/notifier/listener/xml_element_util.cc
@@ -35,7 +35,7 @@ const jingle_xmpp::QName intAttrQName(jingle_xmpp::STR_EMPTY, "int"); jingle_xmpp::XmlElement* int_xml_element = new jingle_xmpp::XmlElement(elementQName, true); - int_xml_element->AddAttr(intAttrQName, base::IntToString(value)); + int_xml_element->AddAttr(intAttrQName, base::NumberToString(value)); return int_xml_element; }
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index d96e904a..eef8c494 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -69,7 +69,6 @@ #include "net/cookies/cookie_util.h" #include "net/cookies/parsed_cookie.h" #include "net/log/net_log.h" -#include "net/ssl/channel_id_service.h" #include "url/origin.h" using base::Time; @@ -337,24 +336,15 @@ } // namespace CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store, - ChannelIDService* channel_id_service, NetLog* net_log) : CookieMonster( std::move(store), - channel_id_service, base::TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds), net_log) {} CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store, base::TimeDelta last_access_threshold, NetLog* net_log) - : CookieMonster(std::move(store), nullptr, last_access_threshold, net_log) { -} - -CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store, - ChannelIDService* channel_id_service, - base::TimeDelta last_access_threshold, - NetLog* net_log) : initialized_(false), started_fetching_all_cookies_(false), finished_fetching_all_cookies_(false), @@ -362,7 +352,6 @@ net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::COOKIE_STORE)), store_(std::move(store)), last_access_threshold_(last_access_threshold), - channel_id_service_(channel_id_service), last_statistic_record_time_(base::Time::Now()), persist_session_cookies_(false), weak_ptr_factory_(this) { @@ -370,21 +359,10 @@ cookieable_schemes_.insert( cookieable_schemes_.begin(), kDefaultCookieableSchemes, kDefaultCookieableSchemes + kDefaultCookieableSchemesCount); - if (channel_id_service_ && store_) { - // |store_| can outlive this CookieMonster, but there are no guarantees - // about the lifetime of |channel_id_service_| relative to |store_|. The - // only guarantee is that |channel_id_service_| will outlive this - // CookieMonster. To avoid the PersistentCookieStore retaining a pointer to - // the ChannelIDStore via this callback after this CookieMonster is - // destroyed, CookieMonster's d'tor sets the callback to a null callback. - store_->SetBeforeCommitCallback( - base::Bind(&ChannelIDStore::Flush, - base::Unretained(channel_id_service_->GetChannelIDStore()))); - } net_log_.BeginEvent( NetLogEventType::COOKIE_STORE_ALIVE, base::BindRepeating(&NetLogCookieMonsterConstructorCallback, - store != nullptr, channel_id_service != nullptr)); + store != nullptr)); } // Asynchronous CookieMonster API @@ -584,10 +562,6 @@ CookieMonster::~CookieMonster() { DCHECK(thread_checker_.CalledOnValidThread()); - if (channel_id_service_ && store_) { - store_->SetBeforeCommitCallback(base::RepeatingClosure()); - } - // TODO(mmenke): Does it really make sense to run // CookieChanged callbacks when the CookieStore is destroyed? for (auto cookie_it = cookies_.begin(); cookie_it != cookies_.end();) {
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index d92c94b..d74a4dc 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -40,7 +40,6 @@ namespace net { -class ChannelIDService; class CookieChangeDispatcher; // The cookie monster is the system for storing and retrieving cookies. It has @@ -131,12 +130,8 @@ // class will take care of initializing it. The backing store is NOT owned by // this class, but it must remain valid for the duration of the cookie // monster's existence. If |store| is NULL, then no backing store will be - // updated. |channel_id_service| is a non-owninng pointer for the - // corresponding ChannelIDService used with this CookieStore. The - // |channel_id_service| must outlive the CookieMonster. |net_log| must outlive - // the CookieMonster. Both |channel_id_service| and |net_log| can be null. + // updated. |net_log| must outlive the CookieMonster and can be null. CookieMonster(scoped_refptr<PersistentCookieStore> store, - ChannelIDService* channel_id_service, NetLog* net_log); // Only used during unit testing. @@ -210,11 +205,6 @@ static std::string GetKey(base::StringPiece domain); private: - CookieMonster(scoped_refptr<PersistentCookieStore> store, - ChannelIDService* channel_id_service, - base::TimeDelta last_access_threshold, - NetLog* net_log); - // For garbage collection constants. FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection); FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, GarbageCollectionTriggers); @@ -631,8 +621,6 @@ std::vector<std::string> cookieable_schemes_; - ChannelIDService* channel_id_service_; - base::Time last_statistic_record_time_; bool persist_session_cookies_;
diff --git a/net/cookies/cookie_monster_netlog_params.cc b/net/cookies/cookie_monster_netlog_params.cc index b4b17d28..dff8422 100644 --- a/net/cookies/cookie_monster_netlog_params.cc +++ b/net/cookies/cookie_monster_netlog_params.cc
@@ -11,12 +11,10 @@ std::unique_ptr<base::Value> NetLogCookieMonsterConstructorCallback( bool persistent_store, - bool channel_id_service, NetLogCaptureMode /* capture_mode */) { std::unique_ptr<base::Value> dict = std::make_unique<base::Value>(base::Value::Type::DICTIONARY); dict->SetKey("persistent_store", base::Value(persistent_store)); - dict->SetKey("channel_id_service", base::Value(channel_id_service)); return dict; }
diff --git a/net/cookies/cookie_monster_netlog_params.h b/net/cookies/cookie_monster_netlog_params.h index 8a5dc1f..16ab7727 100644 --- a/net/cookies/cookie_monster_netlog_params.h +++ b/net/cookies/cookie_monster_netlog_params.h
@@ -20,7 +20,6 @@ // a CookieMonster. std::unique_ptr<base::Value> NetLogCookieMonsterConstructorCallback( bool persistent_store, - bool channel_id_service, NetLogCaptureMode capture_mode); // Returns a Value containing NetLog parameters for adding a cookie.
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index b7c90ec..55e2cc72 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -137,7 +137,7 @@ } TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, nullptr); + auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); std::vector<std::string> cookies; for (int i = 0; i < kNumCookies; i++) { cookies.push_back(base::StringPrintf("a%03d=b", i)); @@ -170,7 +170,7 @@ } TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, nullptr); + auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); std::string cookie(kCookieLine); std::vector<GURL> gurls; // just wanna have ffffuunnn for (int i = 0; i < kNumCookies; ++i) { @@ -203,7 +203,7 @@ } TEST_F(CookieMonsterTest, TestDomainTree) { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, nullptr); + auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); GetCookieListCallback getCookieListCallback; SetCookieCallback setCookieCallback; const char domain_cookie_format_tree[] = "a=b; domain=%s"; @@ -259,7 +259,7 @@ } TEST_F(CookieMonsterTest, TestDomainLine) { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, nullptr); + auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); SetCookieCallback setCookieCallback; GetCookieListCallback getCookieListCallback; std::vector<std::string> domain_list; @@ -320,8 +320,7 @@ store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Import will happen on first access. GURL gurl("www.foo.com"); @@ -335,8 +334,7 @@ } TEST_F(CookieMonsterTest, TestGetKey) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); base::PerfTimeLogger timer("Cookie_monster_get_key"); for (int i = 0; i < kNumCookies; i++) cm->GetKey("www.foo.com");
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc index c929043..6294399 100644 --- a/net/cookies/cookie_monster_store_test.cc +++ b/net/cookies/cookie_monster_store_test.cc
@@ -238,7 +238,7 @@ store->AddCookie(*cc); } - return std::make_unique<CookieMonster>(store.get(), nullptr, nullptr); + return std::make_unique<CookieMonster>(store.get(), nullptr); } MockSimplePersistentCookieStore::~MockSimplePersistentCookieStore() = default;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 02521262..f833a47 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -97,7 +97,6 @@ struct CookieMonsterTestTraits { static std::unique_ptr<CookieStore> Create() { return std::make_unique<CookieMonster>(nullptr /* store */, - nullptr /* channel_id_service */, nullptr /* netlog */); } @@ -382,7 +381,7 @@ (domain_max_cookies + domain_purge_cookies) * 2; // Add a bunch of cookies on a single host, should purge them. { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_); for (int i = 0; i < more_than_enough_cookies; ++i) { std::string cookie = base::StringPrintf("a%03d=b", i); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), cookie)); @@ -399,7 +398,7 @@ // between them. We shouldn't go above kDomainMaxCookies for both together. GURL url_google_specific(http_www_foo_.Format("http://www.gmail.%D")); { - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_); for (int i = 0; i < more_than_enough_cookies; ++i) { std::string cookie_general = base::StringPrintf("a%03d=b", i); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), cookie_general)); @@ -576,7 +575,7 @@ std::unique_ptr<CookieMonster> cm; if (alt_host_entries == nullptr) { - cm.reset(new CookieMonster(nullptr, nullptr, &net_log_)); + cm.reset(new CookieMonster(nullptr, &net_log_)); } else { // When generating all of these cookies on alternate hosts, they need to // be all older than the max "safe" date for GC, which is currently 30 @@ -621,7 +620,7 @@ DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - CookieMonster::kDomainPurgeCookies); - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_); // Each test case adds 181 cookies, so 31 cookies are evicted. // Cookie same priority, repeated for each priority. @@ -684,7 +683,7 @@ DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - CookieMonster::kDomainPurgeCookies); - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_); // Each test case adds 181 cookies, so 31 cookies are evicted. // Cookie same priority, repeated for each priority. @@ -741,7 +740,7 @@ DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - CookieMonster::kDomainPurgeCookies); - auto cm = std::make_unique<CookieMonster>(nullptr, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_); // Each test case adds 180 secure cookies, and some non-secure cookie. The // secure cookies take priority, so the non-secure cookie is removed, along @@ -847,7 +846,7 @@ // Function for creating a CM with a number of cookies in it, // no store (and hence no ability to affect access time). CookieMonster* CreateMonsterForGC(int num_cookies) { - CookieMonster* cm(new CookieMonster(nullptr, nullptr, &net_log_)); + CookieMonster* cm(new CookieMonster(nullptr, &net_log_)); for (int i = 0; i < num_cookies; i++) { SetCookie(cm, GURL(base::StringPrintf("http://h%05d.izzle", i)), "a=1"); } @@ -967,8 +966,8 @@ protected: DeferredCookieTaskTest() : expect_load_called_(false) { persistent_store_ = new NewMockPersistentCookieStore(); - cookie_monster_ = std::make_unique<CookieMonster>(persistent_store_.get(), - nullptr, &net_log_); + cookie_monster_ = + std::make_unique<CookieMonster>(persistent_store_.get(), &net_log_); } // Defines a cookie to be returned from PersistentCookieStore::Load @@ -1352,8 +1351,7 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAll) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); CookieOptions options; options.set_include_httponly(); @@ -1384,8 +1382,7 @@ } TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedInTimeRangeTimestamps) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); Time now = Time::Now(); // Nothing has been added so nothing should be deleted. @@ -1432,8 +1429,7 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedInTimeRangeTimestampsWithInfo) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); Time now = Time::Now(); CanonicalCookie test_cookie; @@ -1543,10 +1539,8 @@ } TEST_F(CookieMonsterTest, SetCookieableSchemes) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); - std::unique_ptr<CookieMonster> cm_foo( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm_foo(new CookieMonster(nullptr, &net_log_)); // Only cm_foo should allow foo:// cookies. std::vector<std::string> schemes; @@ -1739,8 +1733,7 @@ } TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); CookieOptions options; EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_foo_foo_.url(), @@ -1778,8 +1771,7 @@ } TEST_F(CookieMonsterTest, GetExcludedCookiesForURLPathMatching) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); CookieOptions options; EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_foo_foo_.url(), @@ -1814,8 +1806,7 @@ } TEST_F(CookieMonsterTest, CookieSorting) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B1; path=/")); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B2; path=/foo")); @@ -1839,8 +1830,7 @@ } TEST_F(CookieMonsterTest, InheritCreationDate) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); base::Time the_not_so_distant_past(base::Time::Now() - base::TimeDelta::FromSeconds(1000)); @@ -1872,8 +1862,7 @@ // Check that GetAllCookiesForURL() does not return expired cookies and deletes // them. TEST_F(CookieMonsterTest, DeleteExpiredCookiesOnGet) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B;")); @@ -1945,8 +1934,7 @@ // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); // Verify that duplicates were not imported for path "/". // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4). @@ -2002,8 +1990,7 @@ // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); CookieList list(GetAllCookies(cm.get())); EXPECT_EQ(2U, list.size()); @@ -2016,8 +2003,7 @@ } TEST_F(CookieMonsterTest, PredicateSeesAllCookies) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); PopulateCmForPredicateCheck(cm.get()); // We test that we can see all cookies with |delete_info|. This includes // host, http_only, host secure, and all domain cookies. @@ -2039,8 +2025,7 @@ // Mainly a test of GetEffectiveDomain, or more specifically, of the // expected behavior of GetEffectiveDomain within the CookieMonster. TEST_F(CookieMonsterTest, GetKey) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); // This test is really only interesting if GetKey() actually does something. EXPECT_EQ("foo.com", cm->GetKey("www.foo.com")); @@ -2085,7 +2070,7 @@ // Create new cookies and flush them to the store. { std::unique_ptr<CookieMonster> cmout( - new CookieMonster(store.get(), nullptr, &net_log_)); + new CookieMonster(store.get(), &net_log_)); for (const auto& cookie : input_info) { EXPECT_TRUE(SetCanonicalCookie( cmout.get(), @@ -2104,7 +2089,7 @@ // Create a new cookie monster and make sure that everything is correct { std::unique_ptr<CookieMonster> cmin( - new CookieMonster(store.get(), nullptr, &net_log_)); + new CookieMonster(store.get(), &net_log_)); CookieList cookies(GetAllCookies(cmin.get())); ASSERT_EQ(2u, cookies.size()); // Ordering is path length, then creation time. So second cookie @@ -2138,7 +2123,7 @@ base::MakeRefCounted<MockPersistentCookieStore>(); { - CookieMonster cmout(store.get(), nullptr, &net_log_); + CookieMonster cmout(store.get(), &net_log_); GURL url("http://www.example.com/"); EXPECT_TRUE( SetCookieWithCreationTime(&cmout, url, "A=1; max-age=600", current)); @@ -2160,7 +2145,7 @@ // Now read them in. Should get two cookies, not one. { - CookieMonster cmin(store2.get(), nullptr, &net_log_); + CookieMonster cmin(store2.get(), &net_log_); CookieList cookies(GetAllCookies(&cmin)); ASSERT_EQ(2u, cookies.size()); } @@ -2169,8 +2154,7 @@ TEST_F(CookieMonsterTest, CookieListOrdering) { // Put a random set of cookies into a monster and make sure // they're returned in the right order. - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); EXPECT_TRUE( SetCookie(cm.get(), GURL("http://d.c.b.a.foo.com/aa/x.html"), "c=1")); EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.foo.com/aa/bb/cc/x.html"), @@ -2305,8 +2289,7 @@ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); // Get all cookies task that queues a task to set a cookie when executed. ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> @@ -2363,8 +2346,7 @@ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); ResultSavingCookieCallback<uint32_t> delete_callback; cm->DeleteAllAsync(base::BindOnce(&ResultSavingCookieCallback<uint32_t>::Run, @@ -2404,8 +2386,7 @@ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); GetCookieListCallback get_cookie_list_callback1; cm->GetAllCookiesAsync( @@ -2462,8 +2443,7 @@ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); // Get all cookies task that queues a task to set a cookie when executed. ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> @@ -2513,7 +2493,7 @@ TEST_F(CookieMonsterTest, FlushStore) { auto counter = base::MakeRefCounted<CallbackCounter>(); auto store = base::MakeRefCounted<FlushablePersistentStore>(); - auto cm = std::make_unique<CookieMonster>(store, nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(store, &net_log_); ASSERT_EQ(0, store->flush_count()); ASSERT_EQ(0, counter->callback_count()); @@ -2548,7 +2528,7 @@ ASSERT_EQ(2, counter->callback_count()); // If there's no backing store, FlushStore() is always a safe no-op. - cm.reset(new CookieMonster(nullptr, nullptr, &net_log_)); + cm.reset(new CookieMonster(nullptr, &net_log_)); GetAllCookies(cm.get()); // Force init. cm->FlushStore(base::DoNothing()); base::RunLoop().RunUntilIdle(); @@ -2561,23 +2541,9 @@ ASSERT_EQ(3, counter->callback_count()); } -TEST_F(CookieMonsterTest, SetBeforeCommitCallbackIsCalled) { - std::unique_ptr<ChannelIDService> channel_id_service( - new ChannelIDService(nullptr)); - - scoped_refptr<NewMockPersistentCookieStore> store( - new NewMockPersistentCookieStore()); - - // SetBeforeCommitCallback should be called in both the c'tor and d'tor. - EXPECT_CALL(*store, SetBeforeCommitCallback(testing::_)).Times(2); - - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), channel_id_service.get(), &net_log_)); -} - TEST_F(CookieMonsterTest, SetAllCookies) { scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); - auto cm = std::make_unique<CookieMonster>(store.get(), nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(store.get(), &net_log_); cm->SetPersistSessionCookies(true); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "U=V; path=/")); @@ -2640,7 +2606,7 @@ // works). TEST_F(CookieMonsterTest, DeleteAll) { scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); - auto cm = std::make_unique<CookieMonster>(store.get(), nullptr, &net_log_); + auto cm = std::make_unique<CookieMonster>(store.get(), &net_log_); cm->SetPersistSessionCookies(true); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "X=Y; path=/")); @@ -2668,8 +2634,7 @@ } TEST_F(CookieMonsterTest, HistogramCheck) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); // Should match call in InitializeHistograms, but doesn't really matter // since the histogram should have been initialized by the CM construction // above. @@ -2711,8 +2676,7 @@ // CookieStore if the "persist session cookies" option is on. TEST_F(CookieMonsterTest, PersistSessionCookies) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); cm->SetPersistSessionCookies(true); // All cookies set with SetCookie are session cookies. @@ -2749,8 +2713,7 @@ // Test the commands sent to the persistent cookie store. TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); // Add a cookie. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), @@ -2819,8 +2782,7 @@ // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url)); } @@ -2831,8 +2793,7 @@ const std::string cookie_source_histogram = "Cookie.CookieSourceScheme"; scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); histograms.ExpectTotalCount(cookie_source_histogram, 0); @@ -2894,8 +2855,7 @@ const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent"; scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_)); // Set a secure cookie from a secure origin EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "A=B; Secure")); @@ -2993,8 +2953,7 @@ } TEST_F(CookieMonsterTest, SetSecureCookies) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, &net_log_)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_)); GURL http_url("http://www.foo.com"); GURL http_superdomain_url("http://foo.com"); GURL https_url("https://www.foo.com"); @@ -3264,8 +3223,7 @@ // Tests that strict secure cookies doesn't trip equivalent cookie checks // accidentally. Regression test for https://crbug.com/569943. TEST_F(CookieMonsterTest, EquivalentCookies) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); GURL http_url("http://www.foo.com"); GURL http_superdomain_url("http://foo.com"); GURL https_url("https://www.foo.com"); @@ -3293,7 +3251,7 @@ base::MakeRefCounted<MockPersistentCookieStore>(); // Collect load commands so we have control over their execution. persistent_store->set_store_load_commands(true); - CookieMonster cm(persistent_store.get(), nullptr, nullptr); + CookieMonster cm(persistent_store.get(), nullptr); // Start of a canonical cookie set. ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> @@ -3341,7 +3299,7 @@ // that the implementation doesn't just happen to pick the right one because // of implementation details. for (size_t run = 0; run < base::size(kNames); ++run) { - CookieMonster cm(nullptr, nullptr, nullptr); + CookieMonster cm(nullptr, nullptr); Time now = Time::Now(); GURL url("http://www.example.com"); @@ -3378,7 +3336,7 @@ GURL url("http://www.example.com"); std::string cookie_line = "foo=bar"; CookieOptions options; - CookieMonster cm(nullptr, nullptr, nullptr); + CookieMonster cm(nullptr, nullptr); // Write a cookie created at |t1|. auto cookie = CanonicalCookie::Create(url, cookie_line, t1, options); @@ -3418,7 +3376,7 @@ CookieMonsterNotificationTest() : test_url_("http://www.foo.com/foo"), store_(new MockPersistentCookieStore), - monster_(new CookieMonster(store_.get(), nullptr, nullptr)) {} + monster_(new CookieMonster(store_.get(), nullptr)) {} ~CookieMonsterNotificationTest() override = default; @@ -3449,7 +3407,7 @@ store->set_store_load_commands(true); // Bind it to a CookieMonster - auto monster = std::make_unique<CookieMonster>(store.get(), nullptr, nullptr); + auto monster = std::make_unique<CookieMonster>(store.get(), nullptr); // Trigger load dispatch and confirm it. monster->GetAllCookiesAsync(CookieStore::GetCookieListCallback());
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc index 70675bc1..813bfe1 100644 --- a/net/cookies/cookie_store_test_helpers.cc +++ b/net/cookies/cookie_store_test_helpers.cc
@@ -65,7 +65,6 @@ DelayedCookieMonster::DelayedCookieMonster() : cookie_monster_(new CookieMonster(nullptr /* store */, - nullptr /* channel_id_service */, nullptr /* netlog */)), did_run_(false), result_(
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc index 0043b78d..9bf3935 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -1227,7 +1227,7 @@ // Create a cookie on a scheme that doesn't handle cookies by default, // and save it. std::unique_ptr<CookieMonster> cookie_monster = - std::make_unique<CookieMonster>(store_.get(), nullptr, nullptr); + std::make_unique<CookieMonster>(store_.get(), nullptr); cookie_monster->SetCookieableSchemes({"gopher", "http"}); ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> set_cookie_callback; @@ -1267,8 +1267,7 @@ // instances, so they should complete before the new PersistentCookieStore // starts looking at the state on disk. Create(false, false, true /* want current thread to invoke cookie monster */); - cookie_monster = - std::make_unique<CookieMonster>(store_.get(), nullptr, nullptr); + cookie_monster = std::make_unique<CookieMonster>(store_.get(), nullptr); cookie_monster->SetCookieableSchemes({"gopher", "http"}); // Now try to get the cookie back. @@ -1293,7 +1292,7 @@ base::CreateDirectory(temp_dir_.GetPath().Append(kCookieFilename))); Create(false, false, true /* want current thread to invoke cookie monster */); std::unique_ptr<CookieMonster> cookie_monster = - std::make_unique<CookieMonster>(store_.get(), nullptr, nullptr); + std::make_unique<CookieMonster>(store_.get(), nullptr); ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> set_cookie_callback;
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index f942365..05b0d28 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -846,10 +846,11 @@ return; session_deps_.host_resolver->set_synchronous_mode(true); - // The SPDY CONNECT request should have a priority of HIGHEST. + // The SPDY CONNECT request should have a priority of MEDIUM, even though the + // ConnectJob's priority is set to HIGHEST after connection establishment. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( nullptr /* extra_headers */, 0 /* extra_header_count */, - 1 /* stream_id */, HIGHEST, HostPortPair(kEndpointHost, 443))); + 1 /* stream_id */, MEDIUM, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0, ASYNC)}; spdy::SpdySerializedFrame resp( spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index d2350cb..a9a38c4 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -8226,6 +8226,72 @@ EXPECT_TRUE(mock_quic_data.AllWriteDataConsumed()); } +// Makes sure the CONNECT request packet for a QUIC proxy contains the correct +// HTTP/2 stream dependency and weights given the request priority. +TEST_P(QuicNetworkTransactionTest, QuicProxyMultipleRequestsError) { + session_params_.enable_quic = true; + session_params_.enable_quic_proxies_for_https_urls = true; + proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult( + "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS); + + const RequestPriority kRequestPriority = MEDIUM; + const RequestPriority kRequestPriority2 = LOWEST; + + MockQuicData mock_quic_data; + quic::QuicStreamOffset header_stream_offset = 0; + mock_quic_data.AddWrite( + ASYNC, ConstructInitialSettingsPacket(1, &header_stream_offset)); + mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED); + // This should never be reached. + mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED); + mock_quic_data.AddSocketDataToFactory(&socket_factory_); + + // Second connection attempt just fails - result doesn't really matter. + MockQuicData mock_quic_data2; + mock_quic_data2.AddConnect(SYNCHRONOUS, ERR_FAILED); + mock_quic_data2.AddSocketDataToFactory(&socket_factory_); + + int original_max_sockets_per_group = + ClientSocketPoolManager::max_sockets_per_group( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL); + ClientSocketPoolManager::set_max_sockets_per_group( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL, 1); + int original_max_sockets_per_pool = + ClientSocketPoolManager::max_sockets_per_pool( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL); + ClientSocketPoolManager::set_max_sockets_per_pool( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL, 1); + CreateSession(); + + request_.url = GURL("https://mail.example.org/"); + HttpNetworkTransaction trans(kRequestPriority, session_.get()); + TestCompletionCallback callback; + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + HttpRequestInfo request2; + request2.url = GURL("https://mail.example.org/some/other/path/"); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + HttpNetworkTransaction trans2(kRequestPriority2, session_.get()); + TestCompletionCallback callback2; + int rv2 = trans2.Start(&request2, callback2.callback(), net_log_.bound()); + EXPECT_EQ(ERR_IO_PENDING, rv2); + + EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback.WaitForResult()); + EXPECT_TRUE(mock_quic_data.AllWriteDataConsumed()); + + EXPECT_EQ(ERR_FAILED, callback2.WaitForResult()); + + ClientSocketPoolManager::set_max_sockets_per_pool( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL, + original_max_sockets_per_pool); + ClientSocketPoolManager::set_max_sockets_per_group( + HttpNetworkSession::SocketPoolType::NORMAL_SOCKET_POOL, + original_max_sockets_per_group); +} + // Test the request-challenge-retry sequence for basic auth, over a QUIC // connection when setting up a QUIC proxy tunnel. TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) {
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc index db69ce0..e6f2b811 100644 --- a/net/quic/quic_proxy_client_socket.cc +++ b/net/quic/quic_proxy_client_socket.cc
@@ -79,9 +79,13 @@ return kProtoQUIC; } -void QuicProxyClientSocket::SetStreamPriority(RequestPriority priority) { - stream_->SetPriority(ConvertRequestPriorityToQuicPriority(priority)); -} +// Ignore priority changes, just use priority of initial request. Since multiple +// requests are pooled on the QuicProxyClientSocket, reprioritization doesn't +// really work. +// +// TODO(mmenke): Use a single priority value for all QuicProxyClientSockets, +// regardless of what priority they're created with. +void QuicProxyClientSocket::SetStreamPriority(RequestPriority priority) {} // Sends a HEADERS frame to the proxy with a CONNECT request // for the specified endpoint. Waits for the server to send back
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc index d693d21..e5ed0a6 100644 --- a/net/quic/quic_proxy_client_socket_unittest.cc +++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -834,8 +834,10 @@ TEST_P(QuicProxyClientSocketTest, SetStreamPriority) { mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1)); + // Despite setting the priority to HIGHEST, the requets initial priority of + // LOWEST is used. mock_quic_data_.AddWrite(SYNCHRONOUS, - ConstructConnectRequestPacket(2, HIGHEST)); + ConstructConnectRequestPacket(2, LOWEST)); mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin)); mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); mock_quic_data_.AddWrite(
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 05897576..7ffa4ab 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -7,8 +7,10 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" +#include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/stl_util.h" +#include "base/test/bind_test_util.h" #include "base/test/scoped_feature_list.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" @@ -1303,6 +1305,259 @@ } } +// Make sure there's no crash when an auth challenge is received over HTTP2 +// and there are two pending Requests to the socket pool, with a single +// ConnectJob. +// +// See https://crbug.com/940848 +TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) { + const HostPortPair kEndpoint("unresolvable.host.name", 443); + const HostPortPair kProxy("unresolvable.proxy.name", 443); + + session_deps_.host_resolver->set_synchronous_mode(true); + + // Create a socket pool which only allows a single connection at a time. + TransportClientSocketPool pool( + 1, 1, kUnusedIdleSocketTimeout, &tagging_client_socket_factory_, + session_deps_.host_resolver.get(), nullptr /* proxy_delegate */, + nullptr /* http_user_agent_settings */, session_deps_.cert_verifier.get(), + nullptr /* channel_id_server */, + session_deps_.transport_security_state.get(), + session_deps_.cert_transparency_verifier.get(), + session_deps_.ct_policy_enforcer.get(), + nullptr /* ssl_client_session_cache */, + nullptr /* ssl_client_session_cache_privacy_mode */, + session_deps_.ssl_config_service.get(), + nullptr /* socket_performance_watcher_factory */, + nullptr /* network_quality_estimator */, nullptr /* net_log */); + + // First connection attempt will get an error after creating the SpdyStream. + + SpdyTestUtil spdy_util; + spdy::SpdySerializedFrame connect( + spdy_util.ConstructSpdyConnect(nullptr, 0, 1, HIGHEST, kEndpoint)); + + MockWrite writes[] = { + CreateMockWrite(connect, 0, ASYNC), + MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 2), + }; + + MockRead reads[] = { + MockRead(ASYNC, ERR_FAILED, 1), + }; + + SequencedSocketData socket_data(MockConnect(SYNCHRONOUS, OK), reads, writes); + tagging_client_socket_factory_.AddSocketDataProvider(&socket_data); + SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK); + ssl_data.next_proto = kProtoHTTP2; + tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data); + + // Second connection also fails. Not a vital part of this test, but allows + // waiting for the second request to complete without too much extra code. + SequencedSocketData socket_data2( + MockConnect(SYNCHRONOUS, ERR_CONNECTION_TIMED_OUT), + base::span<const MockRead>(), base::span<const MockWrite>()); + tagging_client_socket_factory_.AddSocketDataProvider(&socket_data2); + SSLSocketDataProvider ssl_data2(SYNCHRONOUS, OK); + tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + + scoped_refptr<TransportSocketParams> transport_params = + base::MakeRefCounted<TransportSocketParams>( + kProxy, false /* disable_resolver_cache */, + OnHostResolutionCallback()); + + scoped_refptr<SSLSocketParams> proxy_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + transport_params, nullptr /* socks_proxy_params */, + nullptr /* http_proxy_params */, kProxy, GetSSLConfig(), + PRIVACY_MODE_DISABLED); + + scoped_refptr<HttpProxySocketParams> http_proxy_params = + base::MakeRefCounted<HttpProxySocketParams>( + nullptr /* transport_params */, proxy_ssl_params, + quic::QUIC_VERSION_UNSUPPORTED, kEndpoint, + http_network_session_->http_auth_cache(), + http_network_session_->http_auth_handler_factory(), + http_network_session_->spdy_session_pool(), + nullptr /* quic_stream_factory */, false /* is_trusted_proxy */, + true /* tunnel */, TRAFFIC_ANNOTATION_FOR_TESTS); + scoped_refptr<SSLSocketParams> endpoint_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + nullptr /* direct_params */, nullptr /* socks_proxy_params */, + http_proxy_params, kEndpoint, GetSSLConfig(), PRIVACY_MODE_DISABLED); + + scoped_refptr<TransportClientSocketPool::SocketParams> pool_params = + TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams( + endpoint_ssl_params); + + // Start the first connection attempt. + TestCompletionCallback callback1; + ClientSocketHandle handle1; + int rv1 = handle1.Init( + "a", pool_params, HIGHEST, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback1.callback(), + ClientSocketPool::ProxyAuthCallback(), &pool, NetLogWithSource()); + ASSERT_THAT(rv1, IsError(ERR_IO_PENDING)); + + // Create a second request with a lower priority. + TestCompletionCallback callback2; + ClientSocketHandle handle2; + int rv2 = handle2.Init( + "a", pool_params, LOWEST, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback2.callback(), + ClientSocketPool::ProxyAuthCallback(), &pool, NetLogWithSource()); + ASSERT_THAT(rv2, IsError(ERR_IO_PENDING)); + + // First connection fails after creating a SpdySession and a SpdyStream on + // that session. The SpdyStream will be destroyed under the + // SpdyProxyClientSocket. The failure will result in temporarily assigning the + // failed ConnectJob to the second request, which results in an unneeded + // reprioritization, which should not dereference the null SpdyStream. + // + // TODO(mmenke): Avoid that temporary reassignment. + ASSERT_THAT(callback1.WaitForResult(), IsError(ERR_FAILED)); + + // Second connection fails, getting a connection error. + ASSERT_THAT(callback2.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED)); +} + +// Make sure there's no crash when an auth challenge is received over HTTP2 +// and there are two pending Requests to the socket pool, with a single +// ConnectJob. +// +// See https://crbug.com/940848 +TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) { + const HostPortPair kEndpoint("unresolvable.host.name", 443); + const HostPortPair kProxy("unresolvable.proxy.name", 443); + + session_deps_.host_resolver->set_synchronous_mode(true); + + // Create a socket pool which only allows a single connection at a time. + TransportClientSocketPool pool( + 1, 1, kUnusedIdleSocketTimeout, &tagging_client_socket_factory_, + session_deps_.host_resolver.get(), nullptr /* proxy_delegate */, + nullptr /* http_user_agent_settings */, session_deps_.cert_verifier.get(), + nullptr /* channel_id_server */, + session_deps_.transport_security_state.get(), + session_deps_.cert_transparency_verifier.get(), + session_deps_.ct_policy_enforcer.get(), + nullptr /* ssl_client_session_cache */, + nullptr /* ssl_client_session_cache_privacy_mode */, + session_deps_.ssl_config_service.get(), + nullptr /* socket_performance_watcher_factory */, + nullptr /* network_quality_estimator */, nullptr /* net_log */); + + SpdyTestUtil spdy_util; + spdy::SpdySerializedFrame connect( + spdy_util.ConstructSpdyConnect(nullptr, 0, 1, HIGHEST, kEndpoint)); + + MockWrite writes[] = { + CreateMockWrite(connect, 0, ASYNC), + MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 4), + }; + + // The proxy responds to the connect with a 407, and them an + // ERROR_CODE_HTTP_1_1_REQUIRED. + + const char kAuthStatus[] = "407"; + const char* const kAuthChallenge[] = { + "proxy-authenticate", + "NTLM", + }; + spdy::SpdySerializedFrame connect_auth_resp(spdy_util.ConstructSpdyReplyError( + kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1)); + spdy::SpdySerializedFrame reset( + spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED)); + MockRead reads[] = { + CreateMockRead(connect_auth_resp, 1, ASYNC), + CreateMockRead(reset, 2, SYNCHRONOUS), + MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), + }; + + SequencedSocketData socket_data(MockConnect(SYNCHRONOUS, OK), reads, writes); + tagging_client_socket_factory_.AddSocketDataProvider(&socket_data); + SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK); + ssl_data.next_proto = kProtoHTTP2; + tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data); + + // Second connection fails, and gets a different error. Not a vital part of + // this test, but allows waiting for the second request to complete without + // too much extra code. + SequencedSocketData socket_data2( + MockConnect(SYNCHRONOUS, ERR_CONNECTION_TIMED_OUT), + base::span<const MockRead>(), base::span<const MockWrite>()); + tagging_client_socket_factory_.AddSocketDataProvider(&socket_data2); + SSLSocketDataProvider ssl_data2(SYNCHRONOUS, OK); + tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + + scoped_refptr<TransportSocketParams> transport_params = + base::MakeRefCounted<TransportSocketParams>( + kProxy, false /* disable_resolver_cache */, + OnHostResolutionCallback()); + + scoped_refptr<SSLSocketParams> proxy_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + transport_params, nullptr /* socks_proxy_params */, + nullptr /* http_proxy_params */, kProxy, GetSSLConfig(), + PRIVACY_MODE_DISABLED); + + scoped_refptr<HttpProxySocketParams> http_proxy_params = + base::MakeRefCounted<HttpProxySocketParams>( + nullptr /* transport_params */, proxy_ssl_params, + quic::QUIC_VERSION_UNSUPPORTED, kEndpoint, + http_network_session_->http_auth_cache(), + http_network_session_->http_auth_handler_factory(), + http_network_session_->spdy_session_pool(), + nullptr /* quic_stream_factory */, false /* is_trusted_proxy */, + true /* tunnel */, TRAFFIC_ANNOTATION_FOR_TESTS); + scoped_refptr<SSLSocketParams> endpoint_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + nullptr /* direct_params */, nullptr /* socks_proxy_params */, + http_proxy_params, kEndpoint, GetSSLConfig(), PRIVACY_MODE_DISABLED); + + scoped_refptr<TransportClientSocketPool::SocketParams> pool_params = + TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams( + endpoint_ssl_params); + + // Start the first connection attempt. + TestCompletionCallback callback1; + ClientSocketHandle handle1; + base::RunLoop run_loop; + int rv1 = handle1.Init("a", pool_params, HIGHEST, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, + callback1.callback(), + base::BindLambdaForTesting( + [&](const HttpResponseInfo& response, + HttpAuthController* auth_controller, + base::OnceClosure restart_with_auth_callback) { + run_loop.Quit(); + }), + &pool, NetLogWithSource()); + ASSERT_THAT(rv1, IsError(ERR_IO_PENDING)); + + // Create a second request with a lower priority. + TestCompletionCallback callback2; + ClientSocketHandle handle2; + int rv2 = handle2.Init( + "a", pool_params, LOWEST, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback2.callback(), + ClientSocketPool::ProxyAuthCallback(), &pool, NetLogWithSource()); + ASSERT_THAT(rv2, IsError(ERR_IO_PENDING)); + + // The ConnectJob connection sees the auth challenge and HTTP2 error, which + // causes the SpdySession to be destroyed, as well as the SpdyStream. Then the + // ConnectJob is bound to the first request. Binding the request will result + // in temporarily assigning the ConnectJob to the second request, which + // results in an unneeded reprioritization, which should not dereference the + // null SpdyStream. + // + // TODO(mmenke): Avoid that temporary reassignment. + run_loop.Run(); + + // Just tear down everything without continuing - there are other tests for + // auth over HTTP2. +} + // Test that SocketTag passed into TransportClientSocketPool is applied to // returned sockets. #if defined(OS_ANDROID)
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index e25c7be..c64dcb3 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -91,9 +91,13 @@ return spdy_stream_->GetNegotiatedProtocol(); } -void SpdyProxyClientSocket::SetStreamPriority(RequestPriority priority) { - spdy_stream_->SetPriority(priority); -} +// Ignore priority changes, just use priority of initial request. Since multiple +// requests are pooled on the SpdyProxyClientSocket, reprioritization doesn't +// really work. +// +// TODO(mmenke): Use a single priority value for all SpdyProxyClientSockets, +// regardless of what priority they're created with. +void SpdyProxyClientSocket::SetStreamPriority(RequestPriority priority) {} // Sends a HEADERS frame to the proxy with a CONNECT request // for the specified endpoint. Waits for the server to send back
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 7252716..9fb91f3 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -135,7 +135,7 @@ void PopulateConnectRequestIR(spdy::SpdyHeaderBlock* syn_ir); void PopulateConnectReplyIR(spdy::SpdyHeaderBlock* block, const char* status); spdy::SpdySerializedFrame ConstructConnectRequestFrame( - RequestPriority priority); + RequestPriority priority = LOWEST); spdy::SpdySerializedFrame ConstructConnectAuthRequestFrame(); spdy::SpdySerializedFrame ConstructConnectReplyFrame(); spdy::SpdySerializedFrame ConstructConnectAuthReplyFrame(); @@ -425,7 +425,7 @@ // Constructs a standard SPDY HEADERS frame for a CONNECT request. spdy::SpdySerializedFrame SpdyProxyClientSocketTest::ConstructConnectRequestFrame( - RequestPriority priority = LOWEST) { + RequestPriority priority) { spdy::SpdyHeaderBlock block; PopulateConnectRequestIR(&block); return spdy_util_.ConstructSpdyHeaders(kStreamId, std::move(block), priority, @@ -605,7 +605,7 @@ } TEST_P(SpdyProxyClientSocketTest, SetStreamPriority) { - spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame(HIGHEST)); + spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame(LOWEST)); MockWrite writes[] = { CreateMockWrite(conn, 0, SYNCHRONOUS), }; @@ -618,6 +618,8 @@ Initialize(reads, writes); + // Set the stream priority. Since a connection was already established, it's + // too late to adjust the HTTP2 stream's priority, and the request is ignored. sock_->SetStreamPriority(HIGHEST); AssertConnectSucceeds();
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index c3dec2e..823f678 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -962,7 +962,8 @@ block["hello"] = "bye"; AppendToHeaderBlock(extra_headers, extra_header_count, &block); - return ConstructSpdyReply(stream_id, std::move(block)); + spdy::SpdyHeadersIR reply(stream_id, std::move(block)); + return spdy::SpdySerializedFrame(response_spdy_framer_.SerializeFrame(reply)); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError(int stream_id) {
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 5c7d056..eff048b 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -453,8 +453,7 @@ storage->set_cookie_store(std::move(cookie_store_)); } else { std::unique_ptr<CookieStore> cookie_store( - new CookieMonster(nullptr /* store */, nullptr /* channel_id_service */, - context->net_log())); + new CookieMonster(nullptr /* store */, context->net_log())); storage->set_cookie_store(std::move(cookie_store)); }
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 5a016a7a..1594cd4 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -103,8 +103,7 @@ // In-memory cookie store. if (!cookie_store()) { context_storage_.set_cookie_store(std::make_unique<CookieMonster>( - nullptr /* store */, nullptr /* channel_id_service */, - nullptr /* netlog */)); + nullptr /* store */, nullptr /* netlog */)); } // In-memory Channel ID service. Must be created before the
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index eb1c0157..c71e8ad 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -2650,7 +2650,7 @@ TestURLRequestContext sync_context; std::unique_ptr<CookieMonster> cm = - std::make_unique<CookieMonster>(nullptr, nullptr, nullptr); + std::make_unique<CookieMonster>(nullptr, nullptr); sync_context.set_cookie_store(cm.get()); FilteringTestLayeredNetworkDelegate sync_filter_network_delegate( std::make_unique<TestNetworkDelegate>());
diff --git a/remoting/protocol/webrtc_audio_stream.cc b/remoting/protocol/webrtc_audio_stream.cc index 3028b01..1f198be8 100644 --- a/remoting/protocol/webrtc_audio_stream.cc +++ b/remoting/protocol/webrtc_audio_stream.cc
@@ -52,6 +52,8 @@ audio_sender_ = peer_connection_->AddTrack(audio_track.get(), {kAudioStreamLabel}) .value(); + + webrtc_transport->OnAudioSenderCreated(audio_sender_); } void WebrtcAudioStream::Pause(bool pause) {
diff --git a/remoting/protocol/webrtc_audio_stream.h b/remoting/protocol/webrtc_audio_stream.h index 75ac45e..13baf221 100644 --- a/remoting/protocol/webrtc_audio_stream.h +++ b/remoting/protocol/webrtc_audio_stream.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "remoting/protocol/audio_stream.h" +#include "third_party/webrtc/api/scoped_refptr.h" namespace base { class SingleThreadTaskRunner; @@ -43,7 +44,7 @@ scoped_refptr<WebrtcAudioSourceAdapter> source_adapter_; scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; - scoped_refptr<webrtc::RtpSenderInterface> audio_sender_; + rtc::scoped_refptr<webrtc::RtpSenderInterface> audio_sender_; DISALLOW_COPY_AND_ASSIGN(WebrtcAudioStream); };
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index 24df24a..48f2e5b 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -490,6 +490,11 @@ weak_factory_.GetWeakPtr(), type == webrtc::SessionDescriptionInterface::kOffer)), session_description.release()); + + // SetRemoteDescription() might overwrite any bitrate caps previously set, + // so (re)apply them here. This might happen if ICE state were already + // connected and OnStatsDelivered() had already set the caps. + SetPeerConnectionBitrates(MaxBitrateForConnection()); } XmlElement* candidate_element; @@ -556,6 +561,17 @@ } } +void WebrtcTransport::OnAudioSenderCreated( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender) {} + +void WebrtcTransport::OnVideoSenderCreated( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender) { + // TODO(lambroslambrou): Store the VideoSender here, instead of looping over + // all Senders in GetVideoSender(). + DCHECK_EQ(GetVideoSender(), sender); + SetSenderBitrates(MaxBitrateForConnection()); +} + void WebrtcTransport::OnLocalSessionDescriptionCreated( std::unique_ptr<webrtc::SessionDescriptionInterface> description, const std::string& error) { @@ -777,8 +793,24 @@ LOG(ERROR) << "Connection type unknown, treating as direct."; } + // The max-bitrate needs to be applied even for direct (non-TURN) connections. + // Otherwise the video-sender b/w estimate is capped to a low default value + // (~600kbps). + // Set the global bitrate caps in addition to the VideoSender bitrates. The + // global caps affect the probing configuration used by b/w estimator. + // Setting min bitrate here enables padding. + // + // TODO(sergeyu): Padding needs to be enabled to workaround b/w estimator not + // handling spiky traffic patterns well. This won't be necessary with a + // better bandwidth estimator. + int max_bitrate_bps = MaxBitrateForConnection(); + SetPeerConnectionBitrates(max_bitrate_bps); + SetSenderBitrates(max_bitrate_bps); +} + +int WebrtcTransport::MaxBitrateForConnection() { int max_bitrate_bps = kMaxBitrateBps; - if (connection_relayed.value_or(false)) { + if (connection_relayed_.value_or(false)) { int turn_max_rate_kbps = transport_context_->GetTurnMaxRateKbps(); if (turn_max_rate_kbps <= 0) { VLOG(0) << "No TURN bitrate cap set."; @@ -790,22 +822,17 @@ max_bitrate_bps = turn_max_rate_kbps * 1000; } } + return max_bitrate_bps; +} - // The max-bitrate needs to be applied even for direct (non-TURN) connections. - // Otherwise the video-sender b/w estimate is capped to a low default value - // (~600kbps). - // Set the global bitrate caps in addition to the VideoSender bitrates. The - // global caps affect the probing configuration used by b/w estimator. - // Setting min bitrate here enables padding. - // - // TODO(sergeyu): Padding needs to be enabled to workaround b/w estimator not - // handling spiky traffic patterns well. This won't be necessary with a - // better bandwidth estimator. +void WebrtcTransport::SetPeerConnectionBitrates(int max_bitrate_bps) { webrtc::BitrateSettings bitrate; bitrate.min_bitrate_bps = kMinBitrateBps; bitrate.max_bitrate_bps = max_bitrate_bps; peer_connection()->SetBitrate(bitrate); +} +void WebrtcTransport::SetSenderBitrates(int max_bitrate_bps) { // Only set the cap on the VideoSender, because the AudioSender (via the // Opus codec) is already configured with a lower bitrate. rtc::scoped_refptr<webrtc::RtpSenderInterface> sender = GetVideoSender(); @@ -828,7 +855,8 @@ parameters.encodings[0].min_bitrate_bps = kMinBitrateBps; parameters.encodings[0].max_bitrate_bps = max_bitrate_bps; - sender->SetParameters(parameters); + webrtc::RTCError result = sender->SetParameters(parameters); + DCHECK(result.ok()) << "SetParameters() failed: " << result.message(); } void WebrtcTransport::RequestRtcStats() {
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h index b773b13..ebd97c7a 100644 --- a/remoting/protocol/webrtc_transport.h +++ b/remoting/protocol/webrtc_transport.h
@@ -88,6 +88,16 @@ void ApplySessionOptions(const SessionOptions& options); + // Called when a new AudioSender has been created from + // PeerConnection::AddTrack(). + void OnAudioSenderCreated( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender); + + // Called when a new VideoSender has been created from + // PeerConnection::AddTrack(). + void OnVideoSenderCreated( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender); + private: // PeerConnectionWrapper is responsible for PeerConnection creation, // ownership. It passes all events to the corresponding methods below. This is @@ -122,6 +132,20 @@ void OnStatsDelivered( const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report); + // Returns the max bitrate to set for this connection, taking into + // account any relay bitrate cap. If the relay status is unknown, this + // returns the default maximum bitrate. + int MaxBitrateForConnection(); + + // Sets bitrates on the PeerConnection. + // Called after SetRemoteDescription(), but also called if the relay status + // changes. + void SetPeerConnectionBitrates(int max_bitrate_bps); + + // Sets bitrates on the (video) sender. Called when the sender is created, but + // also called if the relay status changes. + void SetSenderBitrates(int max_bitrate_bps); + void RequestRtcStats(); void RequestNegotiation(); void SendOffer();
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc index 570c794..6e4331d 100644 --- a/remoting/protocol/webrtc_video_stream.cc +++ b/remoting/protocol/webrtc_video_stream.cc
@@ -140,6 +140,8 @@ video_sender_ = peer_connection_->AddTrack(video_track.get(), {kStreamLabel}).value(); + webrtc_transport_->OnVideoSenderCreated(video_sender_); + scheduler_.reset(new WebrtcFrameSchedulerSimple(session_options_)); scheduler_->Start( webrtc_transport_->video_encoder_factory(),
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h index b19c8ae1..07a3cfc 100644 --- a/remoting/protocol/webrtc_video_stream.h +++ b/remoting/protocol/webrtc_video_stream.h
@@ -21,6 +21,7 @@ #include "remoting/codec/webrtc_video_encoder_selector.h" #include "remoting/protocol/host_video_stats_dispatcher.h" #include "remoting/protocol/video_stream.h" +#include "third_party/webrtc/api/scoped_refptr.h" #include "third_party/webrtc/common_types.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" @@ -87,7 +88,7 @@ scoped_refptr<InputEventTimestampsSource> event_timestamps_source_; scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; - scoped_refptr<webrtc::RtpSenderInterface> video_sender_; + rtc::scoped_refptr<webrtc::RtpSenderInterface> video_sender_; HostVideoStatsDispatcher video_stats_dispatcher_;
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index ed80305c..e24b27a 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc
@@ -10,15 +10,16 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/rand_util.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/task/task_scheduler/task_scheduler.h" #include "base/task_runner_util.h" +#include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "jingle/glue/thread_wrapper.h" +#include "net/base/network_change_notifier.h" #include "net/test/test_data_directory.h" #include "net/url_request/url_request_context_getter.h" #include "remoting/base/rsa_key_pair.h" @@ -51,6 +52,7 @@ namespace remoting { +using base::test::ScopedTaskEnvironment; using protocol::ChannelConfig; namespace { @@ -106,7 +108,8 @@ public HostStatusObserver { public: ProtocolPerfTest() - : host_thread_("host"), + : task_environment_(ScopedTaskEnvironment::MainThreadType::IO), + host_thread_("host"), capture_thread_("capture"), encode_thread_("encode"), decode_thread_("decode") { @@ -116,7 +119,7 @@ encode_thread_.Start(); decode_thread_.Start(); - base::TaskScheduler::CreateAndStartWithDefaultParams("ProtocolPerfTest"); + network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); desktop_environment_factory_.reset( new FakeDesktopEnvironmentFactory(capture_thread_.task_runner())); @@ -195,7 +198,7 @@ } void OnClientConnected(const std::string& jid) override { - message_loop_.task_runner()->PostTask( + task_environment_.GetMainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ProtocolPerfTest::OnHostConnectedMainThread, base::Unretained(this))); } @@ -322,7 +325,7 @@ host_->status_monitor()->AddStatusObserver(this); host_->Start(kHostOwner); - message_loop_.task_runner()->PostTask( + task_environment_.GetMainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ProtocolPerfTest::StartClientAfterHost, base::Unretained(this))); } @@ -377,7 +380,7 @@ void MeasureTotalLatency(bool use_webrtc); void MeasureScrollPerformance(bool use_webrtc); - base::MessageLoopForIO message_loop_; + ScopedTaskEnvironment task_environment_; scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; @@ -418,6 +421,8 @@ std::unique_ptr<webrtc::DesktopFrame> last_video_frame_; std::vector<protocol::FrameStats> frame_stats_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; + private: DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); };
diff --git a/services/data_decoder/public/cpp/testing_json_parser.cc b/services/data_decoder/public/cpp/testing_json_parser.cc index 2cddd953..921f8f7 100644 --- a/services/data_decoder/public/cpp/testing_json_parser.cc +++ b/services/data_decoder/public/cpp/testing_json_parser.cc
@@ -11,7 +11,7 @@ #include "base/json/json_reader.h" #include "base/location.h" #include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/values.h" namespace data_decoder { @@ -53,8 +53,8 @@ // Run the callback asynchronously. Post the delete task first, so that the // completion callbacks may quit the run loop without leaking |this|. - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, value ? base::Bind(success_callback_, base::Passed(&value)) : base::Bind(error_callback_, error)); }
diff --git a/services/identity/identity_accessor_impl.cc b/services/identity/identity_accessor_impl.cc index afff7d4..666a5e9 100644 --- a/services/identity/identity_accessor_impl.cc +++ b/services/identity/identity_accessor_impl.cc
@@ -82,14 +82,6 @@ std::move(callback).Run(account_info, account_state); } -void IdentityAccessorImpl::GetAccountInfoFromGaiaId( - const std::string& gaia_id, - GetAccountInfoFromGaiaIdCallback callback) { - AccountInfo account_info = account_tracker_->FindAccountInfoByGaiaId(gaia_id); - AccountState account_state = GetStateOfAccount(account_info); - std::move(callback).Run(account_info, account_state); -} - void IdentityAccessorImpl::GetAccessToken(const std::string& account_id, const ScopeSet& scopes, const std::string& consumer_id,
diff --git a/services/identity/identity_accessor_impl.h b/services/identity/identity_accessor_impl.h index d055c80d..97774ab 100644 --- a/services/identity/identity_accessor_impl.h +++ b/services/identity/identity_accessor_impl.h
@@ -51,9 +51,6 @@ void GetPrimaryAccountInfo(GetPrimaryAccountInfoCallback callback) override; void GetPrimaryAccountWhenAvailable( GetPrimaryAccountWhenAvailableCallback callback) override; - void GetAccountInfoFromGaiaId( - const std::string& gaia_id, - GetAccountInfoFromGaiaIdCallback callback) override; void GetAccessToken(const std::string& account_id, const ScopeSet& scopes, const std::string& consumer_id,
diff --git a/services/identity/identity_accessor_impl_unittest.cc b/services/identity/identity_accessor_impl_unittest.cc index b657d336..4093283 100644 --- a/services/identity/identity_accessor_impl_unittest.cc +++ b/services/identity/identity_accessor_impl_unittest.cc
@@ -64,15 +64,6 @@ quit_closure.Run(); } - void OnReceivedAccountInfoFromGaiaId( - base::RepeatingClosure quit_closure, - const base::Optional<AccountInfo>& account_info, - const AccountState& account_state) { - account_info_from_gaia_id_ = account_info; - account_state_from_gaia_id_ = account_state; - quit_closure.Run(); - } - void OnGotAccounts(base::RepeatingClosure quit_closure, std::vector<mojom::AccountPtr>* output, std::vector<mojom::AccountPtr> accounts) { @@ -301,35 +292,14 @@ // Set the refresh token, but don't sign in yet. std::string account_id_to_use = identity_test_environment()->MakeAccountAvailable(kTestEmail).account_id; - identity_test_environment()->SetRefreshTokenForAccount(account_id_to_use); + base::RunLoop run_loop; GetIdentityAccessorImpl()->GetPrimaryAccountWhenAvailable(base::BindRepeating( &IdentityAccessorImplTest::OnPrimaryAccountAvailable, base::Unretained(this), run_loop.QuitClosure(), base::Unretained(&account_info), base::Unretained(&account_state))); - // Verify that the account is present and has a refresh token, but that the - // primary account is not yet considered available (this also serves to ensure - // that the preceding call has been received by the IdentityAccessor before - // proceeding). - base::RunLoop run_loop2; - GetIdentityAccessorImpl()->GetAccountInfoFromGaiaId( - kTestGaiaId, - base::BindRepeating( - &IdentityAccessorImplTest::OnReceivedAccountInfoFromGaiaId, - base::Unretained(this), run_loop2.QuitClosure())); - run_loop2.Run(); - - EXPECT_TRUE(account_info_from_gaia_id_); - EXPECT_EQ(account_id_to_use, account_info_from_gaia_id_->account_id); - EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia); - EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email); - EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token); - EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account); - - EXPECT_TRUE(account_info.account_id.empty()); - // Sign the user in and check that the callback is invoked as expected (i.e., // the primary account is now considered available). std::string primary_account_id = @@ -435,65 +405,6 @@ EXPECT_TRUE(account_state.is_primary_account); } -// Check that the account info for a given GAIA ID is null if that GAIA ID is -// unknown. -TEST_F(IdentityAccessorImplTest, GetAccountInfoForUnknownGaiaID) { - base::RunLoop run_loop; - GetIdentityAccessorImpl()->GetAccountInfoFromGaiaId( - kTestGaiaId, - base::BindRepeating( - &IdentityAccessorImplTest::OnReceivedAccountInfoFromGaiaId, - base::Unretained(this), run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_FALSE(account_info_from_gaia_id_); -} - -// Check that the account info for a given GAIA ID has expected values if that -// GAIA ID is known and there is no refresh token available for it. -TEST_F(IdentityAccessorImplTest, GetAccountInfoForKnownGaiaIdNoRefreshToken) { - AccountInfo input_info; - input_info.email = kTestEmail; - input_info.gaia = kTestGaiaId; - std::string account_id = - identity_test_environment()->identity_manager()->LegacySeedAccountInfo( - input_info); - - base::RunLoop run_loop; - GetIdentityAccessorImpl()->GetAccountInfoFromGaiaId( - kTestGaiaId, - base::BindRepeating( - &IdentityAccessorImplTest::OnReceivedAccountInfoFromGaiaId, - base::Unretained(this), run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_TRUE(account_info_from_gaia_id_); - EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id); - EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia); - EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email); - EXPECT_FALSE(account_state_from_gaia_id_.has_refresh_token); - EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account); -} - -// Check that the account info for a given GAIA ID has expected values if that -// GAIA ID is known and has a refresh token available. -TEST_F(IdentityAccessorImplTest, GetAccountInfoForKnownGaiaIdRefreshToken) { - std::string account_id = - identity_test_environment()->MakeAccountAvailable(kTestEmail).account_id; - - base::RunLoop run_loop; - GetIdentityAccessorImpl()->GetAccountInfoFromGaiaId( - kTestGaiaId, - base::BindRepeating( - &IdentityAccessorImplTest::OnReceivedAccountInfoFromGaiaId, - base::Unretained(this), run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_TRUE(account_info_from_gaia_id_); - EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id); - EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia); - EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email); - EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token); - EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account); -} - // Check that the expected error is received if requesting an access token when // not signed in. TEST_F(IdentityAccessorImplTest, GetAccessTokenNotSignedIn) {
diff --git a/services/identity/public/mojom/identity_accessor.mojom b/services/identity/public/mojom/identity_accessor.mojom index 4f4f1b9..242c16c 100644 --- a/services/identity/public/mojom/identity_accessor.mojom +++ b/services/identity/public/mojom/identity_accessor.mojom
@@ -29,13 +29,6 @@ GetPrimaryAccountWhenAvailable() => (AccountInfo account_info, AccountState account_state); - // Returns the AccountInfo for the user's Google account corresponding to - // |gaia_id|, or null if the user has such corresponding account. - // |account_state| gives the current state of the account (relevant only if - // |account_info| is non-null). - GetAccountInfoFromGaiaId(string gaia_id) => (AccountInfo? account_info, - AccountState account_state); - // Returns an access token with the requested scopes for the given // |account_id|, or null if it is not possible to obtain such a token (e.g., // because the user is not signed in with that account). |expiration_time|
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc index 53a0cbb..44b7b5d 100644 --- a/services/network/cookie_manager_unittest.cc +++ b/services/network/cookie_manager_unittest.cc
@@ -243,8 +243,7 @@ scoped_refptr<SessionCleanupCookieStore> cleanup_store) { connection_error_seen_ = false; cookie_monster_ = std::make_unique<net::CookieMonster>( - std::move(store), nullptr /*channel_id_service */, - nullptr /* netlog */); + std::move(store), nullptr /* netlog */); cookie_service_ = std::make_unique<CookieManager>( cookie_monster_.get(), std::move(cleanup_store), nullptr); cookie_service_->AddRequest(mojo::MakeRequest(&cookie_service_ptr_));
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index d90c044..0493111c 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -1761,7 +1761,7 @@ std::unique_ptr<net::CookieMonster> cookie_store = std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(), - nullptr, net_log); + net_log); if (params_->persist_session_cookies) cookie_store->SetPersistSessionCookies(true);
diff --git a/services/network/public/cpp/is_potentially_trustworthy.cc b/services/network/public/cpp/is_potentially_trustworthy.cc index 30dc499..5bfa423 100644 --- a/services/network/public/cpp/is_potentially_trustworthy.cc +++ b/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -156,6 +156,93 @@ } // namespace +bool IsOriginPotentiallyTrustworthy(const url::Origin& origin) { + // The code below is based on the specification at + // https://www.w3.org/TR/powerful-features/#is-origin-trustworthy. + + // 1. If origin is an opaque origin, return "Not Trustworthy". + if (origin.opaque()) + return false; + + // 2. Assert: origin is a tuple origin. + DCHECK(!origin.opaque()); + + // 3. If origin’s scheme is either "https" or "wss", return "Potentially + // Trustworthy". + if (GURL::SchemeIsCryptographic(origin.scheme())) + return true; + + // 4. If origin’s host component matches one of the CIDR notations 127.0.0.0/8 + // or ::1/128 [RFC4632], return "Potentially Trustworthy". + // + // Diverging from the spec a bit here - in addition to the hostnames covered + // by https://www.w3.org/TR/powerful-features/#is-origin-trustworthy, the code + // below also considers "localhost" to be potentially secure. + // + // Cannot just pass |origin.host()| to |HostStringIsLocalhost|, because of the + // need to also strip the brackets from things like "[::1]". + if (net::IsLocalhost(origin.GetURL())) + return true; + + // 5. If origin’s scheme component is file, return "Potentially Trustworthy". + // + // This is somewhat redundant with the GetLocalSchemes-based check below. + if (origin.scheme() == url::kFileScheme) + return true; + + // 6. If origin’s scheme component is one which the user agent considers to be + // authenticated, return "Potentially Trustworthy". + // Note: See §7.1 Packaged Applications for detail here. + // + // Note that this ignores some schemes that are considered trustworthy by + // higher layers (e.g. see GetSchemesBypassingSecureContextCheck in //chrome). + // + // See also + // - content::ContentClient::AddAdditionalSchemes and + // content::ContentClient::Schemes::local_schemes and + // content::ContentClient::Schemes::secure_schemes + // - url::AddLocalScheme + // - url::AddSecureScheme + if (base::ContainsValue(url::GetSecureSchemes(), origin.scheme()) || + base::ContainsValue(url::GetLocalSchemes(), origin.scheme())) { + return true; + } + + // 7. If origin has been configured as a trustworthy origin, return + // "Potentially Trustworthy". + // Note: See §7.2 Development Environments for detail here. + if (IsAllowlistedAsSecureOrigin(origin, GetSecureOriginAllowlist())) + return true; + + // 8. Return "Not Trustworthy". + return false; +} + +bool IsUrlPotentiallyTrustworthy(const GURL& url) { + // The code below is based on the specification at + // https://www.w3.org/TR/powerful-features/#is-url-trustworthy. + + // 1. If url’s scheme is "data", return "Not Trustworthy". + // Note: This aligns the definition of a secure context with the de facto + // "data: URL as opaque origin" behavior that a majority of today’s + // browsers have agreed upon, rather than the de jure "data: URL inherits + // origin" behavior defined in HTML. + if (url.SchemeIs(url::kDataScheme)) + return false; + + // 2. If url is "about:blank" or "about:srcdoc", return "Potentially + // Trustworthy". + if (url.SchemeIs(url::kAboutScheme)) + return true; + + // 3. Return the result of executing §3.2 Is origin potentially trustworthy? + // on url’s origin. + // Note: The origin of blob: and filesystem: URLs is the origin of the + // context in which they were created. Therefore, blobs created in a + // trustworthy origin will themselves be potentially trustworthy. + return IsOriginPotentiallyTrustworthy(url::Origin::Create(url)); +} + const std::vector<std::string>& GetSecureOriginAllowlist() { // This function will initialize |s_allowlist| in a thread-safe way because of // the way how |static| works - invoking base::NoDestructor's constructor and
diff --git a/services/network/public/cpp/is_potentially_trustworthy.h b/services/network/public/cpp/is_potentially_trustworthy.h index 279f6c4..e465804b 100644 --- a/services/network/public/cpp/is_potentially_trustworthy.h +++ b/services/network/public/cpp/is_potentially_trustworthy.h
@@ -17,6 +17,18 @@ namespace network { +// Returns whether an origin is potentially trustworthy according to +// https://www.w3.org/TR/powerful-features/#is-origin-trustworthy. +// +// See also blink::SecurityOrigin::isPotentiallyTrustworthy. +COMPONENT_EXPORT(NETWORK_CPP) +bool IsOriginPotentiallyTrustworthy(const url::Origin& origin); + +// Returns whether a URL is potentially trustworthy according to +// https://www.w3.org/TR/powerful-features/#is-url-trustworthy. +COMPONENT_EXPORT(NETWORK_CPP) +bool IsUrlPotentiallyTrustworthy(const GURL& url); + // Return an allowlist of origins and hostname patterns that need to be // considered trustworthy. The allowlist is given by the // --unsafely-treat-insecure-origin-as-secure command-line option. See
diff --git a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc index ec7ced4..71818bca 100644 --- a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc +++ b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -17,6 +17,75 @@ network::GetSecureOriginAllowlist()); } +bool IsPotentiallyTrustworthy(const char* str) { + return network::IsUrlPotentiallyTrustworthy(GURL(str)); +} + +TEST(IsPotentiallyTrustworthy, MainTest) { + const url::Origin unique_origin; + EXPECT_FALSE(network::IsOriginPotentiallyTrustworthy(unique_origin)); + const url::Origin opaque_origin = + url::Origin::Create(GURL("https://www.example.com")) + .DeriveNewOpaqueOrigin(); + EXPECT_FALSE(network::IsOriginPotentiallyTrustworthy(opaque_origin)); + + EXPECT_TRUE(IsPotentiallyTrustworthy("about:blank")); + EXPECT_TRUE(IsPotentiallyTrustworthy("about:blank#ref")); + EXPECT_TRUE(IsPotentiallyTrustworthy("about:srcdoc")); + + EXPECT_FALSE(IsPotentiallyTrustworthy("data:test/plain;blah")); + EXPECT_FALSE(IsPotentiallyTrustworthy("javascript:alert('blah')")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("file:///test/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("file:///test/")); + EXPECT_TRUE(IsPotentiallyTrustworthy("file://localhost/test/")); + EXPECT_TRUE(IsPotentiallyTrustworthy("file://otherhost/test/")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("https://example.com/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/fun.html")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("wss://example.com/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("ws://example.com/fun.html")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("http://localhost/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("http://pumpkin.localhost/fun.html")); + EXPECT_TRUE( + IsPotentiallyTrustworthy("http://crumpet.pumpkin.localhost/fun.html")); + EXPECT_TRUE( + IsPotentiallyTrustworthy("http://pumpkin.localhost:8080/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy( + "http://crumpet.pumpkin.localhost:3000/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://localhost.com/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("https://localhost.com/fun.html")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.0.0.1/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("ftp://127.0.0.1/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.3.0.1/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/fun.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("https://127.example.com/fun.html")); + + EXPECT_TRUE(IsPotentiallyTrustworthy("http://[::1]/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::2]/fun.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://[::1].example.com/fun.html")); + + EXPECT_FALSE( + IsPotentiallyTrustworthy("filesystem:http://www.example.com/temporary/")); + EXPECT_FALSE( + IsPotentiallyTrustworthy("filesystem:ftp://www.example.com/temporary/")); + EXPECT_TRUE( + IsPotentiallyTrustworthy("filesystem:ftp://127.0.0.1/temporary/")); + EXPECT_TRUE(IsPotentiallyTrustworthy( + "filesystem:https://www.example.com/temporary/")); + + EXPECT_FALSE( + IsPotentiallyTrustworthy("blob:http://www.example.com/guid-goes-here")); + EXPECT_FALSE( + IsPotentiallyTrustworthy("blob:ftp://www.example.com/guid-goes-here")); + EXPECT_TRUE(IsPotentiallyTrustworthy("blob:ftp://127.0.0.1/guid-goes-here")); + EXPECT_TRUE( + IsPotentiallyTrustworthy("blob:https://www.example.com/guid-goes-here")); +} + class SecureOriginAllowlistTest : public testing::Test { void TearDown() override { // Ensure that we reset the allowlisted origins without any flags applied. @@ -29,15 +98,11 @@ url::Origin::Create(GURL("http://example.com/a.html")))); EXPECT_FALSE(IsAllowlistedAsSecureOrigin( url::Origin::Create(GURL("http://127.example.com/a.html")))); - // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy - // function (temporarily still in the //content layer) - // EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/a.html")); - // EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/a.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://example.com/a.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://127.example.com/a.html")); // Add http://example.com and http://127.example.com to allowlist by // command-line and see if they are now considered secure origins. - // (The command line is applied via - // ChromeContentClient::AddSecureSchemesAndOrigins) base::test::ScopedCommandLine scoped_command_line; base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); command_line->AppendSwitchASCII( @@ -50,17 +115,13 @@ url::Origin::Create(GURL("http://example.com/a.html")))); EXPECT_TRUE(IsAllowlistedAsSecureOrigin( url::Origin::Create(GURL("http://127.example.com/a.html")))); - // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy - // function (temporarily still in the //content layer) - // EXPECT_TRUE(IsPotentiallyTrustworthy("http://example.com/a.html")); - // EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.example.com/a.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("http://example.com/a.html")); + EXPECT_TRUE(IsPotentiallyTrustworthy("http://127.example.com/a.html")); // Check that similarly named sites are not considered secure. - // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy - // function (temporarily still in the //content layer) - // EXPECT_FALSE(IsPotentiallyTrustworthy("http://128.example.com/a.html")); - // EXPECT_FALSE( - // IsPotentiallyTrustworthy("http://foobar.127.example.com/a.html")); + EXPECT_FALSE(IsPotentiallyTrustworthy("http://128.example.com/a.html")); + EXPECT_FALSE( + IsPotentiallyTrustworthy("http://foobar.127.example.com/a.html")); } TEST_F(SecureOriginAllowlistTest, HostnamePatterns) { @@ -102,10 +163,7 @@ GURL input_url(test.test_input); url::Origin input_origin = url::Origin::Create(input_url); EXPECT_EQ(test.expected_secure, IsAllowlistedAsSecureOrigin(input_origin)); - // TODO(lukasza): Reintegrate this test with IsPotentiallyTrustworthy - // function (temporarily still in the //content layer) - // EXPECT_EQ(test.expected_secure, - // IsPotentiallyTrustworthy(test.test_input)); + EXPECT_EQ(test.expected_secure, IsPotentiallyTrustworthy(test.test_input)); } }
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc index 5a204d3..7b6ea91a 100644 --- a/services/network/restricted_cookie_manager_unittest.cc +++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -84,7 +84,7 @@ class RestrictedCookieManagerTest : public testing::Test { public: RestrictedCookieManagerTest() - : cookie_monster_(nullptr, nullptr, nullptr /* netlog */), + : cookie_monster_(nullptr, nullptr /* netlog */), service_(std::make_unique<RestrictedCookieManager>( &cookie_monster_, &cookie_settings_,
diff --git a/services/resource_coordinator/public/mojom/signals.mojom b/services/resource_coordinator/public/mojom/signals.mojom index d0b4a948..a269924 100644 --- a/services/resource_coordinator/public/mojom/signals.mojom +++ b/services/resource_coordinator/public/mojom/signals.mojom
@@ -27,9 +27,6 @@ kCPUUsage, kExpectedTaskQueueingDuration, kMainThreadTaskLoadIsLow, - // Network is considered almost idle when there's no more than 2 network - // connections. - kNetworkAlmostIdle, kPID, kUKMSourceId, kLifecycleState,
diff --git a/services/ws/public/mojom/window_manager.mojom b/services/ws/public/mojom/window_manager.mojom index 9b9e0df..99cef472 100644 --- a/services/ws/public/mojom/window_manager.mojom +++ b/services/ws/public/mojom/window_manager.mojom
@@ -69,6 +69,9 @@ // A small version of the application icon. Type: SkBitmap const string kAppIconSmall_Property = "prop:app-icon-small"; + // The avatar icon to display in the frame header, if any. Type: SkBitmap + const string kAvatarIcon_Property = "prop:avatar-icon"; + // The Android Java-style package name for an ARC++ window, such as // "com.google.Photos". Type: mojom::String. const string kArcPackageName_Property = "prop:arc-package-name";
diff --git a/styleguide/c++/c++-dos-and-donts.md b/styleguide/c++/c++-dos-and-donts.md index 8a3df325..9f5f4bf 100644 --- a/styleguide/c++/c++-dos-and-donts.md +++ b/styleguide/c++/c++-dos-and-donts.md
@@ -14,7 +14,7 @@ If a file isn't using the symbols from some header, remove the header. It turns out that this happens frequently in the Chromium codebase due to refactoring. -### Move inner classes into the implementation +### Move helper / inner classes into the implementation You can also forward declare classes inside a class: @@ -42,39 +42,6 @@ require the full definition at declaration time (most notably, std::deque and the STL adapters that wrap it). -### Move static implementation details to the implementation whenever possible - -If you have the class in a header file, you should try to move that from a class -member into the anonymous namespace in the implementation file. - -DON'T: - -```cpp -#include "BigImplementationDetail.h" -class PublicInterface { - public: - /* ... */ - private: - static BigImplementationDetail detail_; -}; -``` - -DO: - -```cpp -namespace { -BigImplementationDetail g_detail; -} // namespace -``` - -That way, people who don't use your interface don't need to know about or care -about `BigImplementationDetail`. - -You can do this for helper functions, too. Note that if there is more than one -class in the .cc file, it can aid clarity to define your translation-unit-scope -helpers in an anonymous namespace just above the class that uses them, instead -of at the top of the file. - ## Stop inlining code in headers *** note @@ -700,4 +667,4 @@ ```cpp // FooImpl implements the FooBase class. // FooFunction() modifies |foo_member_|. -``` \ No newline at end of file +```
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index e161fab..b314aaf 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -6215,6 +6215,706 @@ } ] }, + "linux-chromeos-code-coverage": { + "additional_compile_targets": [ + "gn_all" + ], + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "accessibility_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "app_list_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "app_shell_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ash_unittests" + }, + { + "args": [ + "--disable-features=SingleProcessMash" + ], + "name": "non_single_process_mash_ash_unittests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ash_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "aura_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_fuzzer_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "name": "webkit_unit_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "boringssl_crypto_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "boringssl_ssl_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-features=Mash", + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests", + "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.mash.browser_tests.filter" + ], + "name": "mash_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "hard_timeout": 1800 + }, + "test": "browser_tests" + }, + { + "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests" + ], + "name": "non_single_process_mash_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor" + ], + "name": "viz_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--disable-features=WebUIPolymer2", + "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_browser_tests.filter" + ], + "name": "webui_polymer1_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 4 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cacheinvalidation_unittests" + }, + { + "args": [ + "--gtest_filter=-*UsingRealWebcam*" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chrome_app_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chromedriver_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chromeos_components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chromeos_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "components_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "compositor_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 6 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests" + ], + "name": "non_single_process_mash_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-perfetto", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor" + ], + "name": "viz_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "args": [ + "--disable-features=SingleProcessMash" + ], + "name": "non_single_process_mash_content_unittests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor" + ], + "name": "viz_content_unittests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "dbus_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "events_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "exo_unittests" + }, + { + "args": [ + "--disable-features=SingleProcessMash" + ], + "name": "non_single_process_mash_exo_unittests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "exo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "filesystem_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gin_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gl_unittests_ozone" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 3 + }, + "test": "interactive_ui_tests" + }, + { + "args": [ + "--disable-features=SingleProcessMash" + ], + "name": "non_single_process_mash_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 3 + }, + "test": "interactive_ui_tests" + }, + { + "args": [ + "--disable-features=WebUIPolymer2", + "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter" + ], + "name": "webui_polymer1_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "interactive_ui_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "keyboard_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "latency_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "leveldb_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "libjingle_xmpp_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "message_center_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_core_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "nacl_helper_nonsfi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "nacl_loader_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" + }, + { + "args": [ + "--ozone-platform=headless" + ], + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ozone_gl_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ozone_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ozone_x11_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sandbox_linux_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "service_manager_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "shell_dialogs_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "storage_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sync_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "traffic_annotation_auditor_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_chromeos_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_touch_selection_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "args": [ + "--disable-features=SingleProcessMash" + ], + "name": "non_single_process_mash_unit_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wayland_client_perftests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" + } + ] + }, "linux-chromium-tests-staging-builder": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 432616c..96c373e9 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -4563,6 +4563,38 @@ } ] }, + "Android FYI Release (Pixel 2)": { + "isolated_scripts": [ + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "P", + "device_type": "walleye", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + } + ] + }, "Android FYI dEQP Release (Nexus 5X)": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index e4d46d9..9ee9894 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -184,10 +184,8 @@ { "args": [ "-v", - "--browser=exact", + "--browser=android-chrome", "--upload-results", - "--browser-executable=../../out/Release/bin/monochrome_64_32_bundle", - "--device=android", "--run-ref-build", "--test-shard-map-filename=android-pixel2-perf_map.json" ],
diff --git a/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter b/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter index 7c207874..cefdd29 100644 --- a/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter +++ b/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter
@@ -13,3 +13,10 @@ -org.chromium.chrome.browser.webapps.WebApkIntegrationTest.testLaunchAndNavigateOffOrigin -org.chromium.chrome.browser.webapps.WebApkIntegrationTest.testLaunchAndNavigationInNewWindowOffandInOrigin -org.chromium.chrome.browser.webapps.WebApkIntegrationTest.testLaunchAndOpenNewWindowInOrigin + +# Miscellaneous flaky or failing tests: +# http://crbug.com/941856 +-org.chromium.chrome.browser.webapps.WebApkIntegrationTest#testActivateWebApk + +# http://crbug.com/941858 +-org.chromium.chrome.browser.payments.PaymentRequestUpdateWithTest#testUpdateWithShippingOptions
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 64f7b38..6a97f8a 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3403,6 +3403,24 @@ }, }, + 'gpu_fyi_optional_android_release_specific_telemetry_tests': { + 'webgl2_conformance_tests': { + 'telemetry_test_name': 'webgl_conformance', + 'args': [ + '--webgl-conformance-version=2.0.1', + # The current working directory when run via isolate is + # out/Debug or out/Release. Reference this file relatively to + # it. + '--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json', + ], + 'swarming': { + # These tests currently take about an hour and fifteen minutes + # to run. Split them into roughly 5-minute shards. + 'shards': 20, + }, + }, + }, + 'gpu_fyi_vulkan_gtests': { 'vulkan_content_browsertests': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index f8c703b..c3eec97 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1506,6 +1506,14 @@ 'shards': 20, }, }, + 'linux-chromeos-code-coverage': { + 'additional_compile_targets': [ + 'gn_all', + ], + 'test_suites': { + 'gtest_tests': 'linux_chromeos_gtests', + }, + }, 'linux-chromium-tests-staging-builder': { 'additional_compile_targets': [ 'all' @@ -2155,6 +2163,21 @@ 'gpu_telemetry_tests': 'gpu_common_telemetry_tests', }, }, + 'Android FYI Release (Pixel 2)': { + 'browser_config': 'android-chromium', + 'os_type': 'android', + 'skip_merge_script': True, + 'mixins': [ + 'gpu_pool', + 'pie', + 'walleye', + ], + 'test_suites': { + # We currently only want to run the WebGL 2.0 conformance tests on + # this until additional Pixel 2 capacity is added. + 'gpu_telemetry_tests': 'gpu_fyi_optional_android_release_specific_telemetry_tests', + }, + }, 'Android FYI dEQP Release (Nexus 5X)': { 'os_type': 'android', 'skip_merge_script': True,
diff --git a/testing/scripts/get_compile_targets.py b/testing/scripts/get_compile_targets.py index 16cff95..014272e 100755 --- a/testing/scripts/get_compile_targets.py +++ b/testing/scripts/get_compile_targets.py
@@ -27,7 +27,9 @@ for filename in os.listdir(common.SCRIPT_DIR): if not filename.endswith('.py'): continue - if filename in ('common.py', 'get_compile_targets.py'): + if filename in ('common.py', + 'get_compile_targets.py', + 'gpu_integration_test_adapter.py'): continue with common.temporary_file() as tempfile_path:
diff --git a/testing/scripts/gpu_integration_test_adapter.py b/testing/scripts/gpu_integration_test_adapter.py new file mode 100644 index 0000000..e62c501 --- /dev/null +++ b/testing/scripts/gpu_integration_test_adapter.py
@@ -0,0 +1,34 @@ +# Copyright 2019 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 common + +class GpuIntegrationTestAdapater(common.BaseIsolatedScriptArgsAdapter): + + def generate_test_output_args(self, output): + return ['--write-full-results-to', output] + + def generate_test_also_run_disabled_tests_args(self): + return ['--also-run-disabled-tests'] + + def generate_test_filter_args(self, test_filter_str): + filter_list = common.extract_filter_list(test_filter_str) + # isolated_script_test_filter comes in like: + # gpu_tests.webgl_conformance_integration_test.WebGLConformanceIntegrationTest.WebglExtension_WEBGL_depth_texture # pylint: disable=line-too-long + # but we need to pass it to --test-filter like this: + # WebglExtension_WEBGL_depth_texture + filter_list = [f.split('.')[-1] for f in filter_list] + # Need to convert this to a valid regex. + filter_regex = '(' + '|'.join(filter_list) + ')' + return ['--test-filter=%s' % filter_regex] + + def generate_sharding_args(self, total_shards, shard_index): + return ['--total-shards=%d' % total_shards, + '--shard-index=%d' % shard_index] + + def generate_test_launcher_retry_limit_args(self, retry_limit): + return ['--retry-limit=%d' % retry_limit] + + def generate_test_repeat_args(self, repeat_count): + return ['--repeat=%d' % repeat_count]
diff --git a/testing/scripts/run_gpu_integration_test_as_googletest.py b/testing/scripts/run_gpu_integration_test_as_googletest.py index 6a65ee4..fd48ec4 100755 --- a/testing/scripts/run_gpu_integration_test_as_googletest.py +++ b/testing/scripts/run_gpu_integration_test_as_googletest.py
@@ -28,45 +28,14 @@ """ import json -import os -import shutil import sys -import tempfile -import traceback import common +import gpu_integration_test_adapter -class GpuIntegrationTestAdapater(common.BaseIsolatedScriptArgsAdapter): - - def generate_test_output_args(self, output): - return ['--write-full-results-to', output] - - def generate_test_also_run_disabled_tests_args(self): - return ['--also-run-disabled-tests'] - - def generate_test_filter_args(self, test_filter_str): - filter_list = common.extract_filter_list(test_filter_str) - # isolated_script_test_filter comes in like: - # gpu_tests.webgl_conformance_integration_test.WebGLConformanceIntegrationTest.WebglExtension_WEBGL_depth_texture # pylint: disable=line-too-long - # but we need to pass it to --test-filter like this: - # WebglExtension_WEBGL_depth_texture - filter_list = [f.split('.')[-1] for f in filter_list] - # Need to convert this to a valid regex. - filter_regex = '(' + '|'.join(filter_list) + ')' - return ['--test-filter=%s' % filter_regex] - - def generate_sharding_args(self, total_shards, shard_index): - return ['--total-shards=%d' % total_shards, - '--shard-index=%d' % shard_index] - - def generate_test_launcher_retry_limit_args(self, retry_limit): - return ['--retry-limit=%d' % retry_limit] - - def generate_test_repeat_args(self, repeat_count): - return ['--repeat=%d' % repeat_count] def main(): - adapter = GpuIntegrationTestAdapater() + adapter = gpu_integration_test_adapter.GpuIntegrationTestAdapater() return adapter.run_test()
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 3d14e7d..8e44bec5 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -34,6 +34,10 @@ const base::Feature kFirstContentfulPaintPlusPlus{ "FirstContentfulPaintPlusPlus", base::FEATURE_DISABLED_BY_DEFAULT}; +// Perform memory purges after freezing only if all pages are frozen. +const base::Feature kFreezePurgeMemoryAllPagesFrozen{ + "FreezePurgeMemoryAllPagesFrozen", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables the experimental sweep-line algorithm for tracking "jank" from // layout objects changing their visual location between animation frames. const base::Feature kJankTrackingSweepLine{"JankTrackingSweepLine",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 7ac37872..cb90f2d 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -18,6 +18,7 @@ kEnableGpuRasterizationViewportRestriction; BLINK_COMMON_EXPORT extern const base::Feature kScriptStreaming; BLINK_COMMON_EXPORT extern const base::Feature kFirstContentfulPaintPlusPlus; +BLINK_COMMON_EXPORT extern const base::Feature kFreezePurgeMemoryAllPagesFrozen; BLINK_COMMON_EXPORT extern const base::Feature kImplicitRootScroller; BLINK_COMMON_EXPORT extern const base::Feature kJankTrackingSweepLine; BLINK_COMMON_EXPORT extern const base::Feature kBlinkGenPropertyTrees;
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index 08c2bf8..6d9f923a 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1659,16 +1659,21 @@ } if (const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) { - if ((primitive_value->IsCalculated() && - (primitive_value->IsCalculatedPercentageWithLength() || - primitive_value->IsLength() || primitive_value->IsPercentage())) || - CSSPrimitiveValue::IsRelativeUnit( - primitive_value->TypeWithCalcResolved())) { + // For simple (non-calculated) px or percentage values, we do not need to + // convert, as the value already has the proper computed form. + if (!primitive_value->IsCalculated() && + (primitive_value->IsPx() || primitive_value->IsPercentage())) { + return value; + } + + if (primitive_value->IsLength() || primitive_value->IsPercentage() || + primitive_value->IsCalculatedPercentageWithLength()) { // Instead of the actual zoom, use 1 to avoid potential rounding errors Length length = primitive_value->ConvertToLength( css_to_length_conversion_data.CopyWithAdjustedZoom(1)); return *CSSPrimitiveValue::Create(length, 1); } + // If we encounter a calculated number that was not resolved during // parsing, it means that a calc()-expression was allowed in place of // an integer. Such calc()-for-integers must be rounded at computed value
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy.cc b/third_party/blink/renderer/core/feature_policy/feature_policy.cc index 9d3cdc2..c0404af 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy.cc +++ b/third_party/blink/renderer/core/feature_policy/feature_policy.cc
@@ -37,10 +37,6 @@ return false; } - // Impossible to know without an ExecutionContext, so block. - if (!execution_context) - return true; - // Check whether this feature's origin trial is enabled, and block otherwise. DCHECK(origin_trial_enabled); return !origin_trial_enabled(execution_context);
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css index 96fd1f8..ccf544a 100644 --- a/third_party/blink/renderer/core/html/resources/html.css +++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -559,10 +559,16 @@ /* TODO(crbug.com/880258): Use different styles for `-internal-autofill-previewed` and `-internal-autofill-selected`. */ input:-internal-autofill-previewed, -input:-internal-autofill-selected, textarea:-internal-autofill-previewed, +select:-internal-autofill-previewed { + font-family: system-ui !important; + background-color: #E8F0FE !important; + background-image:none !important; + color: #000000 !important; +} + +input:-internal-autofill-selected, textarea:-internal-autofill-selected, -select:-internal-autofill-previewed, select:-internal-autofill-selected { background-color: #E8F0FE !important; background-image:none !important;
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 0dbca64..c41c4b5 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -4821,11 +4821,6 @@ # Whether to paint size or not. boolean show - command setSuspended - parameters - # Whether overlay should be suspended and not consume any resources until resumed. - boolean suspended - # Fired when the node should be inspected. This happens after call to `setInspectMode` or when # user manually inspects an element. event inspectNodeRequested
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc index fe5add9..e472b20 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -266,7 +266,6 @@ swallow_next_escape_up_(false), backend_node_id_to_inspect_(0), enabled_(&agent_state_, false), - suspended_(&agent_state_, false), show_ad_highlights_(&agent_state_, false), show_debug_borders_(&agent_state_, false), show_fps_counter_(&agent_state_, false), @@ -296,6 +295,8 @@ } void InspectorOverlayAgent::Restore() { + if (enabled_.Get()) + enable(); setShowAdHighlights(show_ad_highlights_.Get()); setShowDebugBorders(show_debug_borders_.Get()); setShowFPSCounter(show_fps_counter_.Get()); @@ -303,14 +304,12 @@ setShowScrollBottleneckRects(show_scroll_bottleneck_rects_.Get()); setShowHitTestBorders(show_hit_test_borders_.Get()); setShowViewportSizeOnResize(show_size_on_resize_.Get()); - setSuspended(suspended_.Get()); PickTheRightTool(); } void InspectorOverlayAgent::Dispose() { InspectorBaseAgent::Dispose(); disposed_ = true; - ClearInternal(); } Response InspectorOverlayAgent::enable() { @@ -335,10 +334,18 @@ setShowScrollBottleneckRects(false); setShowHitTestBorders(false); setShowViewportSizeOnResize(false); - setSuspended(false); paused_in_debugger_message_.Clear(); inspect_mode_.Set(protocol::Overlay::InspectModeEnum::None); inspect_mode_protocol_config_.Set(String()); + if (overlay_page_) { + overlay_page_->WillBeDestroyed(); + overlay_page_.Clear(); + overlay_chrome_client_.Clear(); + overlay_host_->ClearListener(); + overlay_host_.Clear(); + } + timer_.Stop(); + frame_overlay_.reset(); PickTheRightTool(); SetNeedsUnbufferedInput(false); return Response::OK(); @@ -444,14 +451,6 @@ return Response::OK(); } -Response InspectorOverlayAgent::setSuspended(bool suspended) { - if (suspended && !suspended_.Get()) - ClearInternal(); - suspended_.Set(suspended); - SetNeedsUnbufferedInput(!suspended); - return Response::OK(); -} - Response InspectorOverlayAgent::highlightRect( int x, int y, @@ -772,8 +771,6 @@ bool InspectorOverlayAgent::IsEmpty() { if (disposed_) return true; - if (suspended_.Get()) - return true; bool has_visible_elements = highlight_node_ || event_target_node_ || highlight_quad_ || (resize_timer_active_ && show_size_on_resize_.Get()); @@ -1043,23 +1040,6 @@ ScheduleUpdate(); } -void InspectorOverlayAgent::ClearInternal() { - if (overlay_page_) { - overlay_page_->WillBeDestroyed(); - overlay_page_.Clear(); - overlay_chrome_client_.Clear(); - overlay_host_->ClearListener(); - overlay_host_.Clear(); - } - resize_timer_active_ = false; - paused_in_debugger_message_.Clear(); - inspect_mode_.Set(protocol::Overlay::InspectModeEnum::None); - inspect_mode_protocol_config_.Set(String()); - timer_.Stop(); - frame_overlay_.reset(); - PickTheRightTool(); -} - void InspectorOverlayAgent::OverlayResumed() { if (v8_session_) v8_session_->resume();
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h index a918309eda..bd6c0ca9 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
@@ -121,7 +121,6 @@ protocol::Response setShowViewportSizeOnResize(bool) override; protocol::Response setPausedInDebuggerMessage( protocol::Maybe<String>) override; - protocol::Response setSuspended(bool) override; protocol::Response setInspectMode( const String& mode, protocol::Maybe<protocol::Overlay::HighlightConfig>) override; @@ -200,7 +199,6 @@ void RebuildOverlayPage(); void Invalidate(); void ScheduleUpdate(); - void ClearInternal(); protocol::Response CompositingEnabled(); @@ -244,7 +242,6 @@ bool swallow_next_escape_up_; DOMNodeId backend_node_id_to_inspect_; InspectorAgentState::Boolean enabled_; - InspectorAgentState::Boolean suspended_; InspectorAgentState::Boolean show_ad_highlights_; InspectorAgentState::Boolean show_debug_borders_; InspectorAgentState::Boolean show_fps_counter_;
diff --git a/third_party/blink/renderer/core/layout/overflow_model.h b/third_party/blink/renderer/core/layout/overflow_model.h index 467a4e4..b8ee53c 100644 --- a/third_party/blink/renderer/core/layout/overflow_model.h +++ b/third_party/blink/renderer/core/layout/overflow_model.h
@@ -159,8 +159,6 @@ // visual overflow. class BoxLayoutOverflowModel { - USING_FAST_MALLOC(BoxLayoutOverflowModel); - public: BoxLayoutOverflowModel(const LayoutRect& layout_rect) : layout_overflow_(layout_rect) {} @@ -186,8 +184,6 @@ }; class BoxVisualOverflowModel { - USING_FAST_MALLOC(BoxVisualOverflowModel); - public: BoxVisualOverflowModel(const LayoutRect& self_visual_overflow_rect) : self_visual_overflow_(self_visual_overflow_rect) {} @@ -237,6 +233,8 @@ struct BoxOverflowModel { base::Optional<BoxLayoutOverflowModel> layout_overflow; base::Optional<BoxVisualOverflowModel> visual_overflow; + + USING_FAST_MALLOC(BoxOverflowModel); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc index 126877a..d0e7234 100644 --- a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc +++ b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" @@ -143,10 +144,23 @@ KeyboardEvent* event) { DCHECK(page_->GetSettings().GetSpatialNavigationEnabled()); + // TODO(bokan): KeyboardEventManager sends non-arrow keys here. KEM should + // filter out the non-arrow keys for us. SpatialNavigationDirection direction = FocusDirectionForKey(event); if (direction == SpatialNavigationDirection::kNone) return false; + // In focusless mode, the user must explicitly move focus in and out of an + // editable so we can avoid advancing interest and we should swallow the + // event. This prevents double-handling actions for things like search box + // suggestions. + if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) { + LocalFrame* frame = + DynamicTo<LocalFrame>(page_->GetFocusController().FocusedOrMainFrame()); + if (frame->Selection().SelectionHasFocus()) + return true; + } + return Advance(direction); }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 5b4acfe..38113da 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -940,7 +940,6 @@ state.direct_compositing_reasons = full_context_.direct_compositing_reasons & CompositingReason::kDirectReasonsForEffectProperty; - CompositingReasonFinder::CompositingReasonsForAnimation(style); if (state.direct_compositing_reasons) { state.compositor_element_id = CompositorElementIdFromUniqueObjectId( object_.UniqueId(), CompositorElementIdNamespace::kPrimaryEffect);
diff --git a/third_party/blink/renderer/devtools/front_end/common/Settings.js b/third_party/blink/renderer/devtools/front_end/common/Settings.js index 9652e59..8b5aeab 100644 --- a/third_party/blink/renderer/devtools/front_end/common/Settings.js +++ b/third_party/blink/renderer/devtools/front_end/common/Settings.js
@@ -272,9 +272,10 @@ /** * @param {function(!Common.Event)} listener * @param {!Object=} thisObject + * @return {!Common.EventTarget.EventDescriptor} */ addChangeListener(listener, thisObject) { - this._eventSupport.addEventListener(this._name, listener, thisObject); + return this._eventSupport.addEventListener(this._name, listener, thisObject); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js index 144a61b..2691b18 100644 --- a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js +++ b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js
@@ -376,9 +376,7 @@ * @return {!Promise} */ async captureScreenshot() { - SDK.OverlayModel.muteHighlight(); const screenshot = await this._model.captureScreenshot(false); - SDK.OverlayModel.unmuteHighlight(); if (screenshot === null) return; @@ -411,9 +409,7 @@ * @return {!Promise} */ async captureFullSizeScreenshot() { - SDK.OverlayModel.muteHighlight(); const screenshot = await this._model.captureScreenshot(true); - SDK.OverlayModel.unmuteHighlight(); if (screenshot === null) return; return this._saveScreenshotBase64(screenshot); @@ -424,9 +420,7 @@ * @return {!Promise} */ async captureAreaScreenshot(clip) { - SDK.OverlayModel.muteHighlight(); const screenshot = await this._model.captureScreenshot(false, clip); - SDK.OverlayModel.unmuteHighlight(); if (screenshot === null) return; return this._saveScreenshotBase64(screenshot);
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js b/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js index 7833a9d..e4932a9 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js
@@ -15,8 +15,6 @@ target.registerOverlayDispatcher(this); this._overlayAgent = target.overlayAgent(); - this._overlayAgent.enable(); - this._overlayAgent.setShowViewportSizeOnResize(true); this._debuggerModel = target.model(SDK.DebuggerModel); if (this._debuggerModel) { @@ -36,43 +34,18 @@ this._highlighter = this._defaultHighlighter; this._showPaintRectsSetting = Common.moduleSetting('showPaintRects'); - this._showPaintRectsSetting.addChangeListener( - () => this._overlayAgent.setShowPaintRects(this._showPaintRectsSetting.get())); - if (this._showPaintRectsSetting.get()) - this._overlayAgent.setShowPaintRects(true); - this._showAdHighlightsSetting = Common.moduleSetting('showAdHighlights'); - this._showAdHighlightsSetting.addChangeListener( - () => this._overlayAgent.setShowAdHighlights(this._showAdHighlightsSetting.get())); - if (this._showAdHighlightsSetting.get()) - this._overlayAgent.setShowAdHighlights(true); - this._showDebugBordersSetting = Common.moduleSetting('showDebugBorders'); - this._showDebugBordersSetting.addChangeListener( - () => this._overlayAgent.setShowDebugBorders(this._showDebugBordersSetting.get())); - if (this._showDebugBordersSetting.get()) - this._overlayAgent.setShowDebugBorders(true); - this._showFPSCounterSetting = Common.moduleSetting('showFPSCounter'); - this._showFPSCounterSetting.addChangeListener( - () => this._overlayAgent.setShowFPSCounter(this._showFPSCounterSetting.get())); - if (this._showFPSCounterSetting.get()) - this._overlayAgent.setShowFPSCounter(true); - this._showScrollBottleneckRectsSetting = Common.moduleSetting('showScrollBottleneckRects'); - this._showScrollBottleneckRectsSetting.addChangeListener( - () => this._overlayAgent.setShowScrollBottleneckRects(this._showScrollBottleneckRectsSetting.get())); - if (this._showScrollBottleneckRectsSetting.get()) - this._overlayAgent.setShowScrollBottleneckRects(true); - this._showHitTestBordersSetting = Common.moduleSetting('showHitTestBorders'); - this._showHitTestBordersSetting.addChangeListener( - () => this._overlayAgent.setShowHitTestBorders(this._showHitTestBordersSetting.get())); - if (this._showHitTestBordersSetting.get()) - this._overlayAgent.setShowHitTestBorders(true); - if (target.suspended()) - this._overlayAgent.setSuspended(true); + this._registeredListeners = []; + this._showViewportSizeOnResize = true; + if (!target.suspended()) { + this._overlayAgent.enable(); + this._wireAgentToSettings(); + } } /** @@ -89,17 +62,48 @@ overlayModel._delayedHideHighlight(0); } - static muteHighlight() { - SDK.OverlayModel.hideDOMNodeHighlight(); - SDK.OverlayModel._highlightDisabled = true; - for (const overlayModel of SDK.targetManager.models(SDK.OverlayModel)) - overlayModel._updatePausedInDebuggerMessage(); + static async muteHighlight() { + return Promise.all(SDK.targetManager.models(SDK.OverlayModel).map(model => model.suspendModel())); } - static unmuteHighlight() { - SDK.OverlayModel._highlightDisabled = false; - for (const overlayModel of SDK.targetManager.models(SDK.OverlayModel)) - overlayModel._updatePausedInDebuggerMessage(); + static async unmuteHighlight() { + return Promise.all(SDK.targetManager.models(SDK.OverlayModel).map(model => model.resumeModel())); + } + + /** + * @return {!Promise} + */ + _wireAgentToSettings() { + this._registeredListeners = [ + this._showPaintRectsSetting.addChangeListener( + () => this._overlayAgent.setShowPaintRects(this._showPaintRectsSetting.get())), + this._showAdHighlightsSetting.addChangeListener( + () => this._overlayAgent.setShowAdHighlights(this._showAdHighlightsSetting.get())), + this._showDebugBordersSetting.addChangeListener( + () => this._overlayAgent.setShowDebugBorders(this._showDebugBordersSetting.get())), + this._showFPSCounterSetting.addChangeListener( + () => this._overlayAgent.setShowFPSCounter(this._showFPSCounterSetting.get())), + this._showScrollBottleneckRectsSetting.addChangeListener( + () => this._overlayAgent.setShowScrollBottleneckRects(this._showScrollBottleneckRectsSetting.get())), + this._showHitTestBordersSetting.addChangeListener( + () => this._overlayAgent.setShowHitTestBorders(this._showHitTestBordersSetting.get())) + ]; + + if (this._showPaintRectsSetting.get()) + this._overlayAgent.setShowPaintRects(true); + if (this._showAdHighlightsSetting.get()) + this._overlayAgent.setShowAdHighlights(true); + if (this._showDebugBordersSetting.get()) + this._overlayAgent.setShowDebugBorders(true); + if (this._showFPSCounterSetting.get()) + this._overlayAgent.setShowFPSCounter(true); + if (this._showScrollBottleneckRectsSetting.get()) + this._overlayAgent.setShowScrollBottleneckRects(true); + if (this._showHitTestBordersSetting.get()) + this._overlayAgent.setShowHitTestBorders(true); + if (this._debuggerModel.isPaused()) + this._updatePausedInDebuggerMessage(); + return this._overlayAgent.setShowViewportSizeOnResize(this._showViewportSizeOnResize); } /** @@ -107,7 +111,8 @@ * @return {!Promise} */ suspendModel() { - return this._overlayAgent.setSuspended(true); + Common.EventTarget.removeEventListeners(this._registeredListeners); + return this._overlayAgent.disable(); } /** @@ -115,19 +120,30 @@ * @return {!Promise} */ resumeModel() { - return this._overlayAgent.setSuspended(false); + this._overlayAgent.enable(); + return this._wireAgentToSettings(); } + /** + * @param {boolean} show + */ setShowViewportSizeOnResize(show) { + this._showViewportSizeOnResize = show; + if (this.target().suspended()) + return; this._overlayAgent.setShowViewportSizeOnResize(show); } + /** + * @return {!Promise} + */ _updatePausedInDebuggerMessage() { - const message = this._debuggerModel.isPaused() && !Common.moduleSetting('disablePausedStateOverlay').get() && - !SDK.OverlayModel._highlightDisabled ? + if (this.target().suspended()) + return Promise.resolve(); + const message = this._debuggerModel.isPaused() && !Common.moduleSetting('disablePausedStateOverlay').get() ? Common.UIString('Paused in debugger') : undefined; - this._overlayAgent.setPausedInDebuggerMessage(message); + return this._overlayAgent.setPausedInDebuggerMessage(message); } /** @@ -161,8 +177,6 @@ * @param {boolean=} showInfo */ highlightInOverlay(data, mode, showInfo) { - if (SDK.OverlayModel._highlightDisabled) - return; if (this._hideHighlightTimeout) { clearTimeout(this._hideHighlightTimeout); this._hideHighlightTimeout = null; @@ -193,8 +207,6 @@ * @param {!Protocol.Page.FrameId} frameId */ highlightFrame(frameId) { - if (SDK.OverlayModel._highlightDisabled) - return; if (this._hideHighlightTimeout) { clearTimeout(this._hideHighlightTimeout); this._hideHighlightTimeout = null;
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js b/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js index ddb7f44..4a213ed 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
@@ -46,8 +46,11 @@ * @param {!Protocol.Page.Viewport=} clip * @return {!Promise<?string>} */ - captureScreenshot(format, quality, clip) { - return this._agent.captureScreenshot(format, quality, clip, true); + async captureScreenshot(format, quality, clip) { + await SDK.OverlayModel.muteHighlight(); + const result = await this._agent.captureScreenshot(format, quality, clip, true); + await SDK.OverlayModel.unmuteHighlight(); + return result; } /**
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc index 1ea1d66..b99b656f 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -29,8 +29,6 @@ #include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h" #include "third_party/blink/renderer/platform/wtf/functional.h" -// And now, a brief note about clipboard permissions. -// // There are 2 clipboard permissions defined in the spec: // * clipboard-read // * clipboard-write @@ -68,6 +66,7 @@ ClipboardPromise::~ClipboardPromise() = default; +// static ScriptPromise ClipboardPromise::CreateForRead(ScriptState* script_state) { ClipboardPromise* clipboard_promise = MakeGarbageCollected<ClipboardPromise>(script_state); @@ -77,6 +76,7 @@ return clipboard_promise->script_promise_resolver_->Promise(); } +// static ScriptPromise ClipboardPromise::CreateForReadText(ScriptState* script_state) { ClipboardPromise* clipboard_promise = MakeGarbageCollected<ClipboardPromise>(script_state); @@ -86,6 +86,7 @@ return clipboard_promise->script_promise_resolver_->Promise(); } +// static ScriptPromise ClipboardPromise::CreateForWrite(ScriptState* script_state, HeapVector<Member<Blob>> data) { ClipboardPromise* clipboard_promise = @@ -99,6 +100,7 @@ return clipboard_promise->script_promise_resolver_->Promise(); } +// static ScriptPromise ClipboardPromise::CreateForWriteText(ScriptState* script_state, const String& data) { ClipboardPromise* clipboard_promise = @@ -120,7 +122,8 @@ scoped_refptr<base::SingleThreadTaskRunner> ClipboardPromise::GetTaskRunner() { DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker); - // TODO(garykac): Replace MiscPlatformAPI with TaskType specific to clipboard. + // TODO(https://crbug.com/941835): Replace MiscPlatformAPI with TaskType + // specific to clipboard. return GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); } @@ -196,7 +199,6 @@ WrapPersistent(this))); } -// TODO(garykac): This currently only handles images and plain text. void ClipboardPromise::HandleReadWithPermission(PermissionStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker); if (status != PermissionStatus::GRANTED) { @@ -246,7 +248,6 @@ } void ClipboardPromise::HandleWrite(HeapVector<Member<Blob>>* data) { - // TODO(huangdarwin): This currently only handles plain text and images. DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker); CHECK(data); blob_sequence_data_ = std::move(*data);
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h index 857cf17..89e0c084 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -90,8 +90,6 @@ bool IsValidClipboardType(const String&); - // Because v8 is thread-hostile, ensures that all interactions with - // ScriptState and ScriptPromiseResolver occur on the main thread. Member<ScriptState> script_state_; Member<ScriptPromiseResolver> script_promise_resolver_; @@ -106,8 +104,11 @@ // Index of clipboard representation currently being processed. wtf_size_t clipboard_representation_index_; + // Only used for reading Blobs via the ClipboardFileReader. scoped_refptr<base::SingleThreadTaskRunner> file_reading_task_runner_; + // Because v8 is thread-hostile, ensures that all interactions with + // ScriptState and ScriptPromiseResolver occur on the main thread. SEQUENCE_CHECKER(async_clipboard_sequence_checker); DISALLOW_COPY_AND_ASSIGN(ClipboardPromise);
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 7f8e8d2..cdd15a6 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -429,9 +429,9 @@ "webgl/webgl_uniform_location.idl", "webgl/webgl_vertex_array_object.idl", "webgl/webgl_vertex_array_object_oes.idl", - "webgpu/webgpu.idl", - "webgpu/webgpu_adapter.idl", - "webgpu/webgpu_device.idl", + "webgpu/gpu.idl", + "webgpu/gpu_adapter.idl", + "webgpu/gpu_device.idl", "webmidi/midi_access.idl", "webmidi/midi_connection_event.idl", "webmidi/midi_input.idl", @@ -734,7 +734,7 @@ "webaudio/wave_shaper_options.idl", "webgl/webgl_context_attributes.idl", "webgl/webgl_context_event_init.idl", - "webgpu/webgpu_adapter_descriptor.idl", + "webgpu/gpu_adapter_descriptor.idl", "webmidi/midi_connection_event_init.idl", "webmidi/midi_message_event_init.idl", "webmidi/midi_options.idl", @@ -851,7 +851,7 @@ "webdatabase/window_web_database.idl", "webgl/webgl2_rendering_context_base.idl", "webgl/webgl_rendering_context_base.idl", - "webgpu/window_webgpu.idl", + "webgpu/navigator_gpu.idl", "webmidi/navigator_web_midi.idl", "webshare/navigator_share.idl", "webusb/navigator_usb.idl",
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc index 6ab33f2..39177bd 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -110,11 +110,8 @@ DEFINE_STATIC_LOCAL(SparseHistogram, max_channel_count_histogram, ("WebAudio.AudioContext.MaxChannelsAvailable")); - DEFINE_STATIC_LOCAL(SparseHistogram, sample_rate_histogram, - ("WebAudio.AudioContext.HardwareSampleRate")); max_channel_count_histogram.Sample( audio_context->destination()->maxChannelCount()); - sample_rate_histogram.Sample(audio_context->sampleRate()); probe::DidCreateAudioContext(&document);
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn index 0182dfa..3b810a96 100644 --- a/third_party/blink/renderer/modules/webgpu/BUILD.gn +++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -6,14 +6,14 @@ blink_modules_sources("webgpu") { sources = [ - "webgpu.cc", - "webgpu.h", - "webgpu_adapter.cc", - "webgpu_adapter.h", - "webgpu_device.cc", - "webgpu_device.h", - "window_webgpu.cc", - "window_webgpu.h", + "gpu.cc", + "gpu.h", + "gpu_adapter.cc", + "gpu_adapter.h", + "gpu_device.cc", + "gpu_device.h", + "navigator_gpu.cc", + "navigator_gpu.h", ] deps = [ "//third_party/dawn/src/dawn:dawn_headers",
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc new file mode 100644 index 0000000..f6b9f9b --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -0,0 +1,63 @@ +// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/gpu.h" + +#include <utility> + +#include "gpu/command_buffer/client/webgpu_interface.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_adapter_descriptor.h" + +namespace blink { + +// static +GPU* GPU::Create(ExecutionContext& execution_context) { + const auto& url = execution_context.Url(); + Platform::GraphicsInfo info; + + std::unique_ptr<WebGraphicsContext3DProvider> context_provider = + Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url, &info); + + // TODO(kainino): we will need a better way of accessing the GPU interface + // from multiple threads than BindToCurrentThread et al. + if (context_provider && context_provider->BindToCurrentThread()) { + info.error_message = + String("bindToCurrentThread failed: " + String(info.error_message)); + } + + if (!context_provider) { + // TODO(kainino): send the error message somewhere + // (see ExtractWebGLContextCreationError). + return nullptr; + } + + return MakeGarbageCollected<GPU>(execution_context, + std::move(context_provider)); +} + +GPU::GPU(ExecutionContext& execution_context, + std::unique_ptr<WebGraphicsContext3DProvider> context_provider) + : ContextLifecycleObserver(&execution_context), + context_provider_(std::move(context_provider)) {} + +GPU::~GPU() = default; + +void GPU::Trace(blink::Visitor* visitor) { + ScriptWrappable::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); +} + +void GPU::ContextDestroyed(ExecutionContext* execution_context) { + context_provider_.reset(); +} + +GPUAdapter* GPU::getAdapter(const GPUAdapterDescriptor* descriptor) { + return GPUAdapter::Create(descriptor->powerPreference()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.h b/third_party/blink/renderer/modules/webgpu/gpu.h new file mode 100644 index 0000000..1e74187 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu.h
@@ -0,0 +1,46 @@ +// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_H_ + +#include <memory> + +#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" +#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" + +namespace blink { + +class GPUAdapter; +class GPUAdapterDescriptor; + +class GPU final : public ScriptWrappable, public ContextLifecycleObserver { + DEFINE_WRAPPERTYPEINFO(); + USING_GARBAGE_COLLECTED_MIXIN(GPU); + + public: + static GPU* Create(ExecutionContext& execution_context); + explicit GPU(ExecutionContext& execution_context, + std::unique_ptr<WebGraphicsContext3DProvider> context_provider); + ~GPU() override; + + // ScriptWrappable overrides + void Trace(blink::Visitor* visitor) override; + + // ContextLifecycleObserver overrides + void ContextDestroyed(ExecutionContext* execution_context) override; + + GPUAdapter* getAdapter(const GPUAdapterDescriptor*); + + private: + std::unique_ptr<WebGraphicsContext3DProvider> context_provider_; + + DISALLOW_COPY_AND_ASSIGN(GPU); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.idl b/third_party/blink/renderer/modules/webgpu/gpu.idl new file mode 100644 index 0000000..55d4bbe3 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu.idl
@@ -0,0 +1,11 @@ +// Copyright 2018 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. + +// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl + +[ + RuntimeEnabled=WebGPU +] interface GPU { + GPUAdapter getAdapter(GPUAdapterDescriptor descriptor); +};
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc new file mode 100644 index 0000000..c96a2cc2 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -0,0 +1,26 @@ +// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/gpu_adapter.h" + +#include "third_party/blink/renderer/modules/webgpu/gpu_device.h" + +namespace blink { + +// static +GPUAdapter* GPUAdapter::Create(const String& name) { + return MakeGarbageCollected<GPUAdapter>(name); +} + +const String& GPUAdapter::name() const { + return name_; +} + +GPUDevice* GPUAdapter::createDevice() { + return GPUDevice::Create(this); +} + +GPUAdapter::GPUAdapter(const String& name) : name_(name) {} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h new file mode 100644 index 0000000..a993c32 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -0,0 +1,36 @@ +// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_ADAPTER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_ADAPTER_H_ + +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +class GPUDevice; + +class GPUAdapter final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static GPUAdapter* Create(const String& name); + + GPUAdapter(const String& name); + + const String& name() const; + + GPUDevice* createDevice(); + + private: + String name_; + + DISALLOW_COPY_AND_ASSIGN(GPUAdapter); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_ADAPTER_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl similarity index 65% rename from third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl rename to third_party/blink/renderer/modules/webgpu/gpu_adapter.idl index 08a9d3ff..01ef4985 100644 --- a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl + [ RuntimeEnabled=WebGPU -] interface WebGPUAdapter { +] interface GPUAdapter { readonly attribute DOMString name; - [CallWith=ExecutionContext] WebGPUDevice createDevice(); + GPUDevice createDevice(); };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter_descriptor.idl new file mode 100644 index 0000000..f2a90b4 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter_descriptor.idl
@@ -0,0 +1,15 @@ +// Copyright 2018 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. + +// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl + +enum GPUPowerPreference { + "default", + "low-power", + "high-performance", +}; + +dictionary GPUAdapterDescriptor { + GPUPowerPreference powerPreference = "default"; +};
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc new file mode 100644 index 0000000..dcacac5 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -0,0 +1,28 @@ +// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/gpu_device.h" + +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h" + +namespace blink { + +// static +GPUDevice* GPUDevice::Create(GPUAdapter* adapter) { + return MakeGarbageCollected<GPUDevice>(adapter); +} + +GPUAdapter* GPUDevice::adapter() const { + return adapter_; +} + +void GPUDevice::Trace(blink::Visitor* visitor) { + visitor->Trace(adapter_); + ScriptWrappable::Trace(visitor); +} + +GPUDevice::GPUDevice(GPUAdapter* adapter) : adapter_(adapter) {} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.h b/third_party/blink/renderer/modules/webgpu/gpu_device.h new file mode 100644 index 0000000..232cbc0 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -0,0 +1,34 @@ +// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_ + +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" + +namespace blink { + +class GPUAdapter; + +class GPUDevice final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static GPUDevice* Create(GPUAdapter*); + + GPUDevice(GPUAdapter*); + + GPUAdapter* adapter() const; + + void Trace(blink::Visitor*) override; + + private: + Member<GPUAdapter> adapter_; + + DISALLOW_COPY_AND_ASSIGN(GPUDevice); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/third_party/blink/renderer/modules/webgpu/gpu_device.idl new file mode 100644 index 0000000..3a1dc5d --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -0,0 +1,11 @@ +// Copyright 2018 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. + +// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl + +[ + RuntimeEnabled=WebGPU +] interface GPUDevice { + readonly attribute GPUAdapter adapter; +};
diff --git a/third_party/blink/renderer/modules/webgpu/navigator_gpu.cc b/third_party/blink/renderer/modules/webgpu/navigator_gpu.cc new file mode 100644 index 0000000..1a08230 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/navigator_gpu.cc
@@ -0,0 +1,49 @@ +// Copyright 2019 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 "third_party/blink/renderer/modules/webgpu/navigator_gpu.h" + +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/navigator.h" +#include "third_party/blink/renderer/modules/webgpu/gpu.h" + +namespace blink { + +NavigatorGPU& NavigatorGPU::From(Navigator& navigator) { + NavigatorGPU* supplement = + Supplement<Navigator>::From<NavigatorGPU>(navigator); + if (!supplement) { + supplement = MakeGarbageCollected<NavigatorGPU>(navigator); + ProvideTo(navigator, supplement); + } + return *supplement; +} + +// static +GPU* NavigatorGPU::gpu(ScriptState* script_state, Navigator& navigator) { + return NavigatorGPU::From(navigator).gpu(script_state); +} + +GPU* NavigatorGPU::gpu(ScriptState* script_state) { + if (!gpu_) { + ExecutionContext* context = ExecutionContext::From(script_state); + DCHECK(context); + + gpu_ = GPU::Create(*context); + } + return gpu_; +} + +void NavigatorGPU::Trace(blink::Visitor* visitor) { + visitor->Trace(gpu_); + Supplement<Navigator>::Trace(visitor); +} + +NavigatorGPU::NavigatorGPU(Navigator& navigator) + : Supplement<Navigator>(navigator) {} + +const char NavigatorGPU::kSupplementName[] = "NavigatorGPU"; + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/navigator_gpu.h b/third_party/blink/renderer/modules/webgpu/navigator_gpu.h new file mode 100644 index 0000000..79312b2 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/navigator_gpu.h
@@ -0,0 +1,43 @@ +// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_NAVIGATOR_GPU_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_NAVIGATOR_GPU_H_ + +#include "third_party/blink/renderer/core/frame/navigator.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/supplementable.h" + +namespace blink { + +class Navigator; +class GPU; + +class NavigatorGPU final : public GarbageCollected<NavigatorGPU>, + public Supplement<Navigator> { + USING_GARBAGE_COLLECTED_MIXIN(NavigatorGPU); + + public: + static const char kSupplementName[]; + + // Gets, or creates, NavigatorGPU supplement on Navigator. + // See platform/Supplementable.h + static NavigatorGPU& From(Navigator&); + + static GPU* gpu(ScriptState* script_state, Navigator&); + GPU* gpu(ScriptState* script_state); + + explicit NavigatorGPU(Navigator&); + + void Trace(blink::Visitor*) override; + + private: + Member<GPU> gpu_; + + DISALLOW_COPY_AND_ASSIGN(NavigatorGPU); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_NAVIGATOR_GPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl b/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl new file mode 100644 index 0000000..5d5fa8b --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl
@@ -0,0 +1,12 @@ +// Copyright 2019 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. + +// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl + +[ + Exposed=Window, + ImplementedAs=NavigatorGPU +] partial interface Navigator { + [SameObject, RuntimeEnabled=WebGPU, CallWith=ScriptState] readonly attribute GPU gpu; +};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.cc b/third_party/blink/renderer/modules/webgpu/webgpu.cc deleted file mode 100644 index 05edb42..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/webgpu.h" - -#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h" -#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.h" - -namespace blink { - -// static -WebGPU* WebGPU::Create() { - return MakeGarbageCollected<WebGPU>(); -} - -WebGPUAdapter* WebGPU::getAdapter(const WebGPUAdapterDescriptor* descriptor) { - return WebGPUAdapter::Create(descriptor->powerPreference()); -} - -WebGPU::WebGPU() {} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.h b/third_party/blink/renderer/modules/webgpu/webgpu.h deleted file mode 100644 index 84a2fc5..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_ - -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" - -namespace blink { - -class WebGPUAdapter; -class WebGPUAdapterDescriptor; - -class WebGPU final : public ScriptWrappable { - DISALLOW_COPY_AND_ASSIGN(WebGPU); - DEFINE_WRAPPERTYPEINFO(); - - public: - static WebGPU* Create(); - - WebGPU(); - - WebGPUAdapter* getAdapter(const WebGPUAdapterDescriptor*); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.idl b/third_party/blink/renderer/modules/webgpu/webgpu.idl deleted file mode 100644 index 8877baff..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu.idl +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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. - -[ - RuntimeEnabled=WebGPU -] interface WebGPU { - WebGPUAdapter getAdapter(WebGPUAdapterDescriptor descriptor); -};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc deleted file mode 100644 index b547074..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h" - -#include "third_party/blink/renderer/modules/webgpu/webgpu_device.h" - -namespace blink { - -// static -WebGPUAdapter* WebGPUAdapter::Create(const String& name) { - return MakeGarbageCollected<WebGPUAdapter>(name); -} - -const String& WebGPUAdapter::name() const { - return name_; -} - -WebGPUDevice* WebGPUAdapter::createDevice(ExecutionContext* execution_context) { - return WebGPUDevice::Create(execution_context, this); -} - -WebGPUAdapter::WebGPUAdapter(const String& name) : name_(name) {} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h deleted file mode 100644 index 07af4bd..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_ - -#include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -class WebGPUDevice; - -class WebGPUAdapter final : public ScriptWrappable { - DISALLOW_COPY_AND_ASSIGN(WebGPUAdapter); - DEFINE_WRAPPERTYPEINFO(); - - public: - static WebGPUAdapter* Create(const String& name); - - WebGPUAdapter(const String& name); - - const String& name() const; - - WebGPUDevice* createDevice(ExecutionContext*); - - private: - String name_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl b/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl deleted file mode 100644 index 4c9a6ca..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 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. - -enum WebGPUPowerPreference { - "default", - "low-power", - "high-performance", -}; - -dictionary WebGPUAdapterDescriptor { - WebGPUPowerPreference powerPreference = "default"; -};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.cc b/third_party/blink/renderer/modules/webgpu/webgpu_device.cc deleted file mode 100644 index 111a129..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_device.cc +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/webgpu_device.h" - -#include "gpu/command_buffer/client/webgpu_interface.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h" - -namespace blink { - -// static -WebGPUDevice* WebGPUDevice::Create(ExecutionContext* execution_context, - WebGPUAdapter* adapter) { - DCHECK(IsMainThread()); - - const auto& url = execution_context->Url(); - Platform::GraphicsInfo info; - - std::unique_ptr<WebGraphicsContext3DProvider> context_provider = - Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url, &info); - - // TODO(kainino): we will need a better way of accessing the WebGPU interface - // from multiple threads than BindToCurrentThread et al. - if (context_provider && context_provider->BindToCurrentThread()) { - info.error_message = - String("bindToCurrentThread failed: " + String(info.error_message)); - } - - if (!context_provider) { - // TODO(kainino): send the error message somewhere - // (see ExtractWebGLContextCreationError). - return nullptr; - } - - return MakeGarbageCollected<WebGPUDevice>(adapter, - std::move(context_provider)); -} - -WebGPUAdapter* WebGPUDevice::adapter() const { - return adapter_; -} - -void WebGPUDevice::Trace(blink::Visitor* visitor) { - visitor->Trace(adapter_); - ScriptWrappable::Trace(visitor); -} - -WebGPUDevice::WebGPUDevice( - WebGPUAdapter* adapter, - std::unique_ptr<WebGraphicsContext3DProvider> context_provider) - : adapter_(adapter), context_provider_(std::move(context_provider)) {} - -gpu::webgpu::WebGPUInterface* WebGPUDevice::Interface() const { - DCHECK(context_provider_); - return context_provider_->WebGPUInterface(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.h b/third_party/blink/renderer/modules/webgpu/webgpu_device.h deleted file mode 100644 index 2d86aef..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_device.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_ - -#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" -#include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" - -namespace blink { - -class WebGPUAdapter; - -class WebGPUDevice final : public ScriptWrappable { - DISALLOW_COPY_AND_ASSIGN(WebGPUDevice); - DEFINE_WRAPPERTYPEINFO(); - - public: - static WebGPUDevice* Create(ExecutionContext*, WebGPUAdapter*); - - WebGPUDevice(WebGPUAdapter*, std::unique_ptr<WebGraphicsContext3DProvider>); - - WebGPUAdapter* adapter() const; - - void Trace(blink::Visitor*) override; - - private: - gpu::webgpu::WebGPUInterface* Interface() const; - - Member<WebGPUAdapter> adapter_; - std::unique_ptr<WebGraphicsContext3DProvider> context_provider_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.idl b/third_party/blink/renderer/modules/webgpu/webgpu_device.idl deleted file mode 100644 index 47f1b690..0000000 --- a/third_party/blink/renderer/modules/webgpu/webgpu_device.idl +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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. - -[ - RuntimeEnabled=WebGPU -] interface WebGPUDevice { - readonly attribute WebGPUAdapter adapter; -};
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.cc b/third_party/blink/renderer/modules/webgpu/window_webgpu.cc deleted file mode 100644 index b392dd09..0000000 --- a/third_party/blink/renderer/modules/webgpu/window_webgpu.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 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 "third_party/blink/renderer/modules/webgpu/window_webgpu.h" - -#include "third_party/blink/renderer/core/frame/local_dom_window.h" -#include "third_party/blink/renderer/modules/webgpu/webgpu.h" - -namespace blink { - -const char WindowWebGPU::kSupplementName[] = "WindowWebGPU"; - -// static -WindowWebGPU& WindowWebGPU::From(LocalDOMWindow& window) { - WindowWebGPU* supplement = - Supplement<LocalDOMWindow>::From<WindowWebGPU>(window); - if (!supplement) { - supplement = MakeGarbageCollected<WindowWebGPU>(window); - ProvideTo(window, supplement); - } - return *supplement; -} - -// static -WebGPU* WindowWebGPU::webgpu(LocalDOMWindow& window) { - return WindowWebGPU::From(window).webgpu(); -} - -WebGPU* WindowWebGPU::webgpu() const { - if (!webgpu_) { - webgpu_ = WebGPU::Create(); - } - return webgpu_.Get(); -} - -void WindowWebGPU::Trace(blink::Visitor* visitor) { - visitor->Trace(webgpu_); - Supplement<LocalDOMWindow>::Trace(visitor); -} - -WindowWebGPU::WindowWebGPU(LocalDOMWindow& window) - : Supplement<LocalDOMWindow>(window) {} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.h b/third_party/blink/renderer/modules/webgpu/window_webgpu.h deleted file mode 100644 index 6ca56063..0000000 --- a/third_party/blink/renderer/modules/webgpu/window_webgpu.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_ - -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/supplementable.h" - -namespace blink { - -class WebGPU; -class LocalDOMWindow; - -class WindowWebGPU final : public GarbageCollected<WindowWebGPU>, - public Supplement<LocalDOMWindow> { - USING_GARBAGE_COLLECTED_MIXIN(WindowWebGPU); - - public: - static const char kSupplementName[]; - - static WindowWebGPU& From(LocalDOMWindow&); - static WebGPU* webgpu(LocalDOMWindow&); - WebGPU* webgpu() const; - - explicit WindowWebGPU(LocalDOMWindow&); - - void Trace(blink::Visitor*) override; - - private: - mutable Member<WebGPU> webgpu_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.idl b/third_party/blink/renderer/modules/webgpu/window_webgpu.idl deleted file mode 100644 index 344cd7d..0000000 --- a/third_party/blink/renderer/modules/webgpu/window_webgpu.idl +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2018 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. - -[ - RuntimeEnabled=WebGPU, - ImplementedAs=WindowWebGPU -] partial interface Window { - [Replaceable, SameObject] readonly attribute WebGPU webgpu; -};
diff --git a/third_party/blink/renderer/platform/audio/audio_destination.cc b/third_party/blink/renderer/platform/audio/audio_destination.cc index 895bc61..30e258b 100644 --- a/third_party/blink/renderer/platform/audio/audio_destination.cc +++ b/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -100,10 +100,13 @@ NOTREACHED(); } + double scale_factor = 1; + if (context_sample_rate.has_value() && context_sample_rate.value() != web_audio_device_->SampleRate()) { - double scale_factor = + scale_factor = context_sample_rate.value() / web_audio_device_->SampleRate(); + resampler_.reset(new MediaMultiChannelResampler( MaxChannelCount(), scale_factor, audio_utilities::kRenderQuantumFrames, ConvertToBaseCallback( @@ -119,6 +122,31 @@ } else { context_sample_rate_ = web_audio_device_->SampleRate(); } + + DEFINE_STATIC_LOCAL(SparseHistogram, sample_rate_histogram, + ("WebAudio.AudioContext.HardwareSampleRate")); + + sample_rate_histogram.Sample(web_audio_device_->SampleRate()); + + // The actual supplied |sampleRate| is probably a small set including 44100, + // 48000, 22050, and 2400 Hz. Other valid values range from 3000 to 384000 + // Hz, but are not expected to be used much. + DEFINE_STATIC_LOCAL(SparseHistogram, selected_sample_rate_histogram, + ("WebAudio.AudioContextOptions.sampleRate")); + + // From the expected values above and the common HW sample rates, we expect + // the most common ratios to be the set 0.5, 44100/48000, and 48000/44100. + // Other values are possible but seem unlikely. + DEFINE_STATIC_LOCAL(SparseHistogram, sample_rate_ratio_histogram, + ("WebAudio.AudioContextOptions.sampleRateRatio")); + + // Record the selected sample rate and ratio if the sampleRate was given. The + // ratio is recorded as a percentage, rounded to the nearest percent. + if (context_sample_rate.has_value()) { + selected_sample_rate_histogram.Sample(context_sample_rate.value()); + sample_rate_ratio_histogram.Sample( + static_cast<int32_t>(100 * scale_factor + 0.5)); + } } AudioDestination::~AudioDestination() {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc index 8e6a111d..128481c 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.cc
@@ -10,21 +10,6 @@ namespace blink { template <typename TextContainerType> -ShapeResultSpacing<TextContainerType>::ShapeResultSpacing( - const TextContainerType& text) - : text_(text), - letter_spacing_(0), - word_spacing_(0), - expansion_(0), - expansion_per_opportunity_(0), - expansion_opportunity_count_(0), - text_justify_(TextJustify::kAuto), - has_spacing_(false), - normalize_space_(false), - allow_tabs_(false), - is_after_expansion_(false) {} - -template <typename TextContainerType> bool ShapeResultSpacing<TextContainerType>::SetSpacing( const FontDescription& font_description) { if (!font_description.LetterSpacing() && !font_description.WordSpacing()) {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h index 391de422..42a3061 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h
@@ -20,7 +20,18 @@ STACK_ALLOCATED(); public: - explicit ShapeResultSpacing(const TextContainerType&); + explicit ShapeResultSpacing(const TextContainerType& text) + : text_(text), + letter_spacing_(0), + word_spacing_(0), + expansion_(0), + expansion_per_opportunity_(0), + expansion_opportunity_count_(0), + text_justify_(TextJustify::kAuto), + has_spacing_(false), + normalize_space_(false), + allow_tabs_(false), + is_after_expansion_(false) {} const TextContainerType& Text() const { return text_; } float LetterSpacing() const { return letter_spacing_; }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index f1fa25d..46c3a38a 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -2269,7 +2269,7 @@ void MainThreadSchedulerImpl::AddPageScheduler( PageSchedulerImpl* page_scheduler) { main_thread_only().page_schedulers.insert(page_scheduler); - memory_purge_manager_.OnPageCreated(page_scheduler->IsFrozen()); + memory_purge_manager_.OnPageCreated(page_scheduler->GetPageLifecycleState()); } void MainThreadSchedulerImpl::RemovePageScheduler( @@ -2277,15 +2277,16 @@ DCHECK(main_thread_only().page_schedulers.find(page_scheduler) != main_thread_only().page_schedulers.end()); main_thread_only().page_schedulers.erase(page_scheduler); - memory_purge_manager_.OnPageDestroyed(page_scheduler->IsFrozen()); + memory_purge_manager_.OnPageDestroyed( + page_scheduler->GetPageLifecycleState()); } void MainThreadSchedulerImpl::OnPageFrozen() { memory_purge_manager_.OnPageFrozen(); } -void MainThreadSchedulerImpl::OnPageUnfrozen() { - memory_purge_manager_.OnPageUnfrozen(); +void MainThreadSchedulerImpl::OnPageResumed() { + memory_purge_manager_.OnPageResumed(); } void MainThreadSchedulerImpl::BroadcastIntervention(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index 5fe86ec..d277cd1 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -306,9 +306,9 @@ void AddPageScheduler(PageSchedulerImpl*); void RemovePageScheduler(PageSchedulerImpl*); - // Called by an associated PageScheduler when frozen or unfrozen. + // Called by an associated PageScheduler when frozen or resumed. void OnPageFrozen(); - void OnPageUnfrozen(); + void OnPageResumed(); void AddTaskTimeObserver(base::sequence_manager::TaskTimeObserver*); void RemoveTaskTimeObserver(base::sequence_manager::TaskTimeObserver*);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc index eeda5a8d..95ffa36a 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
@@ -4,12 +4,28 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h" +#include "base/feature_list.h" #include "base/memory/memory_pressure_listener.h" +#include "base/metrics/field_trial_params.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/page/launching_process_state.h" namespace blink { +namespace { + +base::TimeDelta FreezePurgeMemoryAllPagesFrozenDelay() { + static const base::FeatureParam<int> + kFreezePurgeMemoryAllPagesFrozenDelayInMinutes{ + &blink::features::kFreezePurgeMemoryAllPagesFrozen, + "delay-in-minutes", + MemoryPurgeManager::kDefaultTimeToPurgeAfterFreezing}; + return base::TimeDelta::FromMinutes( + kFreezePurgeMemoryAllPagesFrozenDelayInMinutes.Get()); +} + +} // namespace + MemoryPurgeManager::MemoryPurgeManager() : renderer_backgrounded_(kLaunchingProcessIsBackgrounded), total_page_count_(0), @@ -17,20 +33,23 @@ MemoryPurgeManager::~MemoryPurgeManager() = default; -void MemoryPurgeManager::OnPageCreated(bool is_frozen) { +void MemoryPurgeManager::OnPageCreated(PageLifecycleState state) { total_page_count_++; - if (is_frozen) { + if (state == PageLifecycleState::kFrozen) { frozen_page_count_++; } else { base::MemoryPressureListener::SetNotificationsSuppressed(false); } + + if (!CanPurge()) + purge_timer_.Stop(); } -void MemoryPurgeManager::OnPageDestroyed(bool was_frozen) { +void MemoryPurgeManager::OnPageDestroyed(PageLifecycleState state) { DCHECK_GT(total_page_count_, 0); DCHECK_GE(frozen_page_count_, 0); total_page_count_--; - if (was_frozen) + if (state == PageLifecycleState::kFrozen) frozen_page_count_--; DCHECK_LE(frozen_page_count_, total_page_count_); } @@ -39,9 +58,27 @@ DCHECK_LT(frozen_page_count_, total_page_count_); frozen_page_count_++; + if (purge_timer_.IsRunning()) + return; + if (!CanPurge()) return; + purge_timer_.Start(FROM_HERE, FreezePurgeMemoryAllPagesFrozenDelay(), this, + &MemoryPurgeManager::PerformMemoryPurge); +} + +void MemoryPurgeManager::OnPageResumed() { + DCHECK_GT(frozen_page_count_, 0); + frozen_page_count_--; + if (!CanPurge()) + purge_timer_.Stop(); + base::MemoryPressureListener::SetNotificationsSuppressed(false); +} + +void MemoryPurgeManager::PerformMemoryPurge() { + DCHECK(CanPurge()); + base::MemoryPressureListener::NotifyMemoryPressure( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); @@ -49,18 +86,22 @@ base::MemoryPressureListener::SetNotificationsSuppressed(true); } -void MemoryPurgeManager::OnPageUnfrozen() { - DCHECK_GT(frozen_page_count_, 0); - frozen_page_count_--; - base::MemoryPressureListener::SetNotificationsSuppressed(false); -} - void MemoryPurgeManager::SetRendererBackgrounded(bool backgrounded) { + if (!backgrounded) + purge_timer_.Stop(); renderer_backgrounded_ = backgrounded; } bool MemoryPurgeManager::CanPurge() const { - return renderer_backgrounded_; + if (!renderer_backgrounded_) + return false; + + if (!AreAllPagesFrozen() && base::FeatureList::IsEnabled( + features::kFreezePurgeMemoryAllPagesFrozen)) { + return false; + } + + return true; } bool MemoryPurgeManager::AreAllPagesFrozen() const {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h index 39c9a99..907145f 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
@@ -6,7 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MEMORY_PURGE_MANAGER_H_ #include "base/macros.h" +#include "base/timer/timer.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h" namespace blink { @@ -18,23 +20,36 @@ // Called when a page is created or destroyed, to maintain the total count of // pages owned by a renderer. - void OnPageCreated(bool is_frozen); - void OnPageDestroyed(bool was_frozen); + void OnPageCreated(PageLifecycleState state); + void OnPageDestroyed(PageLifecycleState state); - // Called when a page is frozen. If the renderer is backgrounded, sends a - // critical memory pressure signal to purge memory. + // Called when a page is frozen. If all pages are frozen or + // |kFreezePurgeMemoryAllPagesFrozen| is disabled, and the renderer is + // backgrounded, ensures that a delayed memory purge is scheduled. void OnPageFrozen(); - // Called when a page is unfrozen. Has the effect of unsuppressing memory - // pressure notifications. - void OnPageUnfrozen(); + // Called when a page is resumed (unfrozen). Has the effect of unsuppressing + // memory pressure notifications. + void OnPageResumed(); // Called when the renderer's process priority changes. void SetRendererBackgrounded(bool backgrounded); + // The time of purging after all pages have been frozen. + static constexpr int kDefaultTimeToPurgeAfterFreezing = 0; + private: + // Called when the timer expires. Simulates a critical memory pressure signal + // to purge memory. Suppresses memory pressure notifications if all pages + // are frozen. + void PerformMemoryPurge(); + + // Returns true if all of the following are true: + // - The renderer is backgrounded. + // - All pages are frozen or kFreezePurgeMemoryAllPagesFrozen is disabled. bool CanPurge() const; + // Returns true if |total_page_count_| == |frozen_page_count_| bool AreAllPagesFrozen() const; bool renderer_backgrounded_; @@ -42,6 +57,11 @@ int total_page_count_; int frozen_page_count_; + // Timer to delay memory purging. + // + // TODO(adityakeerthi): This timer should use a best-effort task runner. + base::OneShotTimer purge_timer_; + DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManager); };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc index ae13213..624111b 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
@@ -5,111 +5,265 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h" #include "base/memory/memory_pressure_listener.h" -#include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h" namespace blink { +namespace { + +constexpr base::TimeDelta kDelayForPurgeAfterFreeze = + base::TimeDelta::FromMinutes(1); + class MemoryPurgeManagerTest : public testing::Test { public: - MemoryPurgeManagerTest() = default; + MemoryPurgeManagerTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME, + base::test::ScopedTaskEnvironment::NowSource:: + MAIN_THREAD_MOCK_TIME), + observed_memory_pressure_(false) {} void SetUp() override { memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(base::BindRepeating( &MemoryPurgeManagerTest::OnMemoryPressure, base::Unretained(this))); base::MemoryPressureListener::SetNotificationsSuppressed(false); + + // Set an initial delay to ensure that the first call to TimeTicks::Now() + // before incrementing the counter does not return a null value. + FastForwardBy(base::TimeDelta::FromSeconds(1)); } - void TearDown() override { memory_pressure_listener_.reset(); } + void TearDown() override { + memory_pressure_listener_.reset(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + } protected: + void SetupDelayedPurgeAfterFreezeExperiment() { + scoped_feature_list_.InitAndEnableFeatureWithParameters( + features::kFreezePurgeMemoryAllPagesFrozen, + {{"delay-in-minutes", + base::IntToString(kDelayForPurgeAfterFreeze.InMinutes())}}); + } + void ExpectMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel level) { - EXPECT_CALL(*this, OnMemoryPressure(level)).Times(1); - base::RunLoop().RunUntilIdle(); + base::TimeDelta delay = base::TimeDelta::FromMinutes(0)) { + FastForwardBy(delay); + EXPECT_TRUE(observed_memory_pressure_); + observed_memory_pressure_ = false; } - void ExpectNoMemoryPressure() { - EXPECT_CALL(*this, OnMemoryPressure(testing::_)).Times(0); - base::RunLoop().RunUntilIdle(); + void ExpectNoMemoryPressure( + base::TimeDelta delay = base::TimeDelta::FromMinutes(0)) { + FastForwardBy(delay); + EXPECT_FALSE(observed_memory_pressure_); } + void FastForwardBy(base::TimeDelta delta) { + scoped_task_environment_.FastForwardBy(delta); + } + + base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; + bool observed_memory_pressure_; + MemoryPurgeManager memory_purge_manager_; private: - MOCK_METHOD1(OnMemoryPressure, - void(base::MemoryPressureListener::MemoryPressureLevel)); + void OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel) { + observed_memory_pressure_ = true; + } + DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManagerTest); }; // Verify that OnPageFrozen() triggers a memory pressure notification in a // backgrounded renderer. TEST_F(MemoryPurgeManagerTest, PageFrozenInBackgroundedRenderer) { - memory_purge_manager_.OnPageCreated(false /* is_frozen */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(true); memory_purge_manager_.OnPageFrozen(); - ExpectMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_CRITICAL); + ExpectMemoryPressure(); } // Verify that OnPageFrozen() does not trigger a memory pressure notification in // a foregrounded renderer. TEST_F(MemoryPurgeManagerTest, PageFrozenInForegroundedRenderer) { - memory_purge_manager_.OnPageCreated(false /* is_frozen */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(false); memory_purge_manager_.OnPageFrozen(); ExpectNoMemoryPressure(); } -TEST_F(MemoryPurgeManagerTest, PageUnfrozenUndoMemoryPressureSuppression) { - memory_purge_manager_.OnPageCreated(false /* is_frozen */); +TEST_F(MemoryPurgeManagerTest, PageResumedUndoMemoryPressureSuppression) { + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(true); memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(); EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageUnfrozen(); + memory_purge_manager_.OnPageResumed(); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageDestroyed(false /* was_frozen */); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); } -TEST_F(MemoryPurgeManagerTest, - PageFrozenMemorySuppressionOnlyWhenAllPagesFrozen) { +TEST_F(MemoryPurgeManagerTest, PageFrozenPurgeMemoryAllPagesFrozenDisabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {} /* enabled */, + {features::kFreezePurgeMemoryAllPagesFrozen} /* disabled */); + memory_purge_manager_.SetRendererBackgrounded(true); - memory_purge_manager_.OnPageCreated(false /* is_frozen */); - memory_purge_manager_.OnPageCreated(false /* is_frozen */); - memory_purge_manager_.OnPageCreated(false /* is_frozen */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(); EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageUnfrozen(); + memory_purge_manager_.OnPageResumed(); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageDestroyed(false /* was_frozen */); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageCreated(false /* is_frozen */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - memory_purge_manager_.OnPageDestroyed(false /* was_frozen */); - memory_purge_manager_.OnPageDestroyed(true /* was_frozen */); - memory_purge_manager_.OnPageDestroyed(true /* was_frozen */); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); } +TEST_F(MemoryPurgeManagerTest, PageFrozenPurgeMemoryAllPagesFrozenEnabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {features::kFreezePurgeMemoryAllPagesFrozen} /* enabled */, + {} /* disabled */); + + memory_purge_manager_.SetRendererBackgrounded(true); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.OnPageFrozen(); + ExpectNoMemoryPressure(); + EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageFrozen(); + ExpectNoMemoryPressure(); + EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(); + EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageResumed(); + EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); + EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); +} + +TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelay) { + SetupDelayedPurgeAfterFreezeExperiment(); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + + // The memory pressure notification should not occur immediately + ExpectNoMemoryPressure(); + + // The memory pressure notification should occur after 1 minute + ExpectMemoryPressure(kDelayForPurgeAfterFreeze); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); +} + +TEST_F(MemoryPurgeManagerTest, CancelMemoryPurgeWithDelay) { + SetupDelayedPurgeAfterFreezeExperiment(); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + FastForwardBy(base::TimeDelta::FromSeconds(40)); + ExpectNoMemoryPressure(); + + // If the page is resumed before the memory purge timer expires, the purge + // should be cancelled. + memory_purge_manager_.OnPageResumed(); + ExpectNoMemoryPressure(kDelayForPurgeAfterFreeze); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); +} + +TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelayNewActivePageCreated) { + SetupDelayedPurgeAfterFreezeExperiment(); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + FastForwardBy(base::TimeDelta::FromSeconds(40)); + ExpectNoMemoryPressure(); + + // All pages are no longer frozen, the memory purge should be cancelled. + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + ExpectNoMemoryPressure(kDelayForPurgeAfterFreeze); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); +} + +TEST_F(MemoryPurgeManagerTest, MemoryPurgeWithDelayNewFrozenPageCreated) { + SetupDelayedPurgeAfterFreezeExperiment(); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + FastForwardBy(base::TimeDelta::FromSeconds(40)); + ExpectNoMemoryPressure(); + + // All pages are still frozen and the memory purge should occur. + memory_purge_manager_.OnPageCreated(PageLifecycleState::kFrozen); + ExpectMemoryPressure(kDelayForPurgeAfterFreeze); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); +} + +} // namespace + } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc index 7ddb029..cb665a63 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -125,6 +125,10 @@ background_time_budget_pool_(nullptr), delegate_(delegate), weak_factory_(this) { + page_lifecycle_state_tracker_.reset(new PageLifecycleStateTracker( + this, kDefaultPageVisibility == PageVisibilityState::kVisible + ? PageLifecycleState::kActive + : PageLifecycleState::kHiddenBackgrounded)); main_thread_scheduler->AddPageScheduler(this); do_throttle_page_callback_.Reset(base::BindRepeating( &PageSchedulerImpl::DoThrottlePage, base::Unretained(this))); @@ -143,10 +147,6 @@ } else { delay_for_background_tab_freezing_ = kDelayForBackgroundTabFreezing; } - page_lifecycle_state_tracker_.reset(new PageLifecycleStateTracker( - this, kDefaultPageVisibility == PageVisibilityState::kVisible - ? PageLifecycleState::kActive - : PageLifecycleState::kHiddenBackgrounded)); } PageSchedulerImpl::~PageSchedulerImpl() { @@ -252,7 +252,7 @@ page_lifecycle_state_tracker_->SetPageLifecycleState( PageLifecycleState::kHiddenForegrounded); } - main_thread_scheduler_->OnPageUnfrozen(); + main_thread_scheduler_->OnPageResumed(); } } @@ -587,6 +587,10 @@ SetPageFrozenImpl(true, NotificationPolicy::kNotifyFrames); } +PageLifecycleState PageSchedulerImpl::GetPageLifecycleState() const { + return page_lifecycle_state_tracker_->GetPageLifecycleState(); +} + PageSchedulerImpl::PageLifecycleStateTracker::PageLifecycleStateTracker( PageSchedulerImpl* page_scheduler_impl, PageLifecycleState state) @@ -611,6 +615,11 @@ current_state_ = new_state; } +PageLifecycleState +PageSchedulerImpl::PageLifecycleStateTracker::GetPageLifecycleState() const { + return current_state_; +} + // static base::Optional<PageSchedulerImpl::PageLifecycleStateTransition> PageSchedulerImpl::PageLifecycleStateTracker::
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h index e9e0e9a..b521831 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
@@ -107,6 +107,8 @@ // Return a number of child web frame schedulers for this PageScheduler. size_t FrameCount() const; + PageLifecycleState GetPageLifecycleState() const; + // Generally UKMs are asssociated with the main frame of a page, but the // implementation allows to request a recorder from any local frame with // the same result (e.g. for OOPIF support), therefore we need to select @@ -163,6 +165,7 @@ ~PageLifecycleStateTracker() = default; void SetPageLifecycleState(PageLifecycleState); + PageLifecycleState GetPageLifecycleState() const; private: static base::Optional<PageLifecycleStateTransition>
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.cc b/third_party/blink/renderer/platform/weborigin/security_origin.cc index d629c18ca..afd8cd2d 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin.cc +++ b/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -29,7 +29,10 @@ #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include <stdint.h> + #include <memory> +#include <string> +#include <utility> #include "net/base/url_util.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -433,6 +436,10 @@ } bool SecurityOrigin::IsPotentiallyTrustworthy() const { + // TODO(lukasza): The code below can hopefully be eventually deleted and + // IsOriginPotentiallyTrustworthy can be used instead (from + // //services/network/public/cpp/is_potentially_trustworthy.h). + DCHECK_NE(protocol_, "data"); if (IsOpaque())
diff --git a/third_party/blink/web_tests/ASANExpectations b/third_party/blink/web_tests/ASANExpectations index d648a7e7..b5b04b5 100644 --- a/third_party/blink/web_tests/ASANExpectations +++ b/third_party/blink/web_tests/ASANExpectations
@@ -48,7 +48,9 @@ crbug.com/438499 [ Linux ] http/tests/websocket/workers/worker-simple.html [ Timeout ] crbug.com/438499 [ Linux ] http/tests/workers/text-encoding.html [ Timeout ] crbug.com/438499 [ Linux ] http/tests/devtools/profiler/heap-snapshot-loader.js [ Timeout ] +crbug.com/438499 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/profiler/heap-snapshot-loader.js [ Timeout ] crbug.com/438499 [ Linux ] http/tests/devtools/profiler/heap-snapshot-containment-show-all.js [ Timeout ] +crbug.com/438499 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/profiler/heap-snapshot-containment-show-all.js [ Timeout ] crbug.com/438499 [ Linux ] virtual/threaded/animations/unanimated-style.html [ Timeout ] # Flakily timeout on Linux ASAN bots. @@ -56,7 +58,9 @@ crbug.com/464065 [ Linux ] media/track/css-cue-for-video-in-shadow.html [ Timeout ] crbug.com/464065 [ Linux ] media/track/css-cue-for-video-in-shadow-2.html [ Timeout ] crbug.com/572723 [ Linux ] http/tests/devtools/sources/debugger/debugger-completions-on-call-frame.js [ Timeout Pass ] +crbug.com/572723 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/sources/debugger/debugger-completions-on-call-frame.js [ Timeout Pass ] crbug.com/700795 [ Linux ] http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Skip ] +crbug.com/700795 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Skip ] crbug.com/928941 [ Linux ] external/wpt/background-fetch/fetch.https.window.html [ Timeout ] # Intentionally failed allocations, via partitionAllocGenericFlags()
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index f896f9d..d7cbba6 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -13,8 +13,13 @@ crbug.com/933880 external/wpt/FileAPI/url/url-with-xhr.any.html [ Failure ] crbug.com/933880 external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/interception-take-stream.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/interception-take-stream.js [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/raw-headers-for-protected-document.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/raw-headers-for-protected-document.js [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/raw-headers-for-websocket.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/raw-headers-for-websocket.js [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/security-info-on-response.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/security-info-on-response.js [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/xhr-interception-auth-fail.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/xhr-interception-auth-fail.js [ Failure ] crbug.com/933880 http/tests/misc/redirect-to-about-blank.html [ Timeout ]
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 3da36dd..e3af792 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -23,6 +23,7 @@ crbug.com/786995 virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Leak Pass ] crbug.com/859640 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Leak Pass ] +crbug.com/859640 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Leak Pass ] # Requests with keepalive specified will be kept alive even when the frame is # detached, which means leaks reported by the leak detector are by design. @@ -35,6 +36,7 @@ # ----------------------------------------------------------------- crbug.com/780386 external/wpt/html/dom/reflection-grouping.html [ Leak Pass ] crbug.com/667560 [ Linux ] http/tests/devtools/console/console-search.js [ Leak Pass ] +crbug.com/667560 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/console/console-search.js [ Leak Pass ] crbug.com/835943 [ Linux ] http/tests/appcache/non-html.xhtml [ Leak Pass ] crbug.com/860117 [ Linux ] editing/pasteboard/drag-drop-iframe-refresh-crash.html [ Pass Leak ] @@ -61,12 +63,14 @@ # Sheriff 2018-07-10 # Test flaking on Linux Trusty Leak crbug.com/862029 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-window-filter.js [ Pass Leak ] +crbug.com/862029 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-misc/timeline-window-filter.js [ Pass Leak ] # Sheriff 2018-08-15 crbug.com/874442 [ Linux ] svg/animations/mpath-remove-from-dependents-on-delete-crash.html [ Pass Crash ] # Sheriff 2018-08-17 crbug.com/847114 [ Linux ] http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] +crbug.com/847114 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] crbug.com/847114 [ Linux ] virtual/threaded/http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] # Sheriff 2018-08-29 @@ -92,6 +96,7 @@ #Sheriff 2019-02-21 crbug.com/934144 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.js [ Pass Leak ] +crbug.com/934144 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.js [ Pass Leak ] #Sheriff 2019-02-25 crbug.com/894651 [ Linux ] virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_word_09_rtl_multi_line.html [ Failure Leak ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations index 7e56cda..17b6538 100644 --- a/third_party/blink/web_tests/MSANExpectations +++ b/third_party/blink/web_tests/MSANExpectations
@@ -15,6 +15,7 @@ crbug.com/422982 [ Linux ] virtual/threaded [ Skip ] crbug.com/700795 [ Linux ] http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Skip ] +crbug.com/700795 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Skip ] crbug.com/454267 [ Linux ] virtual/gpu/fast/canvas/canvas-arc-360-winding.html [ Crash ] crbug.com/454267 [ Linux ] virtual/gpu/fast/canvas/canvas-ellipse-360-winding.html [ Crash ] @@ -44,8 +45,11 @@ crbug.com/462190 [ Linux ] inspector-protocol/heap-profiler/heap-snapshot-with-no-detached-iframe.js [ Timeout ] crbug.com/667560 [ Linux ] http/tests/devtools/startup/console/console-format-startup.js [ Timeout Pass ] +crbug.com/667560 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/startup/console/console-format-startup.js [ Timeout Pass ] crbug.com/751906 [ Linux ] http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ] +crbug.com/751906 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ] crbug.com/811820 [ Linux ] http/tests/devtools/tracing-session-id.js [ Timeout Pass ] +crbug.com/811820 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing-session-id.js [ Timeout Pass ] crbug.com/736370 [ Linux ] external/wpt/editing/run/removeformat.html [ Timeout ] crbug.com/810960 [ Linux ] external/wpt/IndexedDB/nested-cloning-large.html [ Timeout ] @@ -69,32 +73,50 @@ crbug.com/729136 [ Linux ] external/wpt/mimesniff/mime-types/parsing.any.worker.html [ Timeout ] crbug.com/729136 [ Linux ] fast/css/css-selector-deeply-nested.html [ Timeout ] crbug.com/729136 [ Linux ] http/tests/devtools/forced-layout-in-microtask.js [ Timeout ] +crbug.com/729136 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/forced-layout-in-microtask.js [ Timeout ] crbug.com/729136 [ Linux ] http/tests/devtools/tracing/timeline-xhr-response-type-blob-event.js [ Timeout ] +crbug.com/729136 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-xhr-response-type-blob-event.js [ Timeout ] crbug.com/729136 [ Linux ] http/tests/devtools/components/file-path-scoring.js [ Timeout ] +crbug.com/729136 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/components/file-path-scoring.js [ Timeout ] crbug.com/729136 [ Linux ] http/tests/devtools/elements/styles-4/styles-should-not-force-sync-style-recalc.js [ Timeout ] +crbug.com/729136 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/styles-should-not-force-sync-style-recalc.js [ Timeout ] crbug.com/729136 [ Linux ] webaudio/mixing.html [ Timeout ] crbug.com/739365 [ Linux ] virtual/layout_ng/fast/block/float/assert-when-moving-float.html [ Skip ] # Tests timing out on WebKit Linux Trusty MSAN crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidations.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidations.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Pass Timeout ] crbug.com/760543 [ Linux ] http/tests/devtools/oopif/oopif-performance-cpu-profiles.js [ Pass Timeout ] +crbug.com/760543 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js [ Pass Timeout ] crbug.com/902685 [ Linux ] http/tests/devtools/isolated-code-cache/same-origin-test.js [ Pass Timeout ] +crbug.com/902685 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Pass Timeout ] crbug.com/902685 [ Linux ] http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Pass Timeout ] +crbug.com/902685 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Pass Timeout ] crbug.com/902685 [ Linux ] virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Pass Timeout ] crbug.com/902685 [ Linux ] virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Pass Timeout ] # Timing out consistenly on WebKit Linux Trusty MSAN crbug.com/798957 [ Linux ] http/tests/devtools/audits2/audits2-limited-run.js [ Skip ] +crbug.com/798957 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/audits2/audits2-limited-run.js [ Skip ] crbug.com/798957 [ Linux ] http/tests/devtools/audits2/audits2-successful-run.js [ Skip ] +crbug.com/798957 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/audits2/audits2-successful-run.js [ Skip ] crbug.com/824455 [ Linux ] external/wpt/webaudio/idlharness.https.html [ Skip ] # Memory allocation hooks are disabled on ASAN/MSAN @@ -105,6 +127,7 @@ # The following test is flaky and timing out on chromium.webkit/WebKit Linux Trusty MSAN. crbug.com/851497 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Timeout ] +crbug.com/851497 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Timeout ] crbug.com/862750 [ Linux ] inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Pass Crash ] crbug.com/862750 [ Linux ] virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Pass Crash ] @@ -114,6 +137,7 @@ crbug.com/856601 [ Linux ] fast/css/visited-link-hang.html [ Pass Timeout ] crbug.com/856601 [ Linux ] http/tests/devtools/elements/styles-4/styles-inline-element-style-changes-should-not-force-style-recalc.js [ Pass Timeout ] +crbug.com/856601 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/styles-inline-element-style-changes-should-not-force-style-recalc.js [ Pass Timeout ] crbug.com/856601 [ Linux ] external/wpt/event-timing/event-timing-retrievability.html [ Pass Timeout ] # Slow idlharness.js tests on MSAN @@ -203,6 +227,7 @@ # Sheriff 2018-11-22 crbug.com/856601 [ Linux ] http/tests/devtools/elements/elements-save-to-temp-var.js [ Pass Timeout ] +crbug.com/856601 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/elements-save-to-temp-var.js [ Pass Timeout ] # Sheriff 2018-12-13 crbug.com/914900 [ Linux ] external/wpt/content-security-policy/embedded-enforcement/idlharness.window.html [ Pass Timeout ] @@ -210,6 +235,7 @@ crbug.com/914900 [ Linux ] external/wpt/fetch/api/idl.any.worker.html [ Pass Timeout ] crbug.com/914900 [ Linux ] external/wpt/secure-contexts/idlharness.any.worker.html [ Pass Timeout ] crbug.com/914900 [ Linux ] http/tests/devtools/network/preview-searchable.js [ Pass Timeout ] +crbug.com/914900 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/network/preview-searchable.js [ Pass Timeout ] crbug.com/914900 [ Linux ] virtual/outofblink-cors/external/wpt/xhr/idlharness.any.worker.html [ Pass Timeout ] # Sheriff 2019-01-28
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 2565b84..dc1a2a66 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -2204,6 +2204,7 @@ # 3) site isolation is enabled without also enabling # IsolatedCodeCache (tests disabled by the test expectation below). Bug(none) http/tests/devtools/isolated-code-cache/cross-origin-test.js [ WontFix ] +Bug(none) virtual/binary-for-devtools/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ WontFix ] # ==== Tests incompatible with the default WPT Origin Isolation end here ==^^ external/wpt/css/css-overscroll-behavior/overscrollBehavior-manual.html [ WontFix ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 5878b9bf..e5c0334 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -78,47 +78,76 @@ # Most DevTools tests are slow in Debug. webkit.org/b/90488 [ Debug ] http/tests/devtools/ [ Slow ] +webkit.org/b/90488 [ Debug ] virtual/binary-for-devtools/http/tests/devtools/ [ Slow ] webkit.org/b/90488 [ Debug ] inspector-protocol/ [ Slow ] # DevTools console, debugger and profiler tests are slow in Release as well. crbug.com/451577 http/tests/devtools/console [ Slow ] +crbug.com/451577 virtual/binary-for-devtools/http/tests/devtools/console [ Slow ] crbug.com/450493 http/tests/devtools/sources/ [ Slow ] +crbug.com/450493 virtual/binary-for-devtools/http/tests/devtools/sources/ [ Slow ] crbug.com/450493 http/tests/devtools/startup/sources/ [ Slow ] +crbug.com/450493 virtual/binary-for-devtools/http/tests/devtools/startup/sources/ [ Slow ] crbug.com/450493 http/tests/devtools/csp/ [ Slow ] +crbug.com/450493 virtual/binary-for-devtools/http/tests/devtools/csp/ [ Slow ] crbug.com/450493 http/tests/devtools/profiler/ [ Slow ] +crbug.com/450493 virtual/binary-for-devtools/http/tests/devtools/profiler/ [ Slow ] crbug.com/420008 http/tests/devtools/tracing/ [ Slow ] +crbug.com/420008 virtual/binary-for-devtools/http/tests/devtools/tracing/ [ Slow ] crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/ [ Slow ] crbug.com/902685 http/tests/devtools/isolated-code-cache/ [ Slow ] +crbug.com/902685 virtual/binary-for-devtools/http/tests/devtools/isolated-code-cache/ [ Slow ] crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/ [ Slow ] crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/ [ Slow ] crbug.com/902685 http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] +crbug.com/902685 virtual/binary-for-devtools/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] crbug.com/902685 virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] # Misc DevTools tests that are slow crbug.com/246190 [ Release ] http/tests/devtools/indexeddb/ [ Slow ] +crbug.com/246190 [ Release ] virtual/binary-for-devtools/http/tests/devtools/indexeddb/ [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/extensions/extensions-sidebar.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-sidebar.js [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/extensions/extensions-events.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-events.js [ Slow ] crbug.com/667560 http/tests/devtools/startup/console/console-format-startup.js [ Slow ] +crbug.com/667560 virtual/binary-for-devtools/http/tests/devtools/startup/console/console-format-startup.js [ Slow ] crbug.com/679833 http/tests/devtools/network/network-datareceived.js [ Slow ] +crbug.com/679833 virtual/binary-for-devtools/http/tests/devtools/network/network-datareceived.js [ Slow ] webkit.org/b/90488 [ Release ] http/tests/devtools/compiler-source-mapping-debug.js [ Slow ] +webkit.org/b/90488 [ Release ] virtual/binary-for-devtools/http/tests/devtools/compiler-source-mapping-debug.js [ Slow ] crbug.com/243492 inspector-protocol/injected-script-discard.js [ Slow ] crbug.com/327078 http/tests/devtools/network/long-script-content.js [ Slow ] +crbug.com/327078 virtual/binary-for-devtools/http/tests/devtools/network/long-script-content.js [ Slow ] crbug.com/420008 [ Release ] http/tests/devtools/editor/text-editor-word-jumps.js [ Slow ] +crbug.com/420008 [ Release ] virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-word-jumps.js [ Slow ] crbug.com/420008 [ Release ] http/tests/devtools/console-xhr-logging.js [ Slow ] +crbug.com/420008 [ Release ] virtual/binary-for-devtools/http/tests/devtools/console-xhr-logging.js [ Slow ] crbug.com/596486 [ Linux ] http/tests/devtools/elements/insert-node.js [ Slow ] +crbug.com/596486 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/insert-node.js [ Slow ] crbug.com/504565 [ Mac ] http/tests/devtools/search/sources-search-scope.js [ Slow ] +crbug.com/504565 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/search/sources-search-scope.js [ Slow ] crbug.com/451577 http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js [ Slow ] +crbug.com/451577 virtual/binary-for-devtools/http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js [ Slow ] crbug.com/451577 http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js [ Slow ] +crbug.com/451577 virtual/binary-for-devtools/http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js [ Slow ] crbug.com/510337 http/tests/devtools/elements/styles-1/edit-value-url-with-color.js [ Slow ] +crbug.com/510337 virtual/binary-for-devtools/http/tests/devtools/elements/styles-1/edit-value-url-with-color.js [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/extensions/extensions-reload.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-reload.js [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/extensions/extensions-resources.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-resources.js [ Slow ] crbug.com/451577 [ Win10 ] http/tests/devtools/extensions/extensions-sidebar.js [ Slow ] +crbug.com/451577 [ Win10 ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-sidebar.js [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/layers/layer-canvas-log.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/layers/layer-canvas-log.js [ Slow ] crbug.com/451577 [ Mac ] http/tests/devtools/network/network-domain-filter.js [ Slow ] +crbug.com/451577 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/network/network-domain-filter.js [ Slow ] crbug.com/510337 cssom/cssvalue-comparison.html [ Slow ] crbug.com/680917 http/tests/devtools/audits2/ [ Slow ] +crbug.com/680917 virtual/binary-for-devtools/http/tests/devtools/audits2/ [ Slow ] # These tests are intentionally SLOW because of throttled loading. crbug.com/73609 http/tests/media/video-play-stall.html [ Slow ] @@ -173,20 +202,25 @@ crbug.com/492664 external/wpt/css/css-writing-modes/text-orientation-script-001o.html [ Slow ] crbug.com/336481 http/tests/devtools/jump-to-previous-editing-location.js [ Slow ] +crbug.com/336481 virtual/binary-for-devtools/http/tests/devtools/jump-to-previous-editing-location.js [ Slow ] crbug.com/346259 http/tests/websocket/no-crash-on-cookie-flood.html [ Slow ] crbug.com/522646 http/tests/media/encrypted-media/encrypted-media-encrypted-event-different-origin.html [ Slow ] crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Slow ] crbug.com/411164 [ Win ] virtual/outofblink-cors/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Slow ] crbug.com/510337 http/tests/devtools/console/console-format.js [ Slow ] +crbug.com/510337 virtual/binary-for-devtools/http/tests/devtools/console/console-format.js [ Slow ] crbug.com/357427 http/tests/workers/terminate-during-sync-operation-file.html [ Slow ] crbug.com/357427 http/tests/workers/terminate-during-sync-operation-filesystem.html [ Slow ] crbug.com/402379 [ Debug ] storage/indexeddb/cursor-continue-validity.html [ Slow ] crbug.com/402379 [ Debug ] storage/indexeddb/mozilla/indexes.html [ Slow ] crbug.com/480769 http/tests/devtools/service-workers/service-workers-redundant.js [ Slow ] +crbug.com/480769 virtual/binary-for-devtools/http/tests/devtools/service-workers/service-workers-redundant.js [ Slow ] crbug.com/480769 http/tests/devtools/service-workers/service-worker-agents.js [ Slow ] +crbug.com/480769 virtual/binary-for-devtools/http/tests/devtools/service-workers/service-worker-agents.js [ Slow ] crbug.com/504703 inspector-protocol/debugger/debugger-step-into-dedicated-worker.js [ Slow ] crbug.com/548765 http/tests/devtools/console-fetch-logging.js [ Slow ] +crbug.com/548765 virtual/binary-for-devtools/http/tests/devtools/console-fetch-logging.js [ Slow ] crbug.com/419993 [ Debug ] fast/css/giant-stylesheet-crash.html [ Slow ] @@ -205,6 +239,7 @@ crbug.com/528419 http/tests/devtools/elements/styles-2/pseudo-elements.js [ Slow ] +crbug.com/528419 virtual/binary-for-devtools/http/tests/devtools/elements/styles-2/pseudo-elements.js [ Slow ] crbug.com/802029 fast/dom/shadow/focus-controller-recursion-crash.html [ Slow ] @@ -254,7 +289,9 @@ # These tests were previously marked Slow in ASANExpectations. crbug.com/451577 [ Linux ] http/tests/devtools/elements/user-properties.js [ Slow ] +crbug.com/451577 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/user-properties.js [ Slow ] crbug.com/451577 [ Linux ] http/tests/devtools/layers/layer-canvas-log.js [ Slow ] +crbug.com/451577 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/layers/layer-canvas-log.js [ Slow ] # These imported tests exercise tens of thousands of code points and generate large results. crbug.com/736056 external/wpt/encoding/legacy-mb-japanese [ Slow ] @@ -324,6 +361,7 @@ crbug.com/800359 external/wpt/mimesniff/mime-types/parsing.any.worker.html [ Slow ] crbug.com/808185 [ Win Release ] http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Slow ] +crbug.com/808185 [ Win Release ] virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Slow ] # OffscreenCanvas non-virtual convert-to-blob tests # These two tests are running without idle-task support in non-virtual @@ -462,8 +500,11 @@ crbug.com/874695 external/wpt/xhr/xmlhttprequest-timeout-worker-synconworker.html [ Slow ] crbug.com/874695 external/wpt/xhr/xmlhttprequest-timeout-worker-twice.html [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-shifted-breakpoint.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-shifted-breakpoint.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/sourcemap-hot-reload.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/sourcemap-hot-reload.js [ Slow ] crbug.com/874695 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Slow ] crbug.com/874695 virtual/outofblink-cors/external/wpt/fetch/http-cache/cc-request.html [ Slow ] crbug.com/874695 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Slow ] crbug.com/874695 virtual/outofblink-cors/external/wpt/xhr/sync-no-timeout.any.html [ Slow ] @@ -853,21 +894,37 @@ crbug.com/874695 http/tests/credentialmanager/credentialscontainer-get-origins.html [ Slow ] crbug.com/874695 http/tests/credentialmanager/register-then-sign.html [ Slow ] crbug.com/874695 http/tests/devtools/audits2/audits2-limited-run.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/audits2/audits2-limited-run.js [ Slow ] crbug.com/874695 http/tests/devtools/audits2/audits2-successful-run.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/audits2/audits2-successful-run.js [ Slow ] crbug.com/874695 http/tests/devtools/console/console-correct-suggestions.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/console/console-correct-suggestions.js [ Slow ] crbug.com/874695 http/tests/devtools/editor/text-editor-formatter.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-formatter.js [ Slow ] crbug.com/874695 http/tests/devtools/inspect-iframe-from-different-domain.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/inspect-iframe-from-different-domain.js [ Slow ] crbug.com/874695 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-cookies-refresh.js [ Slow ] crbug.com/874695 http/tests/devtools/persistence/persistence-mimetype-on-rename.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/persistence/persistence-mimetype-on-rename.js [ Slow ] crbug.com/874695 http/tests/devtools/service-workers/user-agent-override.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/service-workers/user-agent-override.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-in-multiple-workers.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-in-multiple-workers.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger/debugger-proto-property.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger/debugger-proto-property.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger-frameworks/frameworks-dom-xhr-event-breakpoints.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-frameworks/frameworks-dom-xhr-event-breakpoints.js [ Slow ] crbug.com/874695 http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Slow ] crbug.com/874695 http/tests/devtools/tracing/decode-resize.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/tracing/decode-resize.js [ Slow ] crbug.com/874695 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Slow ] crbug.com/874695 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ] crbug.com/874695 external/wpt/event-timing/event-timing-bufferbeforeonload.html [ Slow ] crbug.com/874695 external/wpt/event-timing/event-timing-crossiframe.html [ Slow ] crbug.com/874695 external/wpt/event-timing/event-timing-observethenonload.html [ Slow ] @@ -949,10 +1006,13 @@ crbug.com/874695 http/tests/images/png-progressive-load.html [ Slow ] crbug.com/874695 http/tests/images/webp-progressive-load.html [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Slow ] +crbug.com/874695 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Slow ] crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-none.js [ Slow ] +crbug.com/874695 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-none.js [ Slow ] crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-none.js [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Slow ] +crbug.com/874695 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Slow ] crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Slow ] crbug.com/874695 http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Slow ] crbug.com/874695 http/tests/media/preload-conditions.html [ Slow ] @@ -1293,7 +1353,9 @@ crbug.com/874695 virtual/streaming-preload/http/tests/fetch/workers/thorough/scheme-blob-base-https-other-https.html [ Slow ] crbug.com/874695 virtual/streaming-preload/http/tests/fetch/workers/thorough/scheme-data-base-https-other-https.html [ Slow ] crbug.com/874695 http/tests/devtools/sxg/sxg-cert-not-found.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sxg/sxg-cert-not-found.js [ Slow ] crbug.com/874695 http/tests/devtools/sxg/sxg-disable-cache.js [ Slow ] +crbug.com/874695 virtual/binary-for-devtools/http/tests/devtools/sxg/sxg-disable-cache.js [ Slow ] crbug.com/874695 virtual/threaded/animations/svg/animated-filter-svg-element.html [ Slow ] crbug.com/874695 virtual/disable-blink-gen-property-trees/animations/svg/animated-filter-svg-element.html [ Slow ] crbug.com/874695 virtual/threaded/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 524cb999..b0054e6 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -165,10 +165,15 @@ # Tests temporarily disabled with Site Isolation - uninvestigated bugs: # TODO(lukasza, alexmos): Burn down this list. crbug.com/608015 http/tests/inspector-protocol/access-inspected-object.js [ Failure Timeout ] +crbug.com/608015 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/access-inspected-object.js [ Failure Timeout ] crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Timeout ] +crbug.com/623268 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Timeout ] crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-none.js [ Timeout ] +crbug.com/623268 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-none.js [ Timeout ] crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Timeout ] +crbug.com/623268 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Timeout ] crbug.com/678482 http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] +crbug.com/678482 virtual/binary-for-devtools/http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] crbug.com/678491 http/tests/misc/webtiming-no-origin.html [ Crash Pass ] crbug.com/765779 http/tests/loading/bad-server-subframe.html [ Failure ] crbug.com/793127 external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html [ Crash ] @@ -185,7 +190,9 @@ crbug.com/895001 http/tests/media/autoplay/webaudio-autoplay-iframe-with-gesture.html [ Timeout Pass ] crbug.com/895001 virtual/user-activation-v2/http/tests/media/autoplay/webaudio-autoplay-iframe-with-gesture.html [ Timeout Pass ] crbug.com/901502 http/tests/devtools/oopif/oopif-storage.js [ Pass Failure ] +crbug.com/901502 virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-storage.js [ Pass Failure ] crbug.com/906879 http/tests/inspector-protocol/network/navigation-blocking-xorigin-iframe.js [ Pass Failure ] +crbug.com/906879 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/navigation-blocking-xorigin-iframe.js [ Pass Failure ] # ====== Site Isolation failures until here ====== # ====== Oilpan-only failures from here ====== @@ -197,7 +204,9 @@ # ====== Browserside navigation from here ====== # These tests started failing when browser-side navigation was turned on. crbug.com/762529 http/tests/devtools/network/network-datareceived.js [ Failure ] +crbug.com/762529 virtual/binary-for-devtools/http/tests/devtools/network/network-datareceived.js [ Failure ] crbug.com/759632 http/tests/devtools/network/network-datasaver-warning.js [ Failure ] +crbug.com/759632 virtual/binary-for-devtools/http/tests/devtools/network/network-datasaver-warning.js [ Failure ] # ====== Browserside navigation until here ====== crbug.com/915472 inspector-protocol/worker/worker-autoattach-order.js [ Failure Pass ] @@ -273,6 +282,7 @@ crbug.com/309675 compositing/gestures/gesture-tapHighlight-simple-longPress.html [ Failure ] crbug.com/845267 [ Mac ] http/tests/inspector-protocol/page/page-lifecycleEvents.js [ Failure Pass ] +crbug.com/845267 [ Mac ] virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/page/page-lifecycleEvents.js [ Failure Pass ] # SwiftShader Failures crbug.com/726075 [ Win ] compositing/3d-cube.html [ Failure ] @@ -359,6 +369,7 @@ # These tests are no longer applicable in BlinkGenPropertyTree mode. # TODO(wangxianzhu): Remove them when we remove non-BlinkGenPropertyTree code. Bug(none) http/tests/devtools/layers/layer-sticky-position-constraint-get.js [ Skip ] +Bug(none) virtual/binary-for-devtools/http/tests/devtools/layers/layer-sticky-position-constraint-get.js [ Skip ] Bug(none) inspector-protocol/layers/get-layers.js [ Skip ] # Before we fully launch BlinkGenPropertyTrees, run visual/disable-blink-gen-property-trees/ on Linux. @@ -671,9 +682,6 @@ crbug.com/711704 virtual/layout_ng/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht [ Failure ] -### virtual/layout_ng/external/wpt/css/CSS2/normal-flow -crbug.com/704961 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/width-inherit-001.xht [ Failure ] - # Inline: border in continuations. Fail in Blink. crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001f.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-insert-002f.xht [ Failure ] @@ -692,7 +700,6 @@ crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/replaced-intrinsic-002.xht [ Failure ] ### virtual/layout_ng/external/wpt/css/CSS2/positioning -crbug.com/704961 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/positioning/abspos-027.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/positioning/position-relative-035.xht [ Failure ] ### virtual/layout_ng/fast/block/basic @@ -707,7 +714,6 @@ crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/028.html [ Failure ] crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/float-in-float-hit-testing.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/clear-intruding-floats-when-moving-to-inline-parent-3.html [ Failure Crash Pass ] -crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/floats-and-text-indent.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-in-float-painting.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-list-changed-before-layout-crash.html [ Crash Pass ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling4.html [ Crash Pass ] @@ -717,16 +723,12 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/nopaint-after-layer-destruction2.html [ Failure ] crbug.com/810370 virtual/layout_ng/fast/block/float/overhanging-float-remove-from-fixed-position-block.html [ Failure ] crbug.com/810370 virtual/layout_ng/fast/block/float/overhanging-float-remove-from-fixed-position-block2.html [ Failure ] -crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/overhanging-tall-block.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash.html [ Crash Pass ] crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/width-update-after-clear.html [ Failure ] ### virtual/layout_ng/fast/block/margin-collapse crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/margin-collapse/103.html [ Failure ] -### virtual/layout_ng/fast/inline -crbug.com/635619 [ Mac ] virtual/layout_ng/fast/inline/left-right-center-inline-alignment-in-ltr-and-rtl-blocks.html [ Failure ] - ### virtual/layout_ng/overflow crbug.com/724701 virtual/layout_ng/overflow/overflow-basic-004.html [ Failure ] @@ -748,9 +750,9 @@ # Maybe a Mac-specific rebaselining issue. crbug.com/846557 [ Mac ] virtual/layout_ng_experimental/css3/flexbox/button.html [ Skip ] -crbug.com/591099 [ Mac ] virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-vertical-align-effect.html [ Failure ] crbug.com/835810 [ Win7 ] http/tests/devtools/startup/dom-storage-open.js [ Pass Timeout ] +crbug.com/835810 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/startup/dom-storage-open.js [ Pass Timeout ] ### Image/text failures #crbug.com/714962 virtual/layout_ng/fast/inline/001.html [ Failure ] @@ -771,19 +773,8 @@ crbug.com/714962 virtual/layout_ng/fast/inline/inline-borders-with-bidi-override.html [ Failure ] crbug.com/714962 virtual/layout_ng/fast/inline/outline-continuations.html [ Failure ] -### virtual/layout_ng/external/wpt/css/CSS2/normal-flow/ -crbug.com/714962 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-block-valign-001.xht [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-block-valign-002.xht [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-table-002a.xht [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-table-002b.xht [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-table-valign-001.xht [ Failure ] - ### virtual/layout_ng/fast/block/float/ crbug.com/714962 [ Mac ] virtual/layout_ng/fast/block/float/002.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/block/float/017.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/block/float/float-should-dirty-line-even-when-it-doesnt-intersect-it-3.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/block/float/max-width-clear-float-with-overflow-hidden.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/block/float/trailing-float-with-content.html [ Failure ] ### virtual/layout_ng/fast/writing-mode/ crbug.com/714962 virtual/layout_ng/fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ] @@ -801,8 +792,6 @@ crbug.com/714962 virtual/layout_ng/fast/writing-mode/japanese-lr-selection.html [ Failure ] crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/japanese-lr-text.html [ Failure ] crbug.com/714962 virtual/layout_ng/fast/writing-mode/japanese-rl-selection.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/margins.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/orthogonal-inline-block.html [ Failure ] crbug.com/714962 virtual/layout_ng/fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ] crbug.com/714962 virtual/layout_ng/fast/writing-mode/vertical-align-table-baseline.html [ Failure ] crbug.com/714962 virtual/layout_ng/fast/writing-mode/vertical-baseline-alignment.html [ Failure ] @@ -812,7 +801,6 @@ crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/border-vertical-lr.html [ Failure ] crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/english-lr-text.html [ Failure ] crbug.com/714962 [ Win ] virtual/layout_ng/fast/writing-mode/english-lr-text.html [ Failure ] -crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/japanese-rl-text.html [ Failure ] crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/text-orientation-basic.html [ Failure ] # Crashes/asserts due to inline item reuse. @@ -1838,12 +1826,17 @@ ### sheriff 2018-05-28 crbug.com/840238 http/tests/devtools/elements/shadow/shadow-distribution.js [ Failure ] +crbug.com/840238 virtual/binary-for-devtools/http/tests/devtools/elements/shadow/shadow-distribution.js [ Failure ] crbug.com/667560 [ Debug ] http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass Failure ] +crbug.com/667560 [ Debug ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass Failure ] crbug.com/778515 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Pass Failure ] +crbug.com/778515 virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Pass Failure ] crbug.com/778391 http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Pass Failure ] +crbug.com/778391 virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Pass Failure ] crbug.com/778391 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Pass Failure ] +crbug.com/778391 virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Pass Failure ] crbug.com/767269 [ Win ] inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.js [ Pass Failure ] @@ -1919,8 +1912,6 @@ crbug.com/492664 [ Linux ] external/wpt/css/css-writing-modes/box-offsets-rel-pos-vrl-004.xht [ Failure ] crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/bidi-embed-002.html [ Failure ] crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/bidi-isolate-002.html [ Failure ] -crbug.com/492664 [ Win ] external/wpt/css/css-writing-modes/bidi-override-005.html [ Failure ] -crbug.com/492664 [ Win ] external/wpt/css/css-writing-modes/bidi-plaintext-001.html [ Failure ] crbug.com/280342 [ Mac ] http/tests/media/progress-events-generated-correctly.html [ Failure Pass ] crbug.com/280342 [ Linux ] http/tests/media/progress-events-generated-correctly.html [ Failure Pass ] @@ -1982,6 +1973,7 @@ crbug.com/761798 [ Mac ] inspector-protocol/emulation/device-emulation-desktop.js [ Failure ] crbug.com/771233 [ Win10 ] http/tests/devtools/audits2/ [ Skip ] +crbug.com/771233 [ Win10 ] virtual/binary-for-devtools/http/tests/devtools/audits2/ [ Skip ] crbug.com/923269 virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Failure ] crbug.com/923269 fast/canvas/OffscreenCanvas-copyImage.html [ Failure ] @@ -2064,11 +2056,15 @@ crbug.com/597221 virtual/user-activation-v2/fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ] crbug.com/498539 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] +crbug.com/498539 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] crbug.com/498539 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Pass Failure ] crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Win7 ] http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] +crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Mac ] http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] +crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Linux ] http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] +crbug.com/498539 crbug.com/794869 crbug.com/798548 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/styles-update-from-js.js [ Crash Pass Failure ] crbug.com/889952 fast/selectors/selection-window-inactive.html [ Pass Failure ] @@ -2084,7 +2080,6 @@ # Text::inDocument() returns false but should not. crbug.com/264138 dom/legacy_dom_conformance/xhtml/level3/core/nodecomparedocumentposition38.xhtml [ Failure ] -crbug.com/410145 [ Win ] fast/table/column-in-inline.html [ Failure ] crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass ] crbug.com/411164 [ Win ] virtual/outofblink-cors/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass ] @@ -2160,7 +2155,6 @@ crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-ic-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-ic-003.html [ Failure ] crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-justify-004.html [ Failure ] -crbug.com/626703 [ Win7 ] external/wpt/css/css-text/text-justify/text-justify-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-026.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-028.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-tailoring-001.html [ Failure ] @@ -2325,8 +2319,6 @@ crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-008.xht [ Failure ] crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-020.xht [ Failure ] -crbug.com/498845 [ Win ] fast/multicol/vertical-rl/float-content-break.html [ Failure ] - crbug.com/381684 [ Mac ] fonts/family-fallback-gardiner.html [ Skip ] crbug.com/381684 [ Win ] fonts/family-fallback-gardiner.html [ Skip ] crbug.com/467635 fast/dom/HTMLImageElement/image-sizes-meta-viewport.html [ Skip ] @@ -2390,7 +2382,9 @@ # These contain faulty expectations. https://chromium-review.googlesource.com/c/v8/v8/+/1350790 should fix the # faulty return values but to allow landing that patch, the tests have to be deactivated in the meanwhile. crbug.com/924308 http/tests/devtools/console/console-dir-es6.js [ Pass Failure ] +crbug.com/924308 virtual/binary-for-devtools/http/tests/devtools/console/console-dir-es6.js [ Pass Failure ] crbug.com/924308 http/tests/devtools/console/console-format-es6-2.js [ Pass Failure ] +crbug.com/924308 virtual/binary-for-devtools/http/tests/devtools/console/console-format-es6-2.js [ Pass Failure ] # We only want to run one of the web-animations-api tests in stable mode. crbug.com/441553 virtual/stable/web-animations-api [ Skip ] @@ -2434,6 +2428,7 @@ crbug.com/901906 virtual/threaded/fast/scroll-behavior/smooth-scroll/track-scroll.html [ Pass Failure ] crbug.com/599670 [ Win ] http/tests/devtools/resource-parameters-ipv6.js [ Pass Failure Crash ] +crbug.com/599670 [ Win ] virtual/binary-for-devtools/http/tests/devtools/resource-parameters-ipv6.js [ Pass Failure Crash ] crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Failure ] crbug.com/472330 fast/writing-mode/box-shadow-vertical-lr.html [ Failure ] crbug.com/472330 fast/writing-mode/box-shadow-vertical-rl.html [ Failure ] @@ -2561,8 +2556,11 @@ crbug.com/906847 inspector-protocol/runtime/runtime-getProperties.js [ Skip ] crbug.com/906847 inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js [ Skip ] crbug.com/v8/8672 http/tests/devtools/bindings/suspendtarget-bindings.js [ Skip ] +crbug.com/v8/8672 virtual/binary-for-devtools/http/tests/devtools/bindings/suspendtarget-bindings.js [ Skip ] crbug.com/v8/8672 http/tests/devtools/bindings/suspendtarget-navigator.js [ Skip ] +crbug.com/v8/8672 virtual/binary-for-devtools/http/tests/devtools/bindings/suspendtarget-navigator.js [ Skip ] crbug.com/v8/8672 http/tests/devtools/tracing/decode-resize.js [ Skip ] +crbug.com/v8/8672 virtual/binary-for-devtools/http/tests/devtools/tracing/decode-resize.js [ Skip ] # These testcases are incorrect, mark them as failing until they're fixed in the testsuite. # https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html @@ -2584,9 +2582,7 @@ crbug.com/467127 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-basis-0percent.html [ Failure ] crbug.com/467127 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-shorthand-number.html [ Failure ] crbug.com/467127 [ Mac ] external/wpt/css/css-flexbox/ttwf-reftest-flex-wrap-reverse.html [ Failure ] -crbug.com/467127 [ Win ] external/wpt/css/css-flexbox/ttwf-reftest-flex-wrap-reverse.html [ Failure ] crbug.com/467127 [ Mac ] external/wpt/css/css-flexbox/ttwf-reftest-flex-wrap.html [ Failure ] -crbug.com/467127 [ Win ] external/wpt/css/css-flexbox/ttwf-reftest-flex-wrap.html [ Failure ] crbug.com/467127 external/wpt/css/css-flexbox/negative-margins-001.html [ Failure ] crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001a.xhtml [ Failure ] @@ -2670,6 +2666,7 @@ crbug.com/483653 accessibility/scroll-containers.html [ Skip ] crbug.com/491764 http/tests/devtools/service-workers/user-agent-override.js [ Pass Timeout ] +crbug.com/491764 virtual/binary-for-devtools/http/tests/devtools/service-workers/user-agent-override.js [ Pass Timeout ] # Fails with leak detector. crbug.com/769885 [ Linux ] virtual/android/fullscreen/full-screen-frameset.html [ Skip ] @@ -2685,9 +2682,6 @@ crbug.com/321237 [ Mac ] fast/selectors/007a.html [ Failure ] crbug.com/321237 [ Mac ] fast/text-autosizing/inherited-multiplier.html [ Failure ] crbug.com/321237 [ Win ] fast/text-autosizing/inherited-multiplier.html [ Failure ] -crbug.com/321237 [ Mac ] virtual/stable/fast/css3-text/css3-text-decoration/stable/first-letter-text-decoration.html [ Failure ] -crbug.com/321237 [ Win ] fast/multicol/span/pseudo-before-after-in-content.html [ Failure ] -crbug.com/321237 [ Win ] fast/selectors/004.html [ Failure ] crbug.com/501659 fast/xsl/xslt-missing-namespace-in-xslt.xml [ Failure ] @@ -2757,6 +2751,7 @@ crbug.com/543369 [ Linux ] fast/forms/select-popup/popup-menu-appearance-tall.html [ Failure Pass ] crbug.com/548765 http/tests/devtools/console-fetch-logging.js [ Failure Pass ] +crbug.com/548765 virtual/binary-for-devtools/http/tests/devtools/console-fetch-logging.js [ Failure Pass ] ### See crbug.com/891427 comment near the top of this file: ###crbug.com/564109 [ Win ] http/tests/webfont/font-display-intervention.html [ Pass Failure Timeout ] @@ -2916,11 +2911,14 @@ # Untriaged failures after https://crrev.com/c/543695/. # These need to be updated but appear not to be related to that change. crbug.com/626703 http/tests/devtools/indexeddb/database-refresh-view.js [ Pass Failure ] +crbug.com/626703 virtual/binary-for-devtools/http/tests/devtools/indexeddb/database-refresh-view.js [ Pass Failure ] crbug.com/626703 http/tests/devtools/extensions/extensions-sidebar.js [ Pass Failure ] +crbug.com/626703 virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-sidebar.js [ Pass Failure ] crbug.com/751952 fast/text/international/complex-text-rectangle.html [ Timeout Pass ] crbug.com/751952 [ Mac ] editing/selection/modify_extend/extend_by_character.html [ Failure Pass ] crbug.com/751952 [ Win ] editing/selection/modify_extend/extend_by_character.html [ Failure Pass ] crbug.com/751952 http/tests/devtools/console/console-uncaught-promise.js [ Pass Failure ] +crbug.com/751952 virtual/binary-for-devtools/http/tests/devtools/console/console-uncaught-promise.js [ Pass Failure ] crbug.com/800898 external/wpt/FileAPI/url/url-with-fetch.any.worker.html [ Pass Failure ] crbug.com/800898 external/wpt/FileAPI/url/url-with-xhr.any.worker.html [ Pass Failure ] @@ -3041,6 +3039,12 @@ crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002.html [ Failure ] +crbug.com/626703 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Timeout ] +crbug.com/626703 external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001.html [ Failure ] +crbug.com/626703 external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003.html [ Failure ] +crbug.com/626703 [ Mac10.13 ] virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm [ Timeout ] +crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Timeout ] crbug.com/626703 external/wpt/css/css-text/shaping/shaping-021.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/shaping/shaping-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/shaping/shaping_cchar-000.html [ Failure ] @@ -3164,7 +3168,6 @@ crbug.com/626703 external/wpt/css/css-values/ic-unit-008.html [ Failure ] crbug.com/626703 external/wpt/css/css-values/ic-unit-012.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/document-metadata/the-link-element/stylesheet-not-removed-until-next-stylesheet-loads.html [ Timeout ] -crbug.com/626703 external/wpt/infrastructure/reftest/size.html [ Failure ] crbug.com/626703 external/wpt/svg/interact/manual/event-attribute-001-manual.svg [ Skip ] crbug.com/626703 [ Retina ] virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm [ Timeout ] crbug.com/626703 external/wpt/css/css-text/tab-size/tab-size-spacing-001.html [ Failure ] @@ -3580,7 +3583,6 @@ crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-002.tentative.html [ Failure ] crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-001.tentative.html [ Failure ] crbug.com/626703 external/wpt/screen-orientation/orientation-reading.html [ Timeout ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/float-retry-push-image.html [ Failure ] crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_top [ Timeout ] crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Failure ] @@ -4297,7 +4299,6 @@ crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-04.html [ Failure ] crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-horiz-04.html [ Failure ] crbug.com/926253 [ Linux Debug ] fast/css-grid-layout/grid-self-baseline-04.html [ Failure ] -crbug.com/926253 fast/css-intrinsic-dimensions/height-css-tables-collapsed.html [ Failure ] crbug.com/926253 [ Linux Debug ] fast/css-intrinsic-dimensions/height-css-tables.html [ Failure ] ### Flakes found on all platforms. See crbug.com/936095 ### crbug.com/926253 [ Linux Debug ] fast/css-intrinsic-dimensions/height-tables-collapsed.html [ Failure ] @@ -4331,6 +4332,7 @@ crbug.com/657646 [ Win ] fast/text/font-features/caps-native-synthesis.html [ Failure Pass ] crbug.com/664450 http/tests/devtools/console/console-on-animation-worklet.js [ Skip ] +crbug.com/664450 virtual/binary-for-devtools/http/tests/devtools/console/console-on-animation-worklet.js [ Skip ] crbug.com/826419 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html [ Skip ] @@ -4409,6 +4411,7 @@ crbug.com/688670 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html [ Pass Failure ] crbug.com/849670 http/tests/devtools/service-workers/service-worker-v8-cache.js [ Pass Timeout ] +crbug.com/849670 virtual/binary-for-devtools/http/tests/devtools/service-workers/service-worker-v8-cache.js [ Pass Timeout ] crbug.com/664858 virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html [ Skip ] crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Skip ] @@ -4450,6 +4453,7 @@ # ====== Tests from enabling .any.js/.worker.js tests end here ======== crbug.com/789139 http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Failure Pass Timeout Crash ] +crbug.com/789139 virtual/binary-for-devtools/http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Failure Pass Timeout Crash ] # ====== Begin of display: contents tests ====== @@ -4476,6 +4480,7 @@ crbug.com/678499 virtual/feature-policy-for-sandbox/http/tests/security/contentSecurityPolicy/require-sri-for/require-sri-for-script-preload-allowed.php [ Failure Pass ] crbug.com/747751 [ Win ] http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Failure Pass ] +crbug.com/747751 [ Win ] virtual/binary-for-devtools/http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Failure Pass ] crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ] crbug.com/689781 [ Win Mac ] http/tests/media/media-source/mediasource-duration.html [ Failure Pass ] @@ -4490,9 +4495,13 @@ # Arrow function name inferring crbug.com/916975 http/tests/devtools/console/console-repeat-count.js [ Pass Failure ] +crbug.com/916975 virtual/binary-for-devtools/http/tests/devtools/console/console-repeat-count.js [ Pass Failure ] crbug.com/916975 http/tests/devtools/service-workers/lazy-addeventlisteners.js [ Pass Failure ] +crbug.com/916975 virtual/binary-for-devtools/http/tests/devtools/service-workers/lazy-addeventlisteners.js [ Pass Failure ] crbug.com/916975 http/tests/devtools/sources/debugger-ui/call-stack-show-more.js [ Pass Failure ] +crbug.com/916975 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-ui/call-stack-show-more.js [ Pass Failure ] crbug.com/916975 http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Failure ] +crbug.com/916975 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Failure ] crbug.com/916975 inspector-protocol/css/media-query-listener-exception.js [ Pass Failure ] crbug.com/916975 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Failure ] @@ -4546,6 +4555,7 @@ # Sheriff failures 2017-03-21 crbug.com/703518 http/tests/devtools/tracing/worker-js-frames.js [ Failure Pass ] +crbug.com/703518 virtual/binary-for-devtools/http/tests/devtools/tracing/worker-js-frames.js [ Failure Pass ] crbug.com/703518 virtual/threaded/http/tests/devtools/tracing/worker-js-frames.js [ Failure Pass ] crbug.com/674720 http/tests/loading/preload-img-test.html [ Pass Failure ] @@ -4730,9 +4740,13 @@ crbug.com/757165 [ Win ] fast/spatial-navigation/snav-unit-overflow-and-scroll-in-direction.html [ Pass Failure Timeout Crash ] crbug.com/757165 [ Win ] fast/spatial-navigation/snav-z-index.html [ Pass Failure Timeout Crash ] crbug.com/757165 [ Win ] http/tests/devtools/console/console-filter-test.js [ Skip ] +crbug.com/757165 [ Win ] virtual/binary-for-devtools/http/tests/devtools/console/console-filter-test.js [ Skip ] crbug.com/757165 [ Win ] http/tests/devtools/console/console-links-in-errors-with-trace.js [ Skip ] +crbug.com/757165 [ Win ] virtual/binary-for-devtools/http/tests/devtools/console/console-links-in-errors-with-trace.js [ Skip ] crbug.com/757165 [ Win ] http/tests/devtools/extensions/extensions-panel.js [ Skip ] +crbug.com/757165 [ Win ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-panel.js [ Skip ] crbug.com/757165 [ Win ] http/tests/devtools/sources/ui-source-code-metadata.js [ Skip ] +crbug.com/757165 [ Win ] virtual/binary-for-devtools/http/tests/devtools/sources/ui-source-code-metadata.js [ Skip ] crbug.com/757165 [ Win ] http/tests/misc/client-hints-accept-meta-preloader.html [ Skip ] crbug.com/757165 [ Win ] inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js [ Skip ] crbug.com/757165 [ Win ] paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html [ Skip ] @@ -4785,18 +4799,24 @@ # Tests occasionaly timing out (flaky) on WebKit Win7 dbg builder crbug.com/757955 [ Win7 Debug ] http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ] +crbug.com/757955 [ Win7 Debug ] virtual/binary-for-devtools/http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ] crbug.com/757955 [ Win7 Debug ] storage/indexeddb/mozilla/cursors.html [ Pass Timeout ] crbug.com/757955 [ Win7 Debug ] storage/indexeddb/objectstore-cursor.html [ Pass Timeout ] crbug.com/757955 http/tests/devtools/tracing/timeline-paint/layer-tree.js [ Pass Failure Timeout ] +crbug.com/757955 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-paint/layer-tree.js [ Pass Failure Timeout ] # This test has a fixed number of time which can depend on performance. crbug.com/669329 http/tests/devtools/tracing/timeline-js/timeline-runtime-stats.js [ Pass Failure Crash ] +crbug.com/669329 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-js/timeline-runtime-stats.js [ Pass Failure Crash ] crbug.com/669329 virtual/threaded/http/tests/devtools/tracing/timeline-js/timeline-runtime-stats.js [ Pass Failure Crash ] crbug.com/799619 [ Debug ] http/tests/devtools/profiler/heap-snapshot-inspect-dom-wrapper.js [ Pass Timeout ] +crbug.com/799619 [ Debug ] virtual/binary-for-devtools/http/tests/devtools/profiler/heap-snapshot-inspect-dom-wrapper.js [ Pass Timeout ] crbug.com/939037 [ Win7 ] http/tests/devtools/profiler/heap-snapshot-location.js [ Pass Timeout ] +crbug.com/939037 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/profiler/heap-snapshot-location.js [ Pass Timeout ] crbug.com/939037 [ Mac Linux ] http/tests/devtools/profiler/heap-snapshot-location.js [ Pass Timeout ] +crbug.com/939037 [ Mac Linux ] virtual/binary-for-devtools/http/tests/devtools/profiler/heap-snapshot-location.js [ Pass Timeout ] crbug.com/769347 [ Mac ] fast/dom/inert/inert-node-is-uneditable.html [ Failure ] @@ -4876,8 +4896,10 @@ # Sheriff failures 2017-10-23 crbug.com/772411 http/tests/media/autoplay-crossorigin.html [ Timeout Failure Pass ] crbug.com/777222 http/tests/devtools/inspect-iframe-from-different-domain.js [ Pass Failure Timeout ] +crbug.com/777222 virtual/binary-for-devtools/http/tests/devtools/inspect-iframe-from-different-domain.js [ Pass Failure Timeout ] crbug.com/778745 http/tests/inspector-protocol/cachestorage/read-cached-response.js [ Pass Failure ] +crbug.com/778745 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/cachestorage/read-cached-response.js [ Pass Failure ] # Sheriff failures 2017-10-24 crbug.com/773122 crbug.com/777813 [ Win ] fast/text/font-ascent-mac.html [ Failure Pass ] @@ -4906,12 +4928,15 @@ # Sheriff failures 2017-11-15 crbug.com/785179 [ Win7 Debug ] http/tests/devtools/console/console-viewport-stick-to-bottom.js [ Skip ] +crbug.com/785179 [ Win7 Debug ] virtual/binary-for-devtools/http/tests/devtools/console/console-viewport-stick-to-bottom.js [ Skip ] # Sheriff failures 2017-11-16 crbug.com/785980 [ Win ] http/tests/devtools/network/network-xhr-same-url-as-main-resource.js [ Failure Pass ] +crbug.com/785980 [ Win ] virtual/binary-for-devtools/http/tests/devtools/network/network-xhr-same-url-as-main-resource.js [ Failure Pass ] # Sheriff failures 2017-11-28 crbug.com/785179 [ Mac10.11 Debug ] http/tests/devtools/console/console-viewport-stick-to-bottom.js [ Pass Failure ] +crbug.com/785179 [ Mac10.11 Debug ] virtual/binary-for-devtools/http/tests/devtools/console/console-viewport-stick-to-bottom.js [ Pass Failure ] # Sheriff failures 2017-11-29 crbug.com/789567 scrollbars/custom-scrollbar-inactive-pseudo.html [ Failure Pass ] @@ -4926,6 +4951,7 @@ # Sheriff failures 2017-12-04 crbug.com/667560 http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Pass Failure ] +crbug.com/667560 virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Pass Failure ] # Double tap on modern media controls is a bit more complicated on Mac but # since we are not targeting Mac yet we can come back and fix this later. @@ -4970,7 +4996,9 @@ # Sheriff failures 2018-01-02 crbug.com/798592 [ Win7 ] http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] +crbug.com/798592 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] crbug.com/798592 [ Mac ] http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] +crbug.com/798592 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] crbug.com/798592 [ Win7 ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] crbug.com/798592 [ Mac ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-recalculate-styles.js [ Pass Failure ] @@ -5040,9 +5068,12 @@ crbug.com/813704 http/tests/images/png-partial-load-as-document.html [ Failure Pass ] crbug.com/806645 [ Win7 ] http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] +crbug.com/806645 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] crbug.com/806645 [ Mac ] http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] +crbug.com/806645 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] crbug.com/813216 [ Win7 ] http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.js [ Failure Pass ] +crbug.com/813216 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.js [ Failure Pass ] # MHT works only when loaded from local FS (file://..). crbug.com/778467 [ Fuchsia ] mhtml/mhtml_in_iframe.html [ Failure ] @@ -5056,9 +5087,11 @@ ### See crbug.com/891427 comment near the top of this file: ###crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ] crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ] +crbug.com/817167 virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ] # Sheriff 2018-03-02 crbug.com/818076 http/tests/devtools/oopif/oopif-elements-navigate-in.js [ Failure Pass ] +crbug.com/818076 virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-elements-navigate-in.js [ Failure Pass ] crbug.com/818154 [ Linux Debug ] virtual/gpu-rasterization/images/gif-loop-count.html [ Failure Pass ] # Sheriff 2018-03-05 @@ -5066,7 +5099,9 @@ # Prefetching Signed Exchange DevTools tests are flaky. crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass Failure ] +crbug.com/851363 virtual/binary-for-devtools/http/tests/devtools/sxg/sxg-prefetch-fail.js [ Pass Failure ] crbug.com/851363 http/tests/devtools/sxg/sxg-prefetch.js [ Pass Failure ] +crbug.com/851363 virtual/binary-for-devtools/http/tests/devtools/sxg/sxg-prefetch.js [ Pass Failure ] # Sheriff 2018-03-22 crbug.com/824775 [ Win ] media/controls/video-controls-with-cast-rendering.html [ Pass Failure ] @@ -5131,6 +5166,7 @@ crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ] crbug.com/831685 [ Linux ] external/wpt/2dcontext/compositing/2d.composite.canvas.lighter.html [ Pass Timeout ] crbug.com/831673 http/tests/devtools/reveal-objects.js [ Pass Timeout ] +crbug.com/831673 virtual/binary-for-devtools/http/tests/devtools/reveal-objects.js [ Pass Timeout ] crbug.com/831496 virtual/gpu/fast/canvas/fillrect_gradient.html [ Pass Timeout ] crbug.com/831482 [ Linux ] virtual/gpu-rasterization/images/cross-fade-background-size.html [ Pass Timeout ] crbug.com/831249 [ Linux ] virtual/gpu/fast/canvas/canvas-filter-svg-inline.html [ Pass Timeout ] @@ -5166,27 +5202,35 @@ # Sheriff 2018-05-22 crbug.com/845610 [ Win ] http/tests/inspector-protocol/target/target-browser-context.js [ Pass Failure ] +crbug.com/845610 [ Win ] virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/target/target-browser-context.js [ Pass Failure ] # Sheriff 2018-05-25 crbug.com/846547 fast/webgl/webgl-composite-modes.html [ Pass Failure ] crbug.com/846471 http/tests/devtools/coverage/reveal-autoformat.js [ Pass Timeout ] +crbug.com/846471 virtual/binary-for-devtools/http/tests/devtools/coverage/reveal-autoformat.js [ Pass Timeout ] crbug.com/846656 external/wpt/css/selectors/focus-visible-002-manual.html [ Pass Timeout ] # Sheriff 2018-05-28 # Merged failing devtools/editor tests. crbug.com/749738 http/tests/devtools/editor/text-editor-word-jumps.js [ Timeout Pass ] +crbug.com/749738 virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-word-jumps.js [ Timeout Pass ] crbug.com/846997 http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Timeout Pass ] +crbug.com/846997 virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-ctrl-d-1.js [ Timeout Pass ] crbug.com/849284 [ Mac ] http/tests/devtools/editor/text-editor-ctrl-d-2.js [ Timeout Pass ] +crbug.com/849284 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-ctrl-d-2.js [ Timeout Pass ] crbug.com/846982 http/tests/devtools/editor/text-editor-formatter.js [ Timeout Pass ] +crbug.com/846982 virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-formatter.js [ Timeout Pass ] crbug.com/846981 fast/webgl/texImage-imageBitmap-from-imageData-resize.html [ Pass Timeout ] ### See crbug.com/891427 comment near the top of this file: ###crbug.com/847114 [ Linux ] http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] +###crbug.com/847114 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] ###crbug.com/847114 [ Linux ] virtual/threaded/http/tests/devtools/tracing/decode-resize.js [ Pass Failure ] crbug.com/843135 virtual/gpu/fast/canvas/canvas-arc-circumference-fill.html [ Pass Failure ] # Sheriff 2018-05-31 crbug.com/848398 http/tests/devtools/oopif/oopif-performance-cpu-profiles.js [ Pass Timeout Failure ] +crbug.com/848398 virtual/binary-for-devtools/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js [ Pass Timeout Failure ] # Sheriff 2018-06-01 crbug.com/848851 virtual/exotic-color-space/images/image-hover-display-alt.html [ Failure Pass ] @@ -5211,7 +5255,9 @@ # Sheriff 2018-06-07 crbug.com/850395 virtual/gpu/fast/canvas/canvas-filter-stroke-paint-pattern.html [ Pass Failure ] crbug.com/850358 http/tests/devtools/editor/text-editor-enter-behaviour.js [ Pass Failure Timeout ] +crbug.com/850358 virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-enter-behaviour.js [ Pass Failure Timeout ] crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass Failure Timeout ] +crbug.com/849978 virtual/binary-for-devtools/http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass Failure Timeout ] # Sheriff 2018-06-08 crbug.com/850170 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass Crash Timeout ] @@ -5220,6 +5266,7 @@ # Sheriff 2018-06-11 crbug.com/850202 [ Linux ] http/tests/devtools/network/network-filters.js [ Pass Failure Timeout ] +crbug.com/850202 [ Linux ] virtual/binary-for-devtools/http/tests/devtools/network/network-filters.js [ Pass Failure Timeout ] crbug.com/853360 [ Mac ] fast/css/input-search-padding.html [ Failure ] crbug.com/853360 [ Mac ] fast/forms/calendar-picker/calendar-picker-appearance-ar.html [ Failure ] @@ -5269,6 +5316,7 @@ # Sheriff 2018-06-29 crbug.com/859169 [ Linux Debug ] http/tests/devtools/layers/layer-scroll-rects-get.js [ Failure Pass ] +crbug.com/859169 [ Linux Debug ] virtual/binary-for-devtools/http/tests/devtools/layers/layer-scroll-rects-get.js [ Failure Pass ] # User Activation crbug.com/736415 external/wpt/html/user-activation/activation-api-iframe.tenative.html [ Failure ] @@ -5311,7 +5359,9 @@ crbug.com/867376 [ Linux ] css3/filters/filter-repaint-composited-fallback-crash.html [ Timeout Pass ] crbug.com/867376 [ Mac ] external/wpt/encoding/textdecoder-fatal-single-byte.any.html [ Timeout Pass ] crbug.com/867376 [ Mac ] http/tests/devtools/elements/elements-inspect-iframe-from-different-domain.js [ Timeout Pass ] +crbug.com/867376 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/elements/elements-inspect-iframe-from-different-domain.js [ Timeout Pass ] crbug.com/867376 [ Mac ] http/tests/devtools/elements/css-variables/resolve-inherited-css-variables.js [ Timeout Pass ] +crbug.com/867376 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/elements/css-variables/resolve-inherited-css-variables.js [ Timeout Pass ] crbug.com/867376 [ Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-color.html [ Timeout Pass ] crbug.com/867376 [ Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Timeout Pass ] crbug.com/867376 [ Linux ] virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Timeout Pass ] @@ -5444,6 +5494,7 @@ crbug.com/869364 css3/filters/filter-repaint-composited-fallback.html [ Pass Timeout ] crbug.com/869364 external/wpt/IndexedDB/parallel-cursors-upgrade.html [ Pass Timeout ] crbug.com/869364 http/tests/devtools/console/console-correct-suggestions.js [ Pass Timeout ] +crbug.com/869364 virtual/binary-for-devtools/http/tests/devtools/console/console-correct-suggestions.js [ Pass Timeout ] crbug.com/869364 virtual/gpu/fast/canvas/OffscreenCanvas-filter.html [ Pass Timeout ] # Sheriff 2018-08-01 @@ -5479,6 +5530,7 @@ # Test frequently times out on Mac CQ bots. crbug.com/874703 [ Mac ] http/tests/devtools/extensions/extensions-panel.js [ Timeout Pass ] +crbug.com/874703 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-panel.js [ Timeout Pass ] # Wake Lock api test timeouts crbug.com/872530 external/wpt/wake-lock/wakelock-applicability-manual.https.html [ Pass Timeout ] @@ -5587,6 +5639,7 @@ # Sheriff 2018-09-25 crbug.com/888609 [ Mac ] http/tests/devtools/coverage/gutter-css.js [ Pass Timeout ] +crbug.com/888609 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/coverage/gutter-css.js [ Pass Timeout ] # Sheriff 2018-10-03 crbug.com/891530 [ Linux ] virtual/android/rootscroller/remove-rootscroller-crash.html [ Pass Timeout ] @@ -5648,7 +5701,9 @@ # Sheriff 2018-10-31 crbug.com/900326 [ Win7 ] http/tests/devtools/network/preview-searchable.js [ Timeout Pass ] +crbug.com/900326 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/network/preview-searchable.js [ Timeout Pass ] crbug.com/900326 [ Mac10.12 ] http/tests/devtools/network/preview-searchable.js [ Timeout Pass ] +crbug.com/900326 [ Mac10.12 ] virtual/binary-for-devtools/http/tests/devtools/network/preview-searchable.js [ Timeout Pass ] crbug.com/874695 crbug.com/900641 crbug.com/913865 [ Linux Mac ] compositing/transitions/transform-on-large-layer.html [ Timeout Pass Crash ] crbug.com/900730 [ Mac ] rootscroller/gesture-scroll-document-not-root-scroller.html [ Pass Failure Timeout Crash ] @@ -5683,6 +5738,7 @@ # See also crbug.com/907150 crbug.com/667560 http/tests/devtools/console-cross-origin-iframe-logging.js [ Pass Failure Timeout ] +crbug.com/667560 virtual/binary-for-devtools/http/tests/devtools/console-cross-origin-iframe-logging.js [ Pass Failure Timeout ] crbug.com/907412 [ Mac10.13 ] external/wpt/domxpath/xml_xpath_runner.html [ Pass Timeout ] #Sheriff 2018-11-22 @@ -5706,11 +5762,13 @@ # Sheriff 2018-12-06 crbug.com/912793 http/tests/devtools/sources/debugger-breakpoints/restore-locations-for-breakpoint-with-broken-source-map.js [ Pass Failure ] +crbug.com/912793 virtual/binary-for-devtools/http/tests/devtools/sources/debugger-breakpoints/restore-locations-for-breakpoint-with-broken-source-map.js [ Pass Failure ] crbug.com/912793 virtual/android/fullscreen/full-screen-iframe-allowed-video.html [ Pass Failure ] # Sheriff 2018-12-07 crbug.com/912821 [ Mac ] virtual/threaded/http/tests/devtools/tracing/user-timing.js [ Pass Failure ] crbug.com/912821 [ Mac ] http/tests/devtools/tracing/user-timing.js [ Pass Failure ] +crbug.com/912821 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/tracing/user-timing.js [ Pass Failure ] crbug.com/913173 fast/backgrounds/background-svg-scaling-zoom.html [ Failure Pass ] @@ -5826,9 +5884,13 @@ crbug.com/922951 fast/text/international/inline-plaintext-relayout-with-leading-neutrals.html [ Skip ] crbug.com/922951 http/tests/cache/subresource-fragment-identifier.html [ Skip ] crbug.com/922951 http/tests/devtools/audits2/audits2-successful-run.js [ Skip ] +crbug.com/922951 virtual/binary-for-devtools/http/tests/devtools/audits2/audits2-successful-run.js [ Skip ] crbug.com/922951 http/tests/devtools/tracing-session-id.js [ Skip ] +crbug.com/922951 virtual/binary-for-devtools/http/tests/devtools/tracing-session-id.js [ Skip ] crbug.com/922951 http/tests/devtools/tracing/console-timeline.js [ Skip ] +crbug.com/922951 virtual/binary-for-devtools/http/tests/devtools/tracing/console-timeline.js [ Skip ] crbug.com/922951 http/tests/devtools/tracing/timeline-network-received-data.js [ Skip ] +crbug.com/922951 virtual/binary-for-devtools/http/tests/devtools/tracing/timeline-network-received-data.js [ Skip ] crbug.com/922951 http/tests/history/back-to-post.html [ Skip ] crbug.com/922951 http/tests/images/feature-policy-unoptimized-images-cached-image.html [ Skip ] crbug.com/922951 http/tests/security/offscreencanvas-placeholder-read-blocked-no-crossorigin.html [ Skip ] @@ -5960,13 +6022,16 @@ # These started failing when network service was enabled by default. crbug.com/933880 external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/interception-take-stream.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/interception-take-stream.js [ Failure ] crbug.com/933880 http/tests/inspector-protocol/network/xhr-interception-auth-fail.js [ Failure ] +crbug.com/933880 virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/xhr-interception-auth-fail.js [ Failure ] # This passes in content_shell but not in chrome with network service disabled, # because content_shell does not add the about: handler. With network service # enabled this fails in both content_shell and chrome. crbug.com/933880 http/tests/misc/redirect-to-about-blank.html [ Failure Timeout ] crbug.com/933880 [ Win ] external/wpt/kv-storage/key-types.https.html [ Timeout ] crbug.com/849284 [ Win ] http/tests/devtools/editor/text-editor-ctrl-d-2.js [ Failure Timeout ] +crbug.com/849284 [ Win ] virtual/binary-for-devtools/http/tests/devtools/editor/text-editor-ctrl-d-2.js [ Failure Timeout ] crbug.com/849284 [ Win ] virtual/outofblink-cors/http/tests/fetch/serviceworker-proxied/thorough/redirect.html [ Timeout ] # Sheriff 2019-02-21 @@ -5977,9 +6042,11 @@ crbug.com/934636 virtual/feature-policy-for-sandbox/http/tests/security/cross-origin-indexeddb-allowed.html [ Crash Pass ] crbug.com/934636 virtual/outofblink-cors/http/tests/security/cross-origin-indexeddb-allowed.html [ Crash Pass ] crbug.com/934768 [ Mac ] http/tests/devtools/tracing/worker-events.js [ Failure Pass ] +crbug.com/934768 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/tracing/worker-events.js [ Failure Pass ] crbug.com/934768 [ Mac ] virtual/threaded/http/tests/devtools/tracing/worker-events.js [ Failure Pass ] crbug.com/934818 [ Mac Debug ] virtual/threaded/http/tests/devtools/tracing/decode-resize.js [ Failure Pass ] crbug.com/935027 http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Crash Pass ] +crbug.com/935027 virtual/binary-for-devtools/http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Crash Pass ] # Sheriff 2019-02-25 crbug.com/935587 [ Mac ] virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure Pass ] @@ -5992,8 +6059,6 @@ crbug.com/935690 virtual/video-surface-layer/media/video-played-ranges-1.html [ Failure ] # Sheriff 2019-02-26 -crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-alphabetic-invalid.html [ Failure ] -crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-cyclic-invalid.html [ Failure ] crbug.com/936083 external/wpt/import-maps/builtin-import-scheme.tentative.html [ Failure Pass ] crbug.com/936095 fast/css-intrinsic-dimensions/height-tables-collapsed.html [ Failure Pass ] crbug.com/934818 [ Linux ] virtual/threaded/http/tests/devtools/tracing/decode-resize.js [ Failure Pass ] @@ -6004,6 +6069,7 @@ # Sheriff 2019-02-27 crbug.com/936279 external/wpt/import-maps/fallback-disallowed.sub.tentative.html [ Failure Pass Timeout ] crbug.com/936479 [ Mac10.13 ] http/tests/devtools/sources/debugger/async-callstack-fetch.js [ Failure Crash Pass ] +crbug.com/936479 [ Mac10.13 ] virtual/binary-for-devtools/http/tests/devtools/sources/debugger/async-callstack-fetch.js [ Failure Crash Pass ] crbug.com/936615 [ Win7 ] external/wpt/kv-storage/values.https.html [ Timeout Pass ] # Device Sensor Events were restricted to secure browsing contexts in M74, with a flag available until M76 to undo the change in case of an emergency. @@ -6033,30 +6099,40 @@ crbug.com/937170 [ Linux Win7 ] external/wpt/IndexedDB/interleaved-cursors-large.html [ Pass Timeout Crash ] crbug.com/937312 [ Win7 ] external/wpt/background-fetch/fetch.https.window.html [ Pass Timeout ] crbug.com/937378 [ Win7 ] http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js [ Pass Timeout ] +crbug.com/937378 [ Win7 ] virtual/binary-for-devtools/http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js [ Pass Timeout ] crbug.com/864994 [ Linux Win7 ] external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Timeout Failure Pass ] crbug.com/937416 [ Linux Mac ] http/tests/devtools/resource-tree/resource-tree-htmlimports.js [ Pass Failure ] +crbug.com/937416 [ Linux Mac ] virtual/binary-for-devtools/http/tests/devtools/resource-tree/resource-tree-htmlimports.js [ Pass Failure ] crbug.com/937416 http/tests/devtools/resource-tree/resource-tree-frame-navigate.js [ Pass Failure ] +crbug.com/937416 virtual/binary-for-devtools/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js [ Pass Failure ] crbug.com/937546 [ Win7 ] http/tests/security/xss-DENIED-cross-origin-stack-overflow.html [ Pass Timeout ] # Sheriff 2019-03-02 crbug.com/937639 [ Linux Debug ] external/wpt/html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html [ Pass Failure ] # Sheriff 2019-03-04 crbug.com/937811 [ Linux Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] +crbug.com/937811 [ Linux Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] crbug.com/937811 [ Linux Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] +crbug.com/937811 [ Linux Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] +crbug.com/937811 [ Win Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] +crbug.com/937811 [ Win Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] crbug.com/935689 [ Linux Debug ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ] crbug.com/937858 [ Debug ] external/wpt/ambient-light/AmbientLightSensor.https.html [ Pass Failure ] crbug.com/937902 [ Linux Debug ] virtual/disable-blink-gen-property-trees/compositing/overflow/overflow-scroll-with-local-background.html [ Pass Failure ] crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ] +crbug.com/937991 [ Win7 Release ] virtual/binary-for-devtools/http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ] # Sheriff 2019-03-05 crbug.com/938200 http/tests/devtools/network/network-blocked-reason.js [ Timeout Pass ] +crbug.com/938200 virtual/binary-for-devtools/http/tests/devtools/network/network-blocked-reason.js [ Timeout Pass ] crbug.com/938780 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Failure ] # Sheriff 2019-03-06 crbug.com/938591 [ Linux ] fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Failure Pass ] crbug.com/938884 [ Win7 Mac ] http/tests/devtools/elements/styles-3/styles-add-blank-property.js [ Pass Timeout ] +crbug.com/938884 [ Win7 Mac ] virtual/binary-for-devtools/http/tests/devtools/elements/styles-3/styles-add-blank-property.js [ Pass Timeout ] # Caused a revert of a good change. crbug.com/931533 media/video-played-collapse.html [ Pass Failure ] @@ -6079,3 +6155,4 @@ crbug.com/836242 [ Win ] fast/loader/reload-zero-byte-plugin.html [ Pass Failure ] crbug.com/806357 virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure Crash ] crbug.com/941931 [ Linux Win ] http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed.html [ Pass Failure ] +crbug.com/942134 [ Win ] virtual/exotic-color-space/images/feature-policy-oversized-images.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 3eb6369..97c5dee 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -289,6 +289,16 @@ "args": ["--enable-threaded-compositing"] }, { + "prefix": "binary-for-devtools", + "base": "http/tests/devtools", + "args": ["--enable-internal-devtools-binary-protocol"] + }, + { + "prefix": "binary-for-inspector-protocol", + "base": "http/tests/inspector-protocol", + "args": ["--enable-internal-devtools-binary-protocol"] + }, + { "prefix": "composite-after-paint", "base": "compositing", "args": ["--enable-blink-features=CompositeAfterPaint"]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index 3c5ad49..eb6a3fa4 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -6121,18 +6121,6 @@ {} ] ], - "pointerlock/mouse_buttons_back_forward-manual.html": [ - [ - "/pointerlock/mouse_buttons_back_forward-manual.html", - {} - ] - ], - "pointerlock/movementX_Y_basic-manual.html": [ - [ - "/pointerlock/movementX_Y_basic-manual.html", - {} - ] - ], "pointerlock/movementX_Y_no-jumps-manual.html": [ [ "/pointerlock/movementX_Y_no-jumps-manual.html", @@ -6169,24 +6157,6 @@ {} ] ], - "pointerlock/pointerlock_remove_target-manual.html": [ - [ - "/pointerlock/pointerlock_remove_target-manual.html", - {} - ] - ], - "pointerlock/pointerlock_remove_target_on_mouseup-manual.html": [ - [ - "/pointerlock/pointerlock_remove_target_on_mouseup-manual.html", - {} - ] - ], - "pointerlock/pointerlock_shadow-manual.html": [ - [ - "/pointerlock/pointerlock_shadow-manual.html", - {} - ] - ], "presentation-api/controlling-ua/PresentationAvailability_onchange-manual.https.html": [ [ "/presentation-api/controlling-ua/PresentationAvailability_onchange-manual.https.html", @@ -6939,6 +6909,18 @@ {} ] ], + "animation-worklet/worklet-animation-cancel.https.html": [ + [ + "/animation-worklet/worklet-animation-cancel.https.html", + [ + [ + "/animation-worklet/worklet-animation-cancel-ref.html", + "==" + ] + ], + {} + ] + ], "animation-worklet/worklet-animation-local-time-after-duration.https.html": [ [ "/animation-worklet/worklet-animation-local-time-after-duration.https.html", @@ -7011,6 +6993,18 @@ {} ] ], + "animation-worklet/worklet-animation-start-delay.https.html": [ + [ + "/animation-worklet/worklet-animation-start-delay.https.html", + [ + [ + "/animation-worklet/worklet-animation-start-delay-ref.html", + "==" + ] + ], + {} + ] + ], "animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html": [ [ "/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html", @@ -48291,6 +48285,54 @@ {} ] ], + "css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html": [ + [ + "/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html", + [ + [ + "/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-001.html": [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-001.html", + [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-002.html": [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-002.html", + [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-003.html": [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-003.html", + [ + [ + "/css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-grid/grid-items/grid-items-001.html": [ [ "/css/css-grid/grid-items/grid-items-001.html", @@ -64047,6 +64089,18 @@ {} ] ], + "css/css-text/overflow-wrap/overflow-wrap-break-word-007.html": [ + [ + "/css/css-text/overflow-wrap/overflow-wrap-break-word-007.html", + [ + [ + "/css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [ [ "/css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html", @@ -67155,6 +67209,18 @@ {} ] ], + "css/css-text/white-space/pre-wrap-008.html": [ + [ + "/css/css-text/white-space/pre-wrap-008.html", + [ + [ + "/css/css-text/white-space/reference/white-space-break-spaces-005-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/white-space/pre-wrap-011.html": [ [ "/css/css-text/white-space/pre-wrap-011.html", @@ -67835,6 +67901,18 @@ {} ] ], + "css/css-text/word-break/word-break-break-all-015.html": [ + [ + "/css/css-text/word-break/word-break-break-all-015.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/word-break/word-break-break-all-020.html": [ [ "/css/css-text/word-break/word-break-break-all-020.html", @@ -74595,6 +74673,18 @@ {} ] ], + "css/css-transforms/transform-flattening-001.html": [ + [ + "/css/css-transforms/transform-flattening-001.html", + [ + [ + "about:blank", + "!=" + ] + ], + {} + ] + ], "css/css-transforms/transform-generated-001.html": [ [ "/css/css-transforms/transform-generated-001.html", @@ -118032,6 +118122,16 @@ {} ] ], + "animation-worklet/worklet-animation-cancel-ref.html": [ + [ + {} + ] + ], + "animation-worklet/worklet-animation-duration-ref.html": [ + [ + {} + ] + ], "animation-worklet/worklet-animation-local-time-after-duration-ref.html": [ [ {} @@ -118052,6 +118152,11 @@ {} ] ], + "animation-worklet/worklet-animation-start-delay-ref.html": [ + [ + {} + ] + ], "animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden-ref.html": [ [ {} @@ -140207,6 +140312,26 @@ {} ] ], + "css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html": [ + [ + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html": [ + [ + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html": [ + [ + {} + ] + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html": [ + [ + {} + ] + ], "css/css-grid/grid-items/grid-items-sizing-alignment-001-ref.html": [ [ {} @@ -161982,6 +162107,21 @@ {} ] ], + "feature-policy/resources/feature-policy-idle-detection-worker.html": [ + [ + {} + ] + ], + "feature-policy/resources/feature-policy-idle-detection-worker.js": [ + [ + {} + ] + ], + "feature-policy/resources/feature-policy-idle-detection.html": [ + [ + {} + ] + ], "feature-policy/resources/feature-policy-nested-subframe-policy.https.sub.html": [ [ {} @@ -173197,26 +173337,6 @@ {} ] ], - "html/semantics/forms/form-submission-target/rel-base-target-expected.txt": [ - [ - {} - ] - ], - "html/semantics/forms/form-submission-target/rel-button-target-expected.txt": [ - [ - {} - ] - ], - "html/semantics/forms/form-submission-target/rel-form-target-expected.txt": [ - [ - {} - ] - ], - "html/semantics/forms/form-submission-target/rel-input-target-expected.txt": [ - [ - {} - ] - ], "html/semantics/forms/form-submission-target/resources/endpoint.html": [ [ {} @@ -175817,6 +175937,16 @@ {} ] ], + "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html.headers": [ + [ + {} + ] + ], + "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html.headers": [ + [ + {} + ] + ], "idle-detection/idle-detection.idl": [ [ {} @@ -175827,6 +175957,16 @@ {} ] ], + "idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js": [ + [ + {} + ] + ], + "idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js": [ + [ + {} + ] + ], "imagebitmap-renderingcontext/META.yml": [ [ {} @@ -180622,6 +180762,11 @@ {} ] ], + "portals/resources/portal-activate-data-portal.html": [ + [ + {} + ] + ], "portals/resources/portal-activate-event-portal.html": [ [ {} @@ -184182,6 +184327,41 @@ {} ] ], + "resource-timing/resources/document-navigated.html": [ + [ + {} + ] + ], + "resource-timing/resources/document-refreshed.html": [ + [ + {} + ] + ], + "resource-timing/resources/document-that-navigates.html": [ + [ + {} + ] + ], + "resource-timing/resources/document-that-refreshes.html": [ + [ + {} + ] + ], + "resource-timing/resources/embed-navigate-back.html": [ + [ + {} + ] + ], + "resource-timing/resources/embed-navigate.html": [ + [ + {} + ] + ], + "resource-timing/resources/embed-refresh.html": [ + [ + {} + ] + ], "resource-timing/resources/empty.js": [ [ {} @@ -184232,6 +184412,26 @@ {} ] ], + "resource-timing/resources/iframe-TAO-crossorigin-port.sub.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe-navigate-back.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe-navigate.html": [ + [ + {} + ] + ], + "resource-timing/resources/iframe-refresh.html": [ + [ + {} + ] + ], "resource-timing/resources/iframe-reload-TAO.sub.html": [ [ {} @@ -184302,6 +184502,16 @@ {} ] ], + "resource-timing/resources/navigate_back.html": [ + [ + {} + ] + ], + "resource-timing/resources/nested-contexts.js": [ + [ + {} + ] + ], "resource-timing/resources/nested.css": [ [ {} @@ -184312,6 +184522,21 @@ {} ] ], + "resource-timing/resources/object-navigate-back.html": [ + [ + {} + ] + ], + "resource-timing/resources/object-navigate.html": [ + [ + {} + ] + ], + "resource-timing/resources/object-refresh.html": [ + [ + {} + ] + ], "resource-timing/resources/resource_timing_test0.css": [ [ {} @@ -184757,6 +184982,11 @@ {} ] ], + "screen-orientation/lock-unlock-check-expected.txt": [ + [ + {} + ] + ], "screen-orientation/onchange-event-expected.txt": [ [ {} @@ -184772,6 +185002,11 @@ {} ] ], + "screen-orientation/resources/orientation-utils.js": [ + [ + {} + ] + ], "screen-orientation/resources/sandboxed-iframe-locking.html": [ [ {} @@ -184892,6 +185127,11 @@ {} ] ], + "selection/Document-open-expected.txt": [ + [ + {} + ] + ], "selection/META.yml": [ [ {} @@ -188112,6 +188352,21 @@ {} ] ], + "signed-exchange/resources/register-sw-after-fallback.html": [ + [ + {} + ] + ], + "signed-exchange/resources/register-sw.html": [ + [ + {} + ] + ], + "signed-exchange/resources/service-worker.js": [ + [ + {} + ] + ], "signed-exchange/resources/sxg-location.html": [ [ {} @@ -188167,6 +188422,16 @@ {} ] ], + "signed-exchange/resources/sxg/register-sw-after-fallback.sxg": [ + [ + {} + ] + ], + "signed-exchange/resources/sxg/register-sw-from-sxg.sxg": [ + [ + {} + ] + ], "signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg": [ [ {} @@ -188287,6 +188552,16 @@ {} ] ], + "signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https-expected.txt": [ + [ + {} + ] + ], + "signed-exchange/service-workers/sxg-sw-register.tentative.https-expected.txt": [ + [ + {} + ] + ], "speech-api/META.yml": [ [ {} @@ -201322,6 +201597,11 @@ {} ] ], + "webxr/resources/webxr_math_utils.js": [ + [ + {} + ] + ], "webxr/resources/webxr_test_asserts.js": [ [ {} @@ -211836,6 +212116,18 @@ {} ] ], + "animation-worklet/worklet-animation-creation.https.html": [ + [ + "/animation-worklet/worklet-animation-creation.https.html", + {} + ] + ], + "animation-worklet/worklet-animation-duration.https.html": [ + [ + "/animation-worklet/worklet-animation-duration.https.html", + {} + ] + ], "animation-worklet/worklet-animation-pause.https.html": [ [ "/animation-worklet/worklet-animation-pause.https.html", @@ -235018,6 +235310,12 @@ {} ] ], + "element-timing/observe-video-poster.html": [ + [ + "/element-timing/observe-video-poster.html", + {} + ] + ], "element-timing/progressively-loaded-image.html": [ [ "/element-timing/progressively-loaded-image.html", @@ -248132,6 +248430,12 @@ {} ] ], + "html/browsers/the-window-object/document-attribute.window.js": [ + [ + "/html/browsers/the-window-object/document-attribute.window.html", + {} + ] + ], "html/browsers/the-window-object/focus.window.js": [ [ "/html/browsers/the-window-object/focus.window.html", @@ -248204,6 +248508,12 @@ {} ] ], + "html/browsers/the-window-object/self-et-al.window.js": [ + [ + "/html/browsers/the-window-object/self-et-al.window.html", + {} + ] + ], "html/browsers/the-window-object/window-aliases.html": [ [ "/html/browsers/the-window-object/window-aliases.html", @@ -259844,6 +260154,36 @@ {} ] ], + "idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ + [ + "/idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html", + {} + ] + ], + "idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html": [ + [ + "/idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html", + {} + ] + ], + "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html": [ + [ + "/idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html", + {} + ] + ], + "idle-detection/idle-detection-default-feature-policy.https.sub.html": [ + [ + "/idle-detection/idle-detection-default-feature-policy.https.sub.html", + {} + ] + ], + "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html": [ + [ + "/idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html", + {} + ] + ], "idle-detection/idlharness.https.any.js": [ [ "/idle-detection/idlharness.https.any.html", @@ -264732,6 +265072,12 @@ {} ] ], + "navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html": [ + [ + "/navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html", + {} + ] + ], "navigation-timing/nav2_test_redirect_none.html": [ [ "/navigation-timing/nav2_test_redirect_none.html", @@ -264774,6 +265120,18 @@ {} ] ], + "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html": [ + [ + "/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html", + {} + ] + ], + "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html": [ + [ + "/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html", + {} + ] + ], "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirects.html": [ [ "/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirects.html", @@ -275574,6 +275932,55 @@ {} ] ], + "pointerlock/mouse_buttons_back_forward.html": [ + [ + "/pointerlock/mouse_buttons_back_forward.html", + { + "testdriver": true + } + ] + ], + "pointerlock/movementX_Y_basic.html": [ + [ + "/pointerlock/movementX_Y_basic.html", + { + "testdriver": true, + "timeout": "long" + } + ] + ], + "pointerlock/pointerlock_remove_target.html": [ + [ + "/pointerlock/pointerlock_remove_target.html", + { + "testdriver": true, + "timeout": "long" + } + ] + ], + "pointerlock/pointerlock_remove_target_on_mouseup.html": [ + [ + "/pointerlock/pointerlock_remove_target_on_mouseup.html", + { + "testdriver": true + } + ] + ], + "pointerlock/pointerlock_shadow.html": [ + [ + "/pointerlock/pointerlock_shadow.html", + { + "testdriver": true, + "timeout": "long" + } + ] + ], + "portals/portal-activate-data.html": [ + [ + "/portals/portal-activate-data.html", + {} + ] + ], "portals/portal-activate-event.html": [ [ "/portals/portal-activate-event.html", @@ -285938,6 +286345,12 @@ {} ] ], + "resource-timing/TAO-crossorigin-port.sub.html": [ + [ + "/resource-timing/TAO-crossorigin-port.sub.html", + {} + ] + ], "resource-timing/buffer-full-add-after-full-event.html": [ [ "/resource-timing/buffer-full-add-after-full-event.html", @@ -286026,6 +286439,14 @@ {} ] ], + "resource-timing/nested-context-navigations.html": [ + [ + "/resource-timing/nested-context-navigations.html", + { + "timeout": "long" + } + ] + ], "resource-timing/no-entries-for-cross-origin-css-fetched.sub.html": [ [ "/resource-timing/no-entries-for-cross-origin-css-fetched.sub.html", @@ -286184,18 +286605,18 @@ {} ] ], - "resource-timing/resource_memory_cached.sub.html": [ - [ - "/resource-timing/resource_memory_cached.sub.html", - {} - ] - ], "resource-timing/resource_reparenting.html": [ [ "/resource-timing/resource_reparenting.html", {} ] ], + "resource-timing/resource_reuse.sub.html": [ + [ + "/resource-timing/resource_reuse.sub.html", + {} + ] + ], "resource-timing/resource_script_types.html": [ [ "/resource-timing/resource_script_types.html", @@ -286338,6 +286759,14 @@ {} ] ], + "screen-orientation/lock-unlock-check.html": [ + [ + "/screen-orientation/lock-unlock-check.html", + { + "testdriver": true + } + ] + ], "screen-orientation/onchange-event-subframe.html": [ [ "/screen-orientation/onchange-event-subframe.html", @@ -289102,6 +289531,18 @@ {} ] ], + "signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html": [ + [ + "/signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html", + {} + ] + ], + "signed-exchange/service-workers/sxg-sw-register.tentative.https.html": [ + [ + "/signed-exchange/service-workers/sxg-sw-register.tentative.https.html", + {} + ] + ], "signed-exchange/sxg-double-prefetch.tentative.html": [ [ "/signed-exchange/sxg-double-prefetch.tentative.html", @@ -300424,6 +300865,12 @@ {} ] ], + "webxr/xrRigidTransform_matrix.https.html": [ + [ + "/webxr/xrRigidTransform_matrix.https.html", + {} + ] + ], "webxr/xrSession_cancelAnimationFrame.https.html": [ [ "/webxr/xrSession_cancelAnimationFrame.https.html", @@ -311222,7 +311669,7 @@ "support" ], "2dcontext/META.yml": [ - "53b11d271cc6181435059f99880a28e0e3f6d5a0", + "0f79f2591292a3b2d82e6d42f22f82368381dc08", "support" ], "2dcontext/OWNERS": [ @@ -318038,7 +318485,7 @@ "support" ], "WebIDL/META.yml": [ - "82ae5236f0d9e000f73fe2be9299c74b81938106", + "a8dc9c4410e949fa78bdbe2268edf3f125934487", "support" ], "WebIDL/OWNERS": [ @@ -318242,7 +318689,7 @@ "manual" ], "accelerometer/META.yml": [ - "6554be89580e7328117fc35880f70cf623ce0ee9", + "7df27e1f40b09a70c9dcee46e9b1e40bbf355595", "support" ], "accelerometer/OWNERS": [ @@ -318990,7 +319437,7 @@ "manual" ], "ambient-light/META.yml": [ - "04fce804971f9050c79960c4f5a344ae1b9fe2bc", + "c3f69ba181e69906ebeb1fe42f1e4255f17c47c5", "support" ], "ambient-light/OWNERS": [ @@ -319069,6 +319516,26 @@ "761e66e7d76f4aaf64c7744d0d04a06e3ba16cd1", "testharness" ], + "animation-worklet/worklet-animation-cancel-ref.html": [ + "d44927374703ef2b38d3ed0c9570609b62baec65", + "support" + ], + "animation-worklet/worklet-animation-cancel.https.html": [ + "3a28c7515db455ba50ed50135c5a5bb8534ae580", + "reftest" + ], + "animation-worklet/worklet-animation-creation.https.html": [ + "3e403feb4366457a800f38030481a7b12f9d24f2", + "testharness" + ], + "animation-worklet/worklet-animation-duration-ref.html": [ + "81b01bdca813caccb4a3b5e635db21d4f9411a63", + "support" + ], + "animation-worklet/worklet-animation-duration.https.html": [ + "1526004eaf17d5e420e3989a91ba49bc61f4b704", + "testharness" + ], "animation-worklet/worklet-animation-local-time-after-duration-ref.html": [ "96acf1ad96c7c41e870429d55142269f4468bb97", "support" @@ -319113,6 +319580,14 @@ "ac3f05f4234ac1036e388536c4237686b07e6037", "reftest" ], + "animation-worklet/worklet-animation-start-delay-ref.html": [ + "efef6f842bf0f9d3ce05e6335a3f48d17e625167", + "support" + ], + "animation-worklet/worklet-animation-start-delay.https.html": [ + "c8683f7daccb40b85c56f098a8061854f4ed293a", + "reftest" + ], "animation-worklet/worklet-animation-with-fill-mode.https.html": [ "725d10de438ce60d1b6eece5109e9016cc3fc9e8", "testharness" @@ -319286,7 +319761,7 @@ "testharness" ], "battery-status/META.yml": [ - "eded36c5e2f2487376caae21cda9cc36a5090168", + "12a2f12c32e9c58912a209e369af59d6ceee3aa4", "support" ], "battery-status/OWNERS": [ @@ -319502,7 +319977,7 @@ "support" ], "bluetooth/META.yml": [ - "501396bac744058ef594b19a935732ba0f277219", + "607edb6365b4cde7dc2c292d31c9c4175c466ea8", "support" ], "bluetooth/OWNERS": [ @@ -320542,7 +321017,7 @@ "support" ], "common/META.yml": [ - "594c8b170f5043a944fdd4de17d4bd65eba242fb", + "958883a1b07e7db13249153fc85c69d2a40363a3", "support" ], "common/PrefixedLocalStorage.js": [ @@ -320698,7 +321173,7 @@ "support" ], "common/sleep.py": [ - "afc0a7c26e1c2aa63a54bcf39d74cf9c7adf6d75", + "2e803b1b262423e219be592fab548ada982bc439", "support" ], "common/slow.py": [ @@ -324038,7 +324513,7 @@ "testharness" ], "cookies/META.yml": [ - "946da8833ac886c2f00488880e3b7a10926efe63", + "d0743949b6a122d8bd0adf7b1ed0181f0c51429d", "support" ], "cookies/OWNERS": [ @@ -326326,7 +326801,7 @@ "support" ], "css/CSS2/META.yml": [ - "4ac0804d36d9c7222097a410c32af89c92475ddb", + "e9bc44dc8fdda34cc1dd23a1600c77adeacfacfb", "support" ], "css/CSS2/OWNERS": [ @@ -341470,7 +341945,7 @@ "support" ], "css/css-backgrounds/META.yml": [ - "d90a6e083b663ed9a6ef67ba4a92ebd723747550", + "d673be5f4f29bf82619aba6f40ed7e287e902582", "support" ], "css/css-backgrounds/OWNERS": [ @@ -345402,7 +345877,7 @@ "support" ], "css/css-color/META.yml": [ - "a8d93c12a945781a88b89874aff7a3b2d72393dd", + "a0e70aa6539e88373bc8615c3f4e1453010e85d5", "support" ], "css/css-color/OWNERS": [ @@ -347842,7 +348317,7 @@ "reftest" ], "css/css-flexbox/META.yml": [ - "764d8cbd16850b81fb885927da8556157b890a55", + "0bcad0b51f759e6ea9a05e2fee919677bc790dd3", "support" ], "css/css-flexbox/OWNERS": [ @@ -358738,7 +359213,7 @@ "reftest" ], "css/css-grid/META.yml": [ - "af20bb4be80fabd4211684420c232293ac0815ad", + "e49946f4f7012e2aefbc2fb01573a2e01a903e55", "support" ], "css/css-grid/OWNERS": [ @@ -360637,6 +361112,38 @@ "f50e9ef312418f4d3b737bd55b4a7e5c75f09230", "testharness" ], + "css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html": [ + "96a3ca1d5032e10e0c4491cc17541084543daab2", + "support" + ], + "css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html": [ + "62273b87e49170853bc14e36ecc3fb7b148ff6ac", + "reftest" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html": [ + "109087157512a0dbd7a20c408a8927a828eafae1", + "support" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-001.html": [ + "97532e495c1fd71adbbbcc12642dcd313848fae7", + "reftest" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html": [ + "568642631b1ddc557cf57e2bb7039919f1ac1152", + "support" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-002.html": [ + "2ceba537f0ccd4366cd4b7e1e691bb2d5f1e5a52", + "reftest" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html": [ + "41070a8f013c0ae4a5094d0c3d32aa1fda834bca", + "support" + ], + "css/css-grid/grid-items/grid-item-percentage-sizes-003.html": [ + "fccf4fe0a6ed1f128ff7ec2b322a4a2916c873b1", + "reftest" + ], "css/css-grid/grid-items/grid-items-001.html": [ "99701de8a365345decc575ee00a6270ec03d6433", "reftest" @@ -362606,7 +363113,7 @@ "support" ], "css/css-logical/META.yml": [ - "98d838c04e110e484cae63998cf4ee6c2dd559ed", + "cf789d631b1f61c6fee66d29fc5984d155180702", "support" ], "css/css-logical/OWNERS": [ @@ -366246,7 +366753,7 @@ "testharness" ], "css/css-position/META.yml": [ - "00eb3b13129df2b90c59ba3f2b22fd9a4f1727e4", + "c1ce1ff602eee4668b9cb5d0168c4372193a8d3a", "support" ], "css/css-position/OWNERS": [ @@ -366930,7 +367437,7 @@ "testharness" ], "css/css-properties-values-api/registered-property-initial.html": [ - "82a012e2f68532761b18428c3eaed9479ec8c7e5", + "d35b14be569f3c74d0b3d04e98fed00ed2f956d5", "testharness" ], "css/css-properties-values-api/resources/utils.js": [ @@ -367790,7 +368297,7 @@ "testharness" ], "css/css-scrollbars/META.yml": [ - "9209d5d1f4174d1e22258c0571db89b51f4f3a59", + "f7c0439e202113c9611405ae967b33c2b12cfcee", "support" ], "css/css-scrollbars/auto-scrollbar-inline-children.html": [ @@ -367942,7 +368449,7 @@ "support" ], "css/css-shapes/META.yml": [ - "99136818e66dc50978bc0f7c25a2129556e72f21", + "2e433aa66f914de66e36f0f4f99237254a7def29", "support" ], "css/css-shapes/OWNERS": [ @@ -369366,7 +369873,7 @@ "reftest" ], "css/css-sizing/range-percent-intrinsic-size-2-ref.html": [ - "83eff4b45c2c1e1b53be64242775e8a6016ffe1c", + "207b60d8f27ad3b1bb2b24a866d5de38807256e6", "support" ], "css/css-sizing/range-percent-intrinsic-size-2.html": [ @@ -369374,7 +369881,7 @@ "reftest" ], "css/css-sizing/range-percent-intrinsic-size-2a-ref.html": [ - "815b0a1021cb9113c39fad85b5052429dc74533f", + "861d34c6a08d21fd9145a9697660646f31eda02d", "support" ], "css/css-sizing/range-percent-intrinsic-size-2a.html": [ @@ -369402,7 +369909,7 @@ "reftest" ], "css/css-style-attr/META.yml": [ - "72438735ccd461ff343a0891348dc5810e41416a", + "067e03cfbc7376daf0e1b5eba0dc1c35e21fe69f", "support" ], "css/css-style-attr/reference/ref-green-on-green.xht": [ @@ -369646,7 +370153,7 @@ "support" ], "css/css-syntax/META.yml": [ - "17489e1bc2132f4c2acbc4ec901eccb8f7e4d365", + "359219c09965b90066e4fb31d952d621d0d0dc5b", "support" ], "css/css-syntax/OWNERS": [ @@ -370886,7 +371393,7 @@ "reftest" ], "css/css-text/META.yml": [ - "042b858557d9e6fc66a12e96724b69a02c314d47", + "e7914c0fc7ff9e6999f8847dc1800968472483f2", "support" ], "css/css-text/OWNERS": [ @@ -373421,6 +373928,10 @@ "6dc1b4dff52459d7f5516da64f4e09be313257d1", "reftest" ], + "css/css-text/overflow-wrap/overflow-wrap-break-word-007.html": [ + "0491b921e1aed4b030ca5cf0214afad7bdf3aba1", + "reftest" + ], "css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [ "2c83c46aa50f6d51efbb4d05635d86f7c166042d", "reftest" @@ -375637,6 +376148,10 @@ "de69880ed43c499974e60eafd3d135b6fb5b6632", "reftest" ], + "css/css-text/white-space/pre-wrap-008.html": [ + "1ddbb7fe356e2cd9af2a35aa848541db2ab8fe23", + "reftest" + ], "css/css-text/white-space/pre-wrap-011.html": [ "5f86cff5b3889ea1a810b30c14d680c4fa7dbcae", "reftest" @@ -376190,21 +376705,25 @@ "reftest" ], "css/css-text/word-break/word-break-break-all-011.html": [ - "fade439dd9a9d4505e3ab7b9060a2f962eb6fd95", + "74ca60503f6eb76678ec6d94c8e7f9a2349cfcd4", "reftest" ], "css/css-text/word-break/word-break-break-all-012.html": [ - "cd3d44056ec9715c0a9599bf5b7cad180620af74", + "6cbcbad92c4483021d645a3ba529a4441c26ba7d", "reftest" ], "css/css-text/word-break/word-break-break-all-013.html": [ - "85dce08b6418088292c50e30dab9f497b31fb6ac", + "5029e4d891b221eca7da7e4991ec0d1809ea4d03", "reftest" ], "css/css-text/word-break/word-break-break-all-014.html": [ "674b0545e05a5d25f056ac9850abd11791de6a58", "reftest" ], + "css/css-text/word-break/word-break-break-all-015.html": [ + "9602a1f2cf0bab45bc7f70dbe3fa0aeb75d6df79", + "reftest" + ], "css/css-text/word-break/word-break-break-all-020.html": [ "ac1840131c3f214b993ffd58dcd2124523f89b6b", "reftest" @@ -376386,7 +376905,7 @@ "reftest_node" ], "css/css-transforms/META.yml": [ - "33c1fce3379cc08c33a5641ea0b88864735dcd0c", + "b948e3a31ed377091417bbf32d02791965b15a92", "support" ], "css/css-transforms/OWNERS": [ @@ -379229,6 +379748,10 @@ "ba46b847a34aa1f7dde3b46c457e7292d4c7a016", "support" ], + "css/css-transforms/transform-flattening-001.html": [ + "85d29779b5aa9f0a4a6ee638aafedeb9fcd204a7", + "reftest" + ], "css/css-transforms/transform-generated-001-notref.html": [ "f0c2792682a4fd0a884552f266fa9269d2836e26", "support" @@ -384306,7 +384829,7 @@ "testharness" ], "css/css-ui/META.yml": [ - "e78564bcc0d50add555e6767a596662e3c303c6e", + "7ce4b54a22c78576dc2318ebd651dfd1cce374ad", "support" ], "css/css-ui/OWNERS": [ @@ -387818,7 +388341,7 @@ "reftest" ], "css/css-writing-modes/META.yml": [ - "c74fff07de51aa354967058536c882ce515be8df", + "c11da73b6b438ca69cc6425f5118a4f9aa36a34f", "support" ], "css/css-writing-modes/OWNERS": [ @@ -396682,7 +397205,7 @@ "support" ], "css/selectors/META.yml": [ - "3f86842591ed35be1b36757e58e900899e8e0627", + "8e506d671d4b1e741d3450bd66603edbb3de9f30", "support" ], "css/selectors/OWNERS": [ @@ -403942,7 +404465,7 @@ "testharness" ], "device-memory/META.yml": [ - "b393c6b8337c09b3a7f140520319e61d3acbf56d", + "b8dd4761adff3e18b6552d4a8f02abdcd30a3ea6", "support" ], "device-memory/OWNERS": [ @@ -406637,6 +407160,10 @@ "f127152cf8693481703e5a38306204232e4a9ce5", "testharness" ], + "element-timing/observe-video-poster.html": [ + "40961382ffba6b828ac551cc046265de7d89eac1", + "testharness" + ], "element-timing/progressively-loaded-image.html": [ "cf54e1e5c7a281bc59ba4172cd8ee3d7efdab099", "testharness" @@ -408018,7 +408545,7 @@ "testharness" ], "encrypted-media/META.yml": [ - "3168f7d96f847daf23d9f859e548cb07b0f1c74c", + "b09e3b3c4e860bb92f1bc434c2f13462085f0af2", "support" ], "encrypted-media/OWNERS": [ @@ -408886,7 +409413,7 @@ "support" ], "event-timing/META.yml": [ - "feede41dcef66e8842a081b6053b4e57515f9c1c", + "aa27fb61c310d91b629ff0d7b19cd01ce469e645", "support" ], "event-timing/event-timing-bufferbeforeonload.html": [ @@ -409278,7 +409805,7 @@ "testharness" ], "feature-policy/META.yml": [ - "44ab62ca7243653c47ae8d887f7b4c9697718c0f", + "a4136f77e3fbd8524939de235eaff9c0211bfdba", "support" ], "feature-policy/OWNERS": [ @@ -410005,6 +410532,18 @@ "59652e2e7ae0056a6cc4be7f004b6d0151fb9d44", "support" ], + "feature-policy/resources/feature-policy-idle-detection-worker.html": [ + "1ef5298abf1b2062f98c8aba5675decd36c5313d", + "support" + ], + "feature-policy/resources/feature-policy-idle-detection-worker.js": [ + "c6b8a7c88729c4106db162a9850b92e74b92d6ed", + "support" + ], + "feature-policy/resources/feature-policy-idle-detection.html": [ + "e542e3b8912228e87bf6265bbab803dfe2756b1e", + "support" + ], "feature-policy/resources/feature-policy-nested-subframe-policy.https.sub.html": [ "3d9530c26f668a0ca37464b052e5940a79b1197c", "support" @@ -412774,7 +413313,7 @@ "support" ], "gamepad/META.yml": [ - "5f99b9db8eb163c24bf9a330039a8a7a1659ba6d", + "b008a9e614c1454e9b127b4d59a0d54cea2385bc", "support" ], "gamepad/OWNERS": [ @@ -412794,7 +413333,7 @@ "testharness" ], "generic-sensor/META.yml": [ - "1cfe809776ba04c66560bc9ef6cce0aa476b7082", + "bf48f80f8083f0ca13f432d16a7b3b22b3435526", "support" ], "generic-sensor/OWNERS": [ @@ -413110,7 +413649,7 @@ "manual" ], "gyroscope/META.yml": [ - "67f22d5374b0385db98fc885918d3b2f23a2f66b", + "6a48535e3c7416eb1d54b1a6e6837230ba498b39", "support" ], "gyroscope/OWNERS": [ @@ -413190,7 +413729,7 @@ "testharness" ], "html-media-capture/META.yml": [ - "706dbdf8b6a4bebc09ba4e988936194b8e9a62a2", + "3dd015f3ecb7d95f6677031448823cf5028f546f", "support" ], "html-media-capture/OWNERS": [ @@ -413762,7 +414301,7 @@ "support" ], "html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html": [ - "4d811199b146ec49a5425c6dadee81a51fc1a8c1", + "e9284824f44f2daf663a4155ebf7c203a7e39290", "testharness" ], "html/browsers/browsing-the-web/read-media/pageload-image.html": [ @@ -415425,6 +415964,10 @@ "88a3beba6f10b80b0b90acdc0b0f957e1a17cefc", "testharness" ], + "html/browsers/the-window-object/document-attribute.window.js": [ + "f13acdb8a3261410c0f3100fea49f1ba110ea9ab", + "testharness" + ], "html/browsers/the-window-object/focus.window.js": [ "6ec7feee281e756ae6452e0f9b17d9b93032d010", "testharness" @@ -415533,6 +416076,10 @@ "1fb0ed7c1e62da55b890c6434bee6e46637e0209", "testharness" ], + "html/browsers/the-window-object/self-et-al.window.js": [ + "1b0fa1211a701253b61d1eced344faa8763ad6ef", + "testharness" + ], "html/browsers/the-window-object/support/closed.html": [ "3b70598e34d0e9b46a8ba2150a1589fecfb90ea8", "support" @@ -426361,34 +426908,18 @@ "f37bc33f6f93ca94940ffeb0066945eb9aa020ee", "testharness" ], - "html/semantics/forms/form-submission-target/rel-base-target-expected.txt": [ - "6d848622efe8cf1ac7a49ac1f458517e51147db8", - "support" - ], "html/semantics/forms/form-submission-target/rel-base-target.html": [ "222be95d2e8a9da39525fbf6d8048e6cdfd7a982", "testharness" ], - "html/semantics/forms/form-submission-target/rel-button-target-expected.txt": [ - "c2ff926d578885e946f148903c330ac2a878e380", - "support" - ], "html/semantics/forms/form-submission-target/rel-button-target.html": [ "76fa8685905ad233f9312be3f6bf09503158a666", "testharness" ], - "html/semantics/forms/form-submission-target/rel-form-target-expected.txt": [ - "88e33b90d9131401e3e53638d311198e3ff3ae2c", - "support" - ], "html/semantics/forms/form-submission-target/rel-form-target.html": [ "58611f41a9fdaea1611513e02dad87e017728f9a", "testharness" ], - "html/semantics/forms/form-submission-target/rel-input-target-expected.txt": [ - "b67908139dc6327eabc12a1a5da4b6f4c61de6eb", - "support" - ], "html/semantics/forms/form-submission-target/rel-input-target.html": [ "b80e0240bae3802b04118249ec2b94e16a91e9e6", "testharness" @@ -432541,6 +433072,34 @@ "ef5de2164ed8d58fd27bcbd92eb891892ad28e25", "testharness" ], + "idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ + "f8f57348dfa10cf671f82902f4ec7d4ca5fcd7c6", + "testharness" + ], + "idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html": [ + "422c45c3de6a74134be261142d455a2003a30999", + "testharness" + ], + "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html": [ + "3c019b7e0e476b82e812a3821119c0365eee2fd2", + "testharness" + ], + "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html.headers": [ + "729e9429e6a4ad7375474297d4fd7e7599eb04e0", + "support" + ], + "idle-detection/idle-detection-default-feature-policy.https.sub.html": [ + "7ecf7a4f67700fa86fea55d744656875f1960820", + "testharness" + ], + "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html": [ + "cb455f40bab08010511f17eea4b764872bfbf9b1", + "testharness" + ], + "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html.headers": [ + "f27e1a262717ea1ed666f59035a88a1d481a7460", + "support" + ], "idle-detection/idle-detection.idl": [ "4b502c975ce3b25a94518ce5d98c842b57c6a70d", "support" @@ -432557,8 +433116,16 @@ "d88d1ad1c55afaee243e1e9146827b073c380613", "support" ], + "idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js": [ + "103ce5e9bdb0fae14cd88b4f760c93afce47ae2b", + "support" + ], + "idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js": [ + "66218a5c4420b5644ddefa276fb52f2718907525", + "support" + ], "imagebitmap-renderingcontext/META.yml": [ - "f6a06f4e7d7625855e271ec5422629ca5e734560", + "4239a85f5eeb8de0660d138c5a3d48a17545a9eb", "support" ], "imagebitmap-renderingcontext/OWNERS": [ @@ -434430,7 +434997,7 @@ "support" ], "lint.whitelist": [ - "85d31ced2d6879dd162d4cd3f50229bf851e7f7b", + "12b32126b6677b19836943aee6c604296f9a597d", "support" ], "loading/preloader-css-import-no-quote.tentative.html": [ @@ -434534,7 +435101,7 @@ "testharness" ], "magnetometer/META.yml": [ - "88b900c569340a167ac2a8aa967099bfdfff388b", + "d7d395ee8f2a942327858b189dd8a6b2a249c14e", "support" ], "magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt": [ @@ -434670,11 +435237,11 @@ "reftest" ], "mathml/presentation-markup/fractions/frac-linethickness-001-ref.html": [ - "c703edb764fe883e05e47e26464149aa64af1070", + "d4be8ea03bfc29506af0e26a3d94d5eeafaaf472", "support" ], "mathml/presentation-markup/fractions/frac-linethickness-001.html": [ - "83e15c83dc0bcb911eb52a6b74b86a13c2f1e31e", + "eca82878caec21ea50ed0d3562ac3449e54c7567", "reftest" ], "mathml/presentation-markup/fractions/frac-linethickness-002-ref.html": [ @@ -435862,7 +436429,7 @@ "support" ], "mediacapture-depth/META.yml": [ - "e083c9b8c3ab0b20b24976d8ab94f5d04fb243dd", + "434612091df41dcf66859c46c66ed8cdaa6ba316", "support" ], "mediacapture-depth/dictionary-helper.js": [ @@ -436126,7 +436693,7 @@ "testharness" ], "mediacapture-streams/META.yml": [ - "1ed650e97c451ef1266fd8435e2260d6bf617b67", + "960dc3a5ac47e9c14e8651504cb8057242f7a3be", "support" ], "mediacapture-streams/MediaDevices-IDL-all-expected.txt": [ @@ -436242,7 +436809,7 @@ "manual" ], "mediacapture-streams/MediaStreamTrack-getCapabilities.https-expected.txt": [ - "c245e7eb9b089b3a9fe1d272215dc969054323c7", + "e7f474c303398f0d34de45d621f6b87dfe4da808", "support" ], "mediacapture-streams/MediaStreamTrack-getCapabilities.https.html": [ @@ -439133,6 +439700,10 @@ "74b85c9dbb5e03266c0ba0145ad45d67a025fd0c", "testharness" ], + "navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html": [ + "c0dd249545a640ec0cdd759b2114ab725a609039", + "testharness" + ], "navigation-timing/nav2_test_redirect_none.html": [ "97437e1a5ef2b61ae65762bfa351630eb4714cdf", "testharness" @@ -439161,6 +439732,14 @@ "fb7247d10b7566a93b955e0b9145e3089f329cf4", "testharness" ], + "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html": [ + "0b3978641b9a74f7f9d85c50cefe48210a8f1473", + "testharness" + ], + "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html": [ + "d3ff55087a1715f14a6b089b7bf80e8037ae8a1a", + "testharness" + ], "navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirects.html": [ "8a7f57d746009367d099d141620bcfdfd88acc7d", "testharness" @@ -439418,7 +439997,7 @@ "support" ], "notifications/META.yml": [ - "2cb7972705c7b9ef00375dfa4258e92edb15fb21", + "0daa86e6f487e90830b400bf7f2b871700d024b8", "support" ], "notifications/OWNERS": [ @@ -439546,7 +440125,7 @@ "manual" ], "offscreen-canvas/META.yml": [ - "bcb30ed276642fbbe2d055c6a1d131e097daac69", + "d3e4c387e8b5b9d27ea3dea6febdc1d9a662e4f0", "support" ], "offscreen-canvas/OWNERS": [ @@ -446078,7 +446657,7 @@ "testharness" ], "orientation-sensor/META.yml": [ - "99d6166664ca11196582e9bd058d225df833a4e2", + "427385826fca7a770a816abc5d98cc324f647f68", "support" ], "orientation-sensor/OWNERS": [ @@ -446270,7 +446849,7 @@ "testharness" ], "paint-timing/META.yml": [ - "24acb2587d1a375bfee12c56c56dd457ee6152cd", + "1892a41ed1cffcc8ba704f28bd59f5aa64c2b46a", "support" ], "paint-timing/OWNERS": [ @@ -446494,7 +447073,7 @@ "testharness" ], "payment-method-id/META.yml": [ - "e0931f4f8f584199e85f31501cc6a717e57fe4ab", + "5e9fe05abae6f862301ef85f9905d91eb4e42121", "support" ], "payment-method-id/OWNERS": [ @@ -446534,7 +447113,7 @@ "support" ], "payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html": [ - "45f3f0a5672cf64501718aa43dc5aac87249bab9", + "226fd88ff84ab58baa39da7f0691b18c50b3ff72", "manual" ], "payment-request/PaymentCurrencyAmount/currencySystem-member.https-expected.txt": [ @@ -446834,7 +447413,7 @@ "manual" ], "payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html": [ - "c8dd92636c6392b2436c8235340355c4529e12c1", + "f3f3f76357c1467f4032c5749849bd0063b41010", "manual" ], "payment-request/payment-response/onpayerdetailchange-attribute.https.html": [ @@ -446914,7 +447493,7 @@ "support" ], "payment-request/show-method-postmessage-manual.https.html": [ - "05fce4f248e8ff116065988d1d4d3d2875967ce5", + "920e0a9992eba1f604d5d0246f1c7e7e7b42bd1d", "manual" ], "payment-request/updateWith-method-pmi-handling-manual.https.html": [ @@ -447102,7 +447681,7 @@ "testharness" ], "pointerevents/META.yml": [ - "be61ddddaf62acb3396ada6779ad3f50e6caa709", + "1962feaf8af08b003e519fa525271e70451984d5", "support" ], "pointerevents/OWNERS": [ @@ -447517,13 +448096,13 @@ "f176343a487de4d71bda196657c7958ac62f1553", "testharness" ], - "pointerlock/mouse_buttons_back_forward-manual.html": [ - "4515ebabcbd3dfef30b89512609078b7d89a2a92", - "manual" + "pointerlock/mouse_buttons_back_forward.html": [ + "95490d2d4df442bba56aed62205bdf3bc34e55a3", + "testharness" ], - "pointerlock/movementX_Y_basic-manual.html": [ - "083b7075decf4ecaf782e319139fb52b07fdafe9", - "manual" + "pointerlock/movementX_Y_basic.html": [ + "b09d896ecfb90eea17c294c77582ba53b07283da", + "testharness" ], "pointerlock/movementX_Y_no-jumps-manual.html": [ "11b8d2a49e0a3b59b76174e652b55ef7d5bf939e", @@ -447549,17 +448128,17 @@ "8373a345ea03ca44812efbe6cb2b1d1054050b3e", "manual" ], - "pointerlock/pointerlock_remove_target-manual.html": [ - "a38b06e120535c12f3c93fa2bc035ff46541325e", - "manual" + "pointerlock/pointerlock_remove_target.html": [ + "0ffc9d10a0acd1f026b0e34e8392a8a5408fed84", + "testharness" ], - "pointerlock/pointerlock_remove_target_on_mouseup-manual.html": [ - "71b9eb693713556a7cf263c8a9cc00880e57758c", - "manual" + "pointerlock/pointerlock_remove_target_on_mouseup.html": [ + "4f7a15309c97cc91ec990be25bb803a85bb9c92c", + "testharness" ], - "pointerlock/pointerlock_shadow-manual.html": [ - "8e70915bb89740cb4edfe6a0b92057900bd294db", - "manual" + "pointerlock/pointerlock_shadow.html": [ + "21f3a928cd410471aa7fd32b6a7d427535007041", + "testharness" ], "portals/META.yml": [ "2b3241dd18b60e7e5343aa46d31253f12d415cd1", @@ -447569,6 +448148,10 @@ "29134d490f7bdfb09255e190fe91576629057c78", "support" ], + "portals/portal-activate-data.html": [ + "e2417cb7332010cccd66435743f300313614c0e6", + "testharness" + ], "portals/portal-activate-event.html": [ "33d91e37d9d9ac77c5243a60b42ce841645d248e", "testharness" @@ -447613,6 +448196,10 @@ "4a8414ab5656593811772c3728e4ee83eb034457", "support" ], + "portals/resources/portal-activate-data-portal.html": [ + "cba38a005f57a547c984db0152c918046ced471d", + "support" + ], "portals/resources/portal-activate-event-portal.html": [ "b2759c3701aaba4f5887a8b90bf4ee30e8153661", "support" @@ -448310,7 +448897,7 @@ "support" ], "referrer-policy/META.yml": [ - "a622289c0562dbac99de0a9dbd3b9a70e0783923", + "8ead043aad0a6aa79dad5c2c9e9b757df5869265", "support" ], "referrer-policy/OWNERS": [ @@ -457382,7 +457969,7 @@ "testharness" ], "resource-timing/META.yml": [ - "a2ce7c48f501436168ab93f791f1964e91a14fef", + "76176970d4d93e6a66bf2bc62aec5dd62ccd12c1", "support" ], "resource-timing/OWNERS": [ @@ -457393,6 +457980,10 @@ "26e0a8017d6c2c7b51c94998f34a79fa20eb1e12", "support" ], + "resource-timing/TAO-crossorigin-port.sub.html": [ + "0601217d0ae3a7bc057853dd23901650ccfe4633", + "testharness" + ], "resource-timing/buffer-full-add-after-full-event.html": [ "73ad841e92fddff1e05395241d69a0079e7a84da", "testharness" @@ -457449,6 +458040,10 @@ "a7542f191c10ea7b42110b5fc80e7abf43174bb5", "testharness" ], + "resource-timing/nested-context-navigations.html": [ + "483cc5b82d5debf942dd0013a340f9d5f550834c", + "testharness" + ], "resource-timing/no-entries-for-cross-origin-css-fetched.sub-expected.txt": [ "a256bb2dc766a40f21115049572246bf003499ba", "support" @@ -457565,14 +458160,14 @@ "9912da7c3400138d73245acc372463ca174e6f58", "testharness" ], - "resource-timing/resource_memory_cached.sub.html": [ - "89b5874978c97cd25e31da263d07c9f91c69bbfa", - "testharness" - ], "resource-timing/resource_reparenting.html": [ "7d4947fa7703d13a5adb465ff5eebbb4456cace9", "testharness" ], + "resource-timing/resource_reuse.sub.html": [ + "ff69a2ce73d1fee315ac1134cdbc5c1ff6ccf9fd", + "testharness" + ], "resource-timing/resource_script_types.html": [ "898fa0cee2cb29f69c11d70d831c2eade5b75036", "testharness" @@ -457610,7 +458205,7 @@ "testharness" ], "resource-timing/resources/TAOResponse.py": [ - "fefc75b7b7fc68872b36f56bcb0fa59dd41d2918", + "d98098ccc83e56bfba7f48ae5dc39ffd6e9b969f", "support" ], "resource-timing/resources/all_resource_types.htm": [ @@ -457641,6 +458236,34 @@ "fbd7bc3b6e21ee39478c8a63780bb673dafe96a4", "support" ], + "resource-timing/resources/document-navigated.html": [ + "fa87355c3ed18f5011146a373c4029d3272bb6a8", + "support" + ], + "resource-timing/resources/document-refreshed.html": [ + "7e4ca09891ed35e244b15151a2a6077af74e865f", + "support" + ], + "resource-timing/resources/document-that-navigates.html": [ + "cb567bf3d2ad12154155aef6ad1da7be2a1f3d78", + "support" + ], + "resource-timing/resources/document-that-refreshes.html": [ + "75522782a62dbe3b98b2f1a09c5babc7063b7510", + "support" + ], + "resource-timing/resources/embed-navigate-back.html": [ + "3c3def1d1a1d04279ad2bbceb220879398943681", + "support" + ], + "resource-timing/resources/embed-navigate.html": [ + "20a73c662b4f7b00daa96feda64cde16fc6a6490", + "support" + ], + "resource-timing/resources/embed-refresh.html": [ + "4a49fd0b4c1b54c0f03200f7ed2cb2ae27239788", + "support" + ], "resource-timing/resources/empty.js": [ "3b44754e301ded90e559f6343df641e476803542", "support" @@ -457681,6 +458304,22 @@ "31a769eb3666492a3804f1c3deca73df526c0a4f", "support" ], + "resource-timing/resources/iframe-TAO-crossorigin-port.sub.html": [ + "39f5d13054a79281ed0131315f834645e6e7790c", + "support" + ], + "resource-timing/resources/iframe-navigate-back.html": [ + "c5c1fc1ad4dfaaedc441ae8854079402e56d1106", + "support" + ], + "resource-timing/resources/iframe-navigate.html": [ + "2a1a7e063619fe62c7acf87b99acda26d2cbcf32", + "support" + ], + "resource-timing/resources/iframe-refresh.html": [ + "4ce3ea0424297ac7a8664fc7f7a6dcbff64d6f14", + "support" + ], "resource-timing/resources/iframe-reload-TAO.sub.html": [ "577aff7758c779893f010658d216f34802a4edfe", "support" @@ -457737,6 +458376,14 @@ "d1802a1e02d9aacad091e814cc2955d244d2f977", "support" ], + "resource-timing/resources/navigate_back.html": [ + "345eee1fccca5cf2ea94865a41a41f6e897ede15", + "support" + ], + "resource-timing/resources/nested-contexts.js": [ + "0c202243702aec81426a2dfbca05ce1118c5978b", + "support" + ], "resource-timing/resources/nested.css": [ "90d61b04acc4443430c42331d8c7f21993b0ae4d", "support" @@ -457745,6 +458392,18 @@ "c104f3c8f0695a96646cf24a730eef0342f95876", "support" ], + "resource-timing/resources/object-navigate-back.html": [ + "64e5f584731fdf5fe89e8e60e19fea6bd0f24125", + "support" + ], + "resource-timing/resources/object-navigate.html": [ + "cbb862e7e00fcb7391107fdfe7e7870388f62a4a", + "support" + ], + "resource-timing/resources/object-refresh.html": [ + "b14cf7f17c9d807eaa904f92d170e9ee96435464", + "support" + ], "resource-timing/resources/resource_timing_test0.css": [ "8bc8326ba675adcc8aa809dd0b885dba3285782d", "support" @@ -457838,7 +458497,7 @@ "support" ], "resources/chromium/device.mojom.js": [ - "436d3038b85e4d6f92fa25cd93a41af667e85d26", + "6488cbc69c29170d9441d2210da27a464f67d445", "support" ], "resources/chromium/device.mojom.js.headers": [ @@ -457966,7 +458625,7 @@ "support" ], "resources/chromium/webusb-test.js": [ - "18ee824aafaf45087f4b0aa2d6e90811cb39a751", + "c4d4e8f1ac47a2f8c5ea02fa737a01b36aca6329", "support" ], "resources/chromium/webusb-test.js.headers": [ @@ -458118,7 +458777,7 @@ "testharness" ], "screen-orientation/META.yml": [ - "dc3f290196fabe6e4594a498282fc0091134bdad", + "3ddb3b0507d54269c54a552227771a0bf9131a0e", "support" ], "screen-orientation/OWNERS": [ @@ -458153,6 +458812,14 @@ "1041f91886a87083ed78227e15badb071395dfb4", "testharness" ], + "screen-orientation/lock-unlock-check-expected.txt": [ + "b4d17d2d48a94dffc0320236cad946850ec094e2", + "support" + ], + "screen-orientation/lock-unlock-check.html": [ + "129882d64f6d323d93a183d59f4744a8e888d3f1", + "testharness" + ], "screen-orientation/onchange-event-expected.txt": [ "76af39c5c08a2a59d1699fe78e04253db0db86a3", "support" @@ -458181,12 +458848,16 @@ "4cfd37d02bc58f2bed39075357b393fea769a155", "support" ], + "screen-orientation/resources/orientation-utils.js": [ + "8721818bec2fadcaa3010f3c48d9e38db854f669", + "support" + ], "screen-orientation/resources/sandboxed-iframe-locking.html": [ "e1b50f670105f3a05dacd3518d62770685121c67", "support" ], "scroll-animations/META.yml": [ - "20f3c7e6c930193207c6cbcd329e36f85a993dc9", + "c53f1f432fe1ec2887e30af396a1f1574b76b95d", "support" ], "scroll-animations/constructor-expected.txt": [ @@ -458341,8 +459012,12 @@ "faed70a5c863fb31572f069d598caccab3a00a03", "support" ], + "selection/Document-open-expected.txt": [ + "eaa85d4992385b5f5265eff529ceaedff9ed7c84", + "support" + ], "selection/Document-open.html": [ - "9d170914e6516b2829f1872e001dd4cd08e30b4c", + "9e3cb28124c0d65f61d1e71672c2429a3b64a792", "testharness" ], "selection/META.yml": [ @@ -462642,7 +463317,7 @@ "support" ], "shape-detection/idlharness.any-expected.txt": [ - "a2c26dcade6fe6ec10970115f2ce39faf5a7afa2", + "da45152cbbb78189eb3a5c1d95f5020e0266f383", "support" ], "shape-detection/idlharness.any.js": [ @@ -462814,7 +463489,7 @@ "support" ], "signed-exchange/resources/generate-test-sxgs.sh": [ - "60746ff34caaec9e83942aeae6a6cc74aa8138e0", + "e76286be991ca3d3832f767a5ab7aab172157184", "support" ], "signed-exchange/resources/inner-url.html": [ @@ -462829,6 +463504,18 @@ "d581d5987ea0f9d7c8164d680a4527f2ea519cd4", "support" ], + "signed-exchange/resources/register-sw-after-fallback.html": [ + "2711fc241f3215ff7e6649daefde40e7b2e147da", + "support" + ], + "signed-exchange/resources/register-sw.html": [ + "8a3873bfde88dd9bd0cc979f3db6a7d88b776d22", + "support" + ], + "signed-exchange/resources/service-worker.js": [ + "2647f45a3ea3e7e406305f41a3b4677b26ecd8e7", + "support" + ], "signed-exchange/resources/sxg-location.html": [ "b3ebd2bde7acd2d1885838a37ab9cfc91c250551", "support" @@ -462838,7 +463525,7 @@ "support" ], "signed-exchange/resources/sxg-util.js": [ - "7abb3cf2079087092ac4a7f7332ecf72f9cabd75", + "78edf137408f93150209f76b6e492d13805ca95a", "support" ], "signed-exchange/resources/sxg-version1b2.sxg": [ @@ -462873,6 +463560,14 @@ "6d8538882d27c40b0ffcf0845c090844aaec87b7", "support" ], + "signed-exchange/resources/sxg/register-sw-after-fallback.sxg": [ + "20ae275818765133e5018e0db2263cf21269d756", + "support" + ], + "signed-exchange/resources/sxg/register-sw-from-sxg.sxg": [ + "792222029f1730c20c6673a9b89771c70226faea", + "support" + ], "signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg": [ "2a7dbf6fa69ae29055e51f6c7d32d3ab4ceb6765", "support" @@ -462969,6 +463664,22 @@ "ae96b7213fa7f3d056964a2eeab1528ff840486a", "support" ], + "signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https-expected.txt": [ + "7a8dbb39f3ab20ec490af6a4a60b349d0f09cd25", + "support" + ], + "signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html": [ + "2b76a70dc9feb2fe446fa309202494b172dcb04e", + "testharness" + ], + "signed-exchange/service-workers/sxg-sw-register.tentative.https-expected.txt": [ + "c50ff44a931570ed8899d48654ffbd5d66b98ad4", + "support" + ], + "signed-exchange/service-workers/sxg-sw-register.tentative.https.html": [ + "ad21ebb20d44c846bd99cbffeb510c8af2bb81ea", + "testharness" + ], "signed-exchange/sxg-double-prefetch.tentative.html": [ "d682741744fed929bee8e62fbae4857a4bfbf1d5", "testharness" @@ -463062,7 +463773,7 @@ "testharness" ], "speech-api/META.yml": [ - "4d1b42a44d2a6a447f8a47bc079d7e28436843e0", + "9ce8830e78fc4be5b25e5382248810932abfd829", "support" ], "speech-api/OWNERS": [ @@ -463250,7 +463961,7 @@ "testharness" ], "streams/META.yml": [ - "108c774fae6f0f56b562bfcd0823fab4709f36c5", + "1259a55cb5a99e3ba3a13d81d02dd78d697ddabf", "support" ], "streams/OWNERS": [ @@ -463734,7 +464445,7 @@ "testharness" ], "subresource-integrity/META.yml": [ - "2b8891ec6b498cc6b24df46e21fffad437732b54", + "f6980682f11bc29b19789c91a93d9e0f58383306", "support" ], "subresource-integrity/OWNERS": [ @@ -463926,7 +464637,7 @@ "support" ], "svg/META.yml": [ - "09ef583b72d7a204612e8f124404895137d80205", + "2904d6f606bfd2092952dcb7883d66afc9e9be8b", "support" ], "svg/OWNERS": [ @@ -465706,7 +466417,7 @@ "support" ], "tools/ci/azure/affected_tests.yml": [ - "17fca51d50cbd4f1986c63f3383b18dbdbe9c6fe", + "8076bc386986ed48a7af50fd48a59a544bf8c3bc", "support" ], "tools/ci/azure/checkout.yml": [ @@ -465830,7 +466541,7 @@ "support" ], "tools/ci/taskcluster-run.py": [ - "78c50a6285e81c8fa5e69585a28f04e957a59869", + "fbd2f2ab4ea0b27ffd1690d10d64f88937228d20", "support" ], "tools/ci/tcdownload.py": [ @@ -465910,7 +466621,7 @@ "support" ], "tools/manifest/manifest.py": [ - "7640136b21317f9c990a3021337146f03a796993", + "dc57c24ddb084e2af0eb93e6470f7e5024d6e469", "support" ], "tools/manifest/sourcefile.py": [ @@ -470102,7 +470813,7 @@ "support" ], "tools/wpt/run.py": [ - "df34e591568617616211e0f549872fe94c7568d8", + "a19851d14c5cd2a64355a4e0389ace0b7cbd022f", "support" ], "tools/wpt/testfiles.py": [ @@ -470122,7 +470833,7 @@ "support" ], "tools/wpt/virtualenv.py": [ - "61de936b7679e0f143d43278ad2494b34140b004", + "357ddcbefce1f9ed81324bab0bf2467f572b0753", "support" ], "tools/wpt/wpt.py": [ @@ -470142,7 +470853,7 @@ "support" ], "tools/wptrunner/requirements.txt": [ - "6216fb6708da3c60d6e2b0a60d92a232dc383b0f", + "f17b12b3dddffd988bf05b1255761b713e28ca49", "support" ], "tools/wptrunner/requirements_chrome.txt": [ @@ -470162,7 +470873,7 @@ "support" ], "tools/wptrunner/requirements_firefox.txt": [ - "ee84d840f814088fdb4607ff355096772894a987", + "668cea391543074722e19ad802ea189df84890c0", "support" ], "tools/wptrunner/requirements_ie.txt": [ @@ -471534,7 +472245,7 @@ "testharness" ], "url/META.yml": [ - "3a789a0d513f0a78bf362dd73c8a807d0cd55a50", + "094b266b64b61b97966f2fa88d78dfdf5a00b573", "support" ], "url/OWNERS": [ @@ -471834,7 +472545,7 @@ "testharness" ], "vibration/META.yml": [ - "016588931f9d1221bd9730605bd3d7abaeb069d7", + "91cd8c9d8056e8512e049280b7c1a43a76b3074f", "support" ], "vibration/OWNERS": [ @@ -472002,7 +472713,7 @@ "support" ], "wake-lock/META.yml": [ - "a5ff85281f875366aa3f22262e1a58beb60fe8f3", + "7ca3da2d8d2e4c90c55074246589d5464aa7ae3e", "support" ], "wake-lock/OWNERS": [ @@ -474182,7 +474893,7 @@ "testharness" ], "webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html": [ - "2c1162d47b973937c826caba0c740f58970defcc", + "3e364eb7b359948402ef8ecdb287a5f55bb80fc3", "testharness" ], "webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/no-cors.https.html": [ @@ -475390,7 +476101,7 @@ "testharness" ], "webmessaging/META.yml": [ - "e70b780b57a659a928ce7575f19224dcce8087f9", + "95d5071171b5a20cc14a414c97c9eae2f525f43f", "support" ], "webmessaging/MessageEvent-trusted-worker.js": [ @@ -475958,7 +476669,7 @@ "testharness" ], "webrtc/META.yml": [ - "2025a11f3810042bcef24acae751ce5ffd3a3ee8", + "eed4ac834313773528e5665d80505cb4b951a1c9", "support" ], "webrtc/OWNERS": [ @@ -476198,7 +476909,7 @@ "support" ], "webrtc/RTCPeerConnection-getStats.https.html": [ - "247402b83be0a2655fa8d4ad43fa166b6459c587", + "c2c4e8e37176ce13447c1c8238aa6243f9aea130", "testharness" ], "webrtc/RTCPeerConnection-getTransceivers.html": [ @@ -476238,11 +476949,11 @@ "testharness" ], "webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt": [ - "086110186f91ea9336e73f0cc0bc1217aafef88a", + "62c3abf9a08a1fcbc0c5454a5b417ea4c85623e3", "support" ], "webrtc/RTCPeerConnection-onnegotiationneeded.html": [ - "ac9d70c43eff1ddd0995dcea741f3b6ea850464b", + "f7bf8bd3e3bdc24c63a92da22eaae77b95f0d4fd", "testharness" ], "webrtc/RTCPeerConnection-onsignalingstatechanged.https.html": [ @@ -476302,7 +477013,7 @@ "testharness" ], "webrtc/RTCPeerConnection-setLocalDescription.html": [ - "5e9b54389bf8ca762eeb95be275991f1f9291fd2", + "2becbd3e23efee6ee14988b770c34e8fba9d3455", "testharness" ], "webrtc/RTCPeerConnection-setRemoteDescription-answer.html": [ @@ -476358,7 +477069,7 @@ "testharness" ], "webrtc/RTCPeerConnection-transceivers.https.html": [ - "f56a170616cca25d2619158a2f3894aeee59b95a", + "9b3a9a85413e2dcfdbcbbefe2b8b05a0ffd05ca0", "testharness" ], "webrtc/RTCPeerConnectionIceEvent-constructor-expected.txt": [ @@ -477726,7 +478437,7 @@ "support" ], "webstorage/META.yml": [ - "0da67a586b84030b835ddbdaa0af20ddadb8f4b3", + "020075c3f2401ca4b8da73116a84582d46e265c0", "support" ], "webstorage/OWNERS": [ @@ -481198,7 +481909,7 @@ "support" ], "webxr/META.yml": [ - "b5e3e65a12cb4124e43c4f24b7fca84910fda119", + "520afec2000721d04aae9ed89bca49297fa31d4b", "support" ], "webxr/OWNERS": [ @@ -481206,7 +481917,7 @@ "support" ], "webxr/idlharness.https.window-expected.txt": [ - "c491e806fb5c5c9aed9f7cad7e6cc65e080b8350", + "979535e73edb7d4bb6aafa38d5e418f420c4ec14", "support" ], "webxr/idlharness.https.window.js": [ @@ -481221,6 +481932,10 @@ "2d8e5b387dc88588921ccfa49dd14db58009900c", "support" ], + "webxr/resources/webxr_math_utils.js": [ + "bb55fb72978690427aac38b84d1eac24e838d0eb", + "support" + ], "webxr/resources/webxr_test_asserts.js": [ "2253ffc2d39d268142711fca7f81dda3fc6a318c", "support" @@ -481290,13 +482005,17 @@ "testharness" ], "webxr/xrRay_matrix.https.html": [ - "3c9cea0849f77063d3c86eff7f2d85e4830c851c", + "85d7bffb87b731f6a863ec752ede5ceac3bfca16", "testharness" ], "webxr/xrRigidTransform_constructor.https.html": [ "abaf8bf9ebe2fed3c99cef5bf52d697b9e8ed1c8", "testharness" ], + "webxr/xrRigidTransform_matrix.https.html": [ + "21236c732461de4422dcab7a3709cdc7ffc0f3a6", + "testharness" + ], "webxr/xrSession_cancelAnimationFrame.https.html": [ "cc7b8802cba01ac03adb53a06308acd5642dd0af", "testharness" @@ -483262,7 +483981,7 @@ "testharness" ], "xhr/META.yml": [ - "4b2ecf39bf3a07188d587f0a7ac3d22cad55f923", + "c343ceac4375531d92d2ef1ec88de5c7a3897bbe", "support" ], "xhr/OWNERS": [
diff --git a/third_party/blink/web_tests/external/wpt/2dcontext/META.yml b/third_party/blink/web_tests/external/wpt/2dcontext/META.yml index 53b11d2..0f79f259 100644 --- a/third_party/blink/web_tests/external/wpt/2dcontext/META.yml +++ b/third_party/blink/web_tests/external/wpt/2dcontext/META.yml
@@ -3,5 +3,4 @@ - AmeliaBR - annevk - kenrussell - - jdashg - fserb
diff --git a/third_party/blink/web_tests/external/wpt/WebIDL/META.yml b/third_party/blink/web_tests/external/wpt/WebIDL/META.yml index 82ae523..a8dc9c44 100644 --- a/third_party/blink/web_tests/external/wpt/WebIDL/META.yml +++ b/third_party/blink/web_tests/external/wpt/WebIDL/META.yml
@@ -1,6 +1,5 @@ spec: https://heycam.github.io/webidl/ suggested_reviewers: - domenic - - jensl - tobie - yuki3
diff --git a/third_party/blink/web_tests/external/wpt/accelerometer/META.yml b/third_party/blink/web_tests/external/wpt/accelerometer/META.yml index 6554be8..7df27e1f 100644 --- a/third_party/blink/web_tests/external/wpt/accelerometer/META.yml +++ b/third_party/blink/web_tests/external/wpt/accelerometer/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/accelerometer/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/ambient-light/META.yml b/third_party/blink/web_tests/external/wpt/ambient-light/META.yml index 04fce804..c3f69ba 100644 --- a/third_party/blink/web_tests/external/wpt/ambient-light/META.yml +++ b/third_party/blink/web_tests/external/wpt/ambient-light/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/ambient-light/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - rakuco - Honry
diff --git a/third_party/blink/web_tests/external/wpt/battery-status/META.yml b/third_party/blink/web_tests/external/wpt/battery-status/META.yml index eded36c5..12a2f12c 100644 --- a/third_party/blink/web_tests/external/wpt/battery-status/META.yml +++ b/third_party/blink/web_tests/external/wpt/battery-status/META.yml
@@ -1,5 +1,4 @@ spec: https://w3c.github.io/battery/ suggested_reviewers: - anssiko - - dontcallmedom - zqzhang
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/META.yml b/third_party/blink/web_tests/external/wpt/bluetooth/META.yml index 501396b..607edb6 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/META.yml +++ b/third_party/blink/web_tests/external/wpt/bluetooth/META.yml
@@ -1,6 +1,5 @@ spec: https://webbluetoothcg.github.io/web-bluetooth/ suggested_reviewers: - dougt - - g-ortuno - odejesush - reillyeon
diff --git a/third_party/blink/web_tests/external/wpt/common/META.yml b/third_party/blink/web_tests/external/wpt/common/META.yml index 594c8b17..958883a 100644 --- a/third_party/blink/web_tests/external/wpt/common/META.yml +++ b/third_party/blink/web_tests/external/wpt/common/META.yml
@@ -1,5 +1,4 @@ suggested_reviewers: - zqzhang - - dontcallmedom - deniak - gsnedders
diff --git a/third_party/blink/web_tests/external/wpt/cookies/META.yml b/third_party/blink/web_tests/external/wpt/cookies/META.yml index 946da88..d074394 100644 --- a/third_party/blink/web_tests/external/wpt/cookies/META.yml +++ b/third_party/blink/web_tests/external/wpt/cookies/META.yml
@@ -1,3 +1,2 @@ suggested_reviewers: - - inikulin - mikewest
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/META.yml b/third_party/blink/web_tests/external/wpt/css/CSS2/META.yml index 4ac0804..e9bc44dc 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/META.yml
@@ -5,4 +5,3 @@ - svgeesus - kojiishi - frivoal - - bert-github
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/META.yml b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/META.yml index d90a6e0..d673be5 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/META.yml
@@ -1,6 +1,4 @@ spec: https://drafts.csswg.org/css-backgrounds/ suggested_reviewers: - dbaron - - bert-github - fantasai - - bradkemper
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/META.yml b/third_party/blink/web_tests/external/wpt/css/css-color/META.yml index a8d93c12..a0e70aa 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-color/META.yml
@@ -1,6 +1,5 @@ spec: https://drafts.csswg.org/css-color/ suggested_reviewers: - dbaron - - tantek - svgeesus - tabatkins
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/META.yml b/third_party/blink/web_tests/external/wpt/css/css-flexbox/META.yml index 764d8cbd..0bcad0b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/META.yml
@@ -4,7 +4,6 @@ - plinss - mrego - cbiesinger - - atanassov - fantasai - rachelandrew - tabatkins
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/META.yml b/third_party/blink/web_tests/external/wpt/css/css-grid/META.yml index af20bb4..e49946f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/META.yml
@@ -2,10 +2,8 @@ suggested_reviewers: - mrego - plinss - - jxs - tabatkins - fantasai - - atanassov - javifernandez - rachelandrew - svillar
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html new file mode 100644 index 0000000..96a3ca1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage-ref.html
@@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: Testcase for bug 1526567</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.webconsole-app { + display: grid; +} + +.sidebar { + display: flex; + flex: 1; + flex-direction: row; + background: blue; +} + +.controlled { + display: flex; + overflow: auto; +} + +.sidebar-wrapper { + display: grid; + grid-template-columns: 100px; + grid-template-rows: 50px 1fr; + overflow: hidden; +} + +.sidebar-contents { + grid-row: 2 / 3; + overflow: auto; +} + + </style> +</head> +<body> + +<div class="webconsole-app"> + <div class="sidebar"> + <div class="controlled"> + <div class="sidebar-wrapper"> + <div></div> + <div class="sidebar-contents"> + <div style="height:400px; background: grey"></div> + </div> + </div> + </div> + </div> +</div> + + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html new file mode 100644 index 0000000..62273b87 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-overflow-auto-max-height-percentage.html
@@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Testcase for bug 1526567</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto"> + <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1526567"> + <link rel="match" href="grid-item-overflow-auto-max-height-percentage-ref.html"> + <meta name="assert" content="Check that max-height:100% has no effect on a grid item's max-content contribution, since the percentage basis is indefinite in this case."> + <style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.webconsole-app { + display: grid; + height: 200px; +} + +.sidebar { + display: flex; + flex: 1; + flex-direction: row; + height: 100%; + background: blue; +} + +.controlled { + display: flex; + overflow: auto; +} + +.sidebar-wrapper { + display: grid; + grid-template-columns: 100px; + grid-template-rows: 50px 1fr; + overflow: hidden; +} + +.sidebar-contents { + grid-row: 2 / 3; + overflow: auto; + max-height: 100%; +} + + </style> +</head> +<body> + +<div class="webconsole-app"> + <div class="sidebar"> + <div class="controlled"> + <div class="sidebar-wrapper"> + <div></div> + <div class="sidebar-contents"> + <div style="height:400px; background: grey"></div> + </div> + </div> + </div> + </div> +</div> + + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html new file mode 100644 index 0000000..1090871 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001-ref.html
@@ -0,0 +1,312 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Reference: item [min-|max-]*[width|height] percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px / 3px auto 4px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2; + height: 30px; + width: 30px; +} +.content { + height: 30px; + width: 30px; +} +.min { + height: 7px; + width: 3px; +} +.min:not(.max):not(.size) { + height: 30px; + width: 30px; +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001.html new file mode 100644 index 0000000..97532e4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001.html
@@ -0,0 +1,318 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: item [min-|max-]*[width|height] percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<link rel="help" href="http://www.w3.org/TR/css-grid-1"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1526567"> +<link rel="match" href="grid-item-percentage-sizes-001-ref.html"> +<meta name="assert" content="Checks that item [min-|max-]*[width|height] percentages are resolved correctly in span=1 auto tracks."> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px / 3px auto 4px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2; +} +.content { + height: 30px; + width: 30px; +} +.min { + min-height: 100%; + min-width: 100%; +} +.max { + max-height: 100%; + max-width: 100%; +} +.size { + height: 100%; + width: 100%; +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html new file mode 100644 index 0000000..5686426 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002-ref.html
@@ -0,0 +1,312 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Reference: item [min-|max-]*[width|height] percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px 3px / 3px auto 4px 2px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2/span 2/span 2; + height: 30px; + width: 30px; +} +.content { + height: 30px; + width: 30px; +} +.min { + height: 6px; + width: 5px; +} +.min:not(.max):not(.size) { + height: 30px; + width: 30px; +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002.html new file mode 100644 index 0000000..2ceba537 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002.html
@@ -0,0 +1,318 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: item [min-|max-]*[width|height] percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<link rel="help" href="http://www.w3.org/TR/css-grid-1"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1526567"> +<link rel="match" href="grid-item-percentage-sizes-002-ref.html"> +<meta name="assert" content="Checks that item [min-|max-]*[width|height] percentages are resolved correctly in span=2 auto tracks."> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px 3px / 3px auto 4px 2px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2/span 2/span 2; +} +.content { + height: 30px; + width: 30px; +} +.min { + min-height: 100%; + min-width: 100%; +} +.max { + max-height: 100%; + max-width: 100%; +} +.size { + height: 100%; + width: 100%; +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html new file mode 100644 index 0000000..41070a8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003-ref.html
@@ -0,0 +1,316 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Reference: item [min-|max-]*[width|height] calc() percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px / 3px auto 4px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2; + height: 30px; + width: 30px; +} +.content { + height: 30px; + width: 30px; +} +.min { + height: 9px; + width: 5px; +} +.min:not(.max):not(.size) { + height: 30px; + width: 30px; +} +.size:not(.min) { + height: 32px; + width: 32px; +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003.html new file mode 100644 index 0000000..fccf4fe --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-003.html
@@ -0,0 +1,318 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: item [min-|max-]*[width|height] calc() percentages</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<link rel="help" href="http://www.w3.org/TR/css-grid-1"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1526567"> +<link rel="match" href="grid-item-percentage-sizes-003-ref.html"> +<meta name="assert" content="Checks that item [min-|max-]*[width|height] percentages are resolved correctly in span=1 auto tracks."> +<style> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + height: 10px; + width: 10px; + grid: 1px auto 2px / 3px auto 4px; + border: solid 1px; + margin: 0 20px 20px 0; + place-items: start; +} +.item { + background: cyan; + grid-area: 2/2; +} +.content { + height: 30px; + width: 30px; +} +.min { + min-height: calc(2px + 100%); + min-width: calc(2px + 100%); +} +.max { + max-height: calc(2px + 100%); + max-width: calc(2px + 100%); +} +.size { + height: calc(2px + 100%); + width: calc(2px + 100%); +} + +.hl .item { writing-mode: horizontal-tb; direction:ltr; } +.hr .item { writing-mode: horizontal-tb; direction:rtl; } +.vrl .item { writing-mode: vertical-rl; direction:ltr; } +.vrr .item { writing-mode: vertical-rl; direction:rtl; } +.vll .item { writing-mode: vertical-lr; direction:ltr; } +.vlr .item { writing-mode: vertical-lr; direction:rtl; } +.sll .item { writing-mode: sideways-lr; direction:ltr; } +.slr .item { writing-mode: sideways-lr; direction:rtl; } + +</style> +<div class="hl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vrr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vll"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="vlr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="slr"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div> + +<div class="srl"> +<div class="grid"> + <div class="item max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item max size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min size"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max"> + <div class="content"></div> + </div> +</div> +<div class="grid"> + <div class="item min max size"> + <div class="content"></div> + </div> +</div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-logical/META.yml b/third_party/blink/web_tests/external/wpt/css/css-logical/META.yml index 98d838c..cf789d63 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-logical/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-logical/META.yml
@@ -1,4 +1,3 @@ spec: https://drafts.csswg.org/css-logical/ suggested_reviewers: - - atanassov - fantasai
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/META.yml b/third_party/blink/web_tests/external/wpt/css/css-position/META.yml index 00eb3b1..c1ce1ff 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-position/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-position/META.yml
@@ -1,3 +1,3 @@ spec: https://drafts.csswg.org/css-position/ suggested_reviewers: - - atanassov + - astearns
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt index c657b7c..3823a752 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 55 tests; 54 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 60 tests; 59 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS <length> values computed are correctly via var()-reference PASS <length> values computed are correctly via var()-reference when font-size is inherited PASS <length> values are computed correctly when font-size is inherited [14em] @@ -9,6 +9,11 @@ PASS <length> values are computed correctly [14em] PASS <length> values are computed correctly [15vmin] PASS <length> values are computed correctly [calc(16px - 7em + 10vh)] +PASS <length> values are computed correctly [1in] +PASS <length> values are computed correctly [2.54cm] +PASS <length> values are computed correctly [25.4mm] +PASS <length> values are computed correctly [6pc] +PASS <length> values are computed correctly [72pt] PASS <length-percentage> values are computed correctly [17em] PASS <length-percentage> values are computed correctly [18%] PASS <length-percentage> values are computed correctly [calc(19em - 2%)]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html index b1e5d237..f03b257 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
@@ -101,6 +101,12 @@ test_computed_value('<length>', '15vmin', length_ref('15vmin')); test_computed_value('<length>', 'calc(16px - 7em + 10vh)', length_ref('calc(10vh - 54px)')); +test_computed_value('<length>', '1in', '96px'); +test_computed_value('<length>', '2.54cm', '96px'); +test_computed_value('<length>', '25.4mm', '96px'); +test_computed_value('<length>', '6pc', '96px'); +test_computed_value('<length>', '72pt', '96px'); + test_computed_value('<length-percentage>', '17em', '170px'); test_computed_value('<length-percentage>', '18%', '18%'); test_computed_value('<length-percentage>', 'calc(19em - 2%)', 'calc(-2% + 190px)');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-initial.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-initial.html index d35b14b..17c883a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-initial.html +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-initial.html
@@ -18,6 +18,12 @@ } test_initial_value({ syntax: '<length>', initialValue: 'calc(10px + 15px)' }, '25px'); +test_initial_value({ syntax: '<length>', initialValue: '1in' }, '96px'); +test_initial_value({ syntax: '<length>', initialValue: '2.54cm' }, '96px'); +test_initial_value({ syntax: '<length>', initialValue: '25.4mm' }, '96px'); +test_initial_value({ syntax: '<length>', initialValue: '6pc' }, '96px'); +test_initial_value({ syntax: '<length>', initialValue: '72pt' }, '96px'); +test_initial_value({ syntax: '<percentage>', initialValue: 'calc(10% + 20%)' }, '30%'); test_initial_value({ syntax: '<length-percentage>', initialValue: 'calc(1in + 10% + 4px)' }, 'calc(10% + 100px)'); test_initial_value({ syntax: '<color>', initialValue: 'pink', inherits: true }, 'rgb(255, 192, 203)'); test_initial_value({ syntax: '<color>', initialValue: 'purple' }, 'rgb(128, 0, 128)');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scrollbars/META.yml b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/META.yml index 9209d5d..f7c0439 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scrollbars/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/META.yml
@@ -1,3 +1,3 @@ spec: https://drafts.csswg.org/css-scrollbars/ suggested_reviewers: - - tantek + - upsuper
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/META.yml b/third_party/blink/web_tests/external/wpt/css/css-shapes/META.yml index 9913681..2e433aa 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-shapes/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/META.yml
@@ -1,7 +1,5 @@ spec: https://drafts.csswg.org/css-shapes/ suggested_reviewers: - - bemjb - kojiishi - plinss - - atanassov - astearns
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html index 83eff4b4..207b60d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html
@@ -97,12 +97,14 @@ <input type="range" class="mb" orient="vertical"> </div></div> -<div class="grid" style="grid: 4px / auto"> - <input type="range" class="mb" orient="vertical" style="height:2px"> +<div class="grid" style="grid: min-content / auto"> + <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1"> + <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1"> </div> -<div class="grid" style="grid: 30px / auto"> - <input type="range" class="b" orient="vertical" style="height:15px"> +<div class="grid" style="grid: min-content / auto"> + <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1"> + <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1"> </div> <div class="grid" style="grid: 30px / auto"> @@ -117,12 +119,14 @@ <input type="range" class="mb n" orient="vertical"> </div></div> -<div class="grid" style="grid: 4px / auto"> - <input type="range" class="mb n" orient="vertical" style="height:2px"> +<div class="grid" style="grid: min-content / auto"> + <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1"> + <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1"> </div> -<div class="grid" style="grid: 30px / auto"> - <input type="range" class="b" orient="vertical" style="height:15px"> +<div class="grid" style="grid: min-content / auto"> + <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1"> + <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1"> </div> <div class="grid" style="grid: 30px / auto">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html index 815b0a1..861d34c6 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html
@@ -71,8 +71,9 @@ <input type="range" class="mb" orient="vertical"> </div></div> -<div class="grid" style="grid: 30px / auto"> - <input type="range" class="b" orient="vertical" style="height:15px"> +<div class="grid" style="grid: min-content / auto"> + <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1"> + <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1"> </div> <div class="grid" style="grid: 30px / auto">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-style-attr/META.yml b/third_party/blink/web_tests/external/wpt/css/css-style-attr/META.yml index 7243873..067e03cf 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-style-attr/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-style-attr/META.yml
@@ -1,4 +1,3 @@ spec: https://drafts.csswg.org/css-style-attr/ suggested_reviewers: - - tantek - fantasai
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/META.yml b/third_party/blink/web_tests/external/wpt/css/css-syntax/META.yml index 17489e1..359219c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-syntax/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/META.yml
@@ -2,4 +2,3 @@ suggested_reviewers: - gregwhitworth - tabatkins - - simonsapin
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/META.yml b/third_party/blink/web_tests/external/wpt/css/css-text/META.yml index 042b8585..e7914c0 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-text/META.yml
@@ -5,5 +5,4 @@ - frivoal - r12a - nox - - hakatashi - fantasai
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/META.yml b/third_party/blink/web_tests/external/wpt/css/css-transforms/META.yml index 33c1fce3..b948e3a3 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/META.yml
@@ -3,5 +3,4 @@ - dbaron - plinss - dirkschulze - - hober - grorg
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-flattening-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-flattening-001.html new file mode 100644 index 0000000..85d2977 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-flattening-001.html
@@ -0,0 +1,10 @@ +<!doctype html> +<title>CSS Transforms: Transforms are flattened if transform-style is flat.</title> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#3d-rendering-context"> +<link rel="mismatch" href="about:blank"> +<!-- Should see a green rectangle, not white --> +<div style="transform: rotateX(45deg)"> + <div style="transform: rotateX(45deg); background: green; width: 100px; height: 100px"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/META.yml b/third_party/blink/web_tests/external/wpt/css/css-ui/META.yml index e78564bc..7ce4b54 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/META.yml
@@ -4,4 +4,3 @@ - mrego - plinss - svgeesus - - tantek
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/META.yml b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/META.yml index c74fff07..c11da73b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/META.yml
@@ -2,7 +2,6 @@ suggested_reviewers: - kojiishi - fantasai - - myakura - r12a - plinss - upsuper
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/META.yml b/third_party/blink/web_tests/external/wpt/css/selectors/META.yml index 3f86842..8e506d6 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/META.yml +++ b/third_party/blink/web_tests/external/wpt/css/selectors/META.yml
@@ -1,6 +1,5 @@ spec: https://drafts.csswg.org/selectors/ suggested_reviewers: - - tantek - fantasai - frivoal - plinss
diff --git a/third_party/blink/web_tests/external/wpt/device-memory/META.yml b/third_party/blink/web_tests/external/wpt/device-memory/META.yml index b393c6b..b8dd476 100644 --- a/third_party/blink/web_tests/external/wpt/device-memory/META.yml +++ b/third_party/blink/web_tests/external/wpt/device-memory/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/device-memory/ suggested_reviewers: - - tdresser - npm1
diff --git a/third_party/blink/web_tests/external/wpt/encrypted-media/META.yml b/third_party/blink/web_tests/external/wpt/encrypted-media/META.yml index 3168f7d..b09e3b3 100644 --- a/third_party/blink/web_tests/external/wpt/encrypted-media/META.yml +++ b/third_party/blink/web_tests/external/wpt/encrypted-media/META.yml
@@ -1,3 +1,6 @@ spec: https://w3c.github.io/encrypted-media/ suggested_reviewers: - - ddorwin + - cpearce + - joeyparrish + - jrummell-chromium + - jyavenard
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/META.yml b/third_party/blink/web_tests/external/wpt/event-timing/META.yml index feede41d..aa27fb6 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/META.yml +++ b/third_party/blink/web_tests/external/wpt/event-timing/META.yml
@@ -1,4 +1,3 @@ spec: https://github.com/WICG/event-timing suggested_reviewers: - npm1 - - tdresser
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/META.yml b/third_party/blink/web_tests/external/wpt/feature-policy/META.yml index 44ab62c..a4136f7 100644 --- a/third_party/blink/web_tests/external/wpt/feature-policy/META.yml +++ b/third_party/blink/web_tests/external/wpt/feature-policy/META.yml
@@ -1,3 +1,3 @@ spec: https://wicg.github.io/feature-policy/ suggested_reviewers: - - clelland + - bakulf
diff --git a/third_party/blink/web_tests/external/wpt/gamepad/META.yml b/third_party/blink/web_tests/external/wpt/gamepad/META.yml index 5f99b9d..b008a9e 100644 --- a/third_party/blink/web_tests/external/wpt/gamepad/META.yml +++ b/third_party/blink/web_tests/external/wpt/gamepad/META.yml
@@ -1,3 +1,3 @@ spec: https://w3c.github.io/gamepad/ suggested_reviewers: - - luser + - marcoscaceres
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml b/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml index 1cfe809..bf48f80 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/sensors/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - rakuco - Honry
diff --git a/third_party/blink/web_tests/external/wpt/gyroscope/META.yml b/third_party/blink/web_tests/external/wpt/gyroscope/META.yml index 67f22d53..6a48535 100644 --- a/third_party/blink/web_tests/external/wpt/gyroscope/META.yml +++ b/third_party/blink/web_tests/external/wpt/gyroscope/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/gyroscope/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml b/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml index 706dbdf8..3dd015f 100644 --- a/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml +++ b/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/html-media-capture/ suggested_reviewers: - - haoxli - zqzhang
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/document-attribute.window.js b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/document-attribute.window.js new file mode 100644 index 0000000..f13acdb8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/document-attribute.window.js
@@ -0,0 +1,15 @@ +async_test(t => { + const frame = document.createElement("iframe"); + frame.onload = t.step_func(() => { + const frameW = frame.contentWindow, + frameD = frame.contentDocument; + assert_equals(frameW.document, frameD); + frame.remove(); + assert_equals(frameW.document, frameD); + t.step_timeout(() => { + assert_equals(frameW.document, frameD); + t.done(); + }, 100); + }); + document.body.append(frame); +}, "Window object's document IDL attribute and discarding the browsing context");
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/self-et-al.window.js b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/self-et-al.window.js new file mode 100644 index 0000000..1b0fa121 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/self-et-al.window.js
@@ -0,0 +1,43 @@ +function delayed_assert_done(t, w, windowProxySelfReference) { + // Let's make sure nobody is being sneaky + t.step_timeout(() => { + t.step_timeout(() => { + assert_equals(w[windowProxySelfReference], w, `${windowProxySelfReference} got cleared after some time`); + t.done(); + }, 0); + }, 0); +} + +[ + "frames", + "globalThis", + "self", + "window" +].forEach(windowProxySelfReference => { + async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")), + otherW = frame.contentWindow; + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} is broken`); + frame.remove(); + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context removal`); + assert_true(otherW.closed); + + delayed_assert_done(t, otherW, windowProxySelfReference); + }, `iframeWindow.${windowProxySelfReference} before and after removal`); + + async_test(t => { + const otherW = window.open(); + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} is broken`); + otherW.onunload = t.step_func(() => { + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context unload`); + t.step_timeout(() => { + assert_equals(otherW.opener, null); // Ensure browsing context is discarded + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context removal`); + delayed_assert_done(t, otherW, windowProxySelfReference); + }, 0); + }); + otherW.close(); + assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context closure`); + assert_true(otherW.closed); + }, `popupWindow.${windowProxySelfReference} before, after closing, and after discarding`) +});
diff --git a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/META.yml b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/META.yml index f6a06f4..4239a85 100644 --- a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/META.yml +++ b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/META.yml
@@ -3,5 +3,4 @@ - AmeliaBR - annevk - kenrussell - - jdashg - fserb
diff --git a/third_party/blink/web_tests/external/wpt/lint.whitelist b/third_party/blink/web_tests/external/wpt/lint.whitelist index 11b75562..12b3212 100644 --- a/third_party/blink/web_tests/external/wpt/lint.whitelist +++ b/third_party/blink/web_tests/external/wpt/lint.whitelist
@@ -187,6 +187,8 @@ SET TIMEOUT: payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html SET TIMEOUT: preload/single-download-preload.html SET TIMEOUT: resize-observer/resources/iframe.html +SET TIMEOUT: resource-timing/resources/iframe-TAO* +SET TIMEOUT: resource-timing/resources/nested-contexts.js SET TIMEOUT: screen-orientation/onchange-event.html SET TIMEOUT: secure-contexts/basic-popup-and-iframe-tests.https.js SET TIMEOUT: service-workers/cache-storage/script-tests/cache-abort.js
diff --git a/third_party/blink/web_tests/external/wpt/magnetometer/META.yml b/third_party/blink/web_tests/external/wpt/magnetometer/META.yml index 88b900c..d7d395e 100644 --- a/third_party/blink/web_tests/external/wpt/magnetometer/META.yml +++ b/third_party/blink/web_tests/external/wpt/magnetometer/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/magnetometer/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html index c703edb..d4be8ea 100644 --- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html
@@ -16,23 +16,26 @@ </style> </head> <body> - <p>This test passes if you see fractions with line thickness equal to the height of their blue numerator and cyan denominator.</p> + <p>This test passes if you see the same fraction four times.</p> <math> - <mfrac linethickness="5px"> - <mspace width="20px" height="5px" style="background: blue"></mspace> - <mspace width="20px" height="5px" style="background: cyan"></mspace> - </mfrac> - <mfrac linethickness="10px"> + <mfrac> <mspace width="20px" height="10px" style="background: blue"></mspace> <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> - <mfrac linethickness="20px"> - <mspace width="20px" height="20px" style="background: blue"></mspace> - <mspace width="20px" height="20px" style="background: cyan"></mspace> + <mspace width="20px"/> + <mfrac> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> - <mfrac linethickness="50px"> - <mspace width="20px" height="50px" style="background: blue"></mspace> - <mspace width="20px" height="50px" style="background: cyan"></mspace> + <mspace width="20px"/> + <mfrac> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + <mspace width="20px"/> + <mfrac> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> </math> </body>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html index 83e15c8..eca8287 100644 --- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html
@@ -4,7 +4,7 @@ <meta charset="utf-8"> <title>fractions linethickness</title> <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#mfrac"> - <meta name="assert" content="Verifies 'thin', 'medium', 'thick' and unitless values for the linethickness attribute of the mfrac element"> + <meta name="assert" content="Verifies deprecated 'thin', 'medium', 'thick' and unitless values have no effect on the linethickness of the mfrac element"> <link rel="match" href="frac-linethickness-001-ref.html"> <style type="text/css"> @font-face { @@ -19,23 +19,26 @@ </style> </head> <body> - <p>This test passes if you see fractions with line thickness equal to the height of their blue numerator and cyan denominator.</p> + <p>This test passes if you see the same fraction four times.</p> <math> <mfrac linethickness="thin"> - <mspace width="20px" height="5px" style="background: blue"></mspace> - <mspace width="20px" height="5px" style="background: cyan"></mspace> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> + <mspace width="20px"/> <mfrac linethickness="medium"> <mspace width="20px" height="10px" style="background: blue"></mspace> <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> + <mspace width="20px"/> <mfrac linethickness="thick"> - <mspace width="20px" height="20px" style="background: blue"></mspace> - <mspace width="20px" height="20px" style="background: cyan"></mspace> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> + <mspace width="20px"/> <mfrac linethickness="5"> - <mspace width="20px" height="50px" style="background: blue"></mspace> - <mspace width="20px" height="50px" style="background: cyan"></mspace> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> </math> </body>
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-depth/META.yml b/third_party/blink/web_tests/external/wpt/mediacapture-depth/META.yml index e083c9b..4346120 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-depth/META.yml +++ b/third_party/blink/web_tests/external/wpt/mediacapture-depth/META.yml
@@ -3,4 +3,3 @@ - anssiko - Honry - robman - - astojilj
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/META.yml b/third_party/blink/web_tests/external/wpt/mediacapture-streams/META.yml index 1ed650e..960dc3a5 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/META.yml +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/META.yml
@@ -2,7 +2,5 @@ suggested_reviewers: - agouaillard - alvestrand - - dontcallmedom - - eric-carlson - youennf - jan-ivar
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html new file mode 100644 index 0000000..c0dd249 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_redirect_chain_xserver_partial_opt_in.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <title>Navigation Timing 2 WPT</title> + <link rel="author" title="Google" href="http://www.google.com/" /> + <link rel="help" href="http://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> + <script> + + function verifyTimingEventOrder(eventOrder, timingEntry) { + for (let i = 0; i < eventOrder.length - 1; i++) { + assert_true(timingEntry[eventOrder[i]] < timingEntry[eventOrder[i + 1]], + "Expected " + eventOrder[i] + " to be no greater than " + eventOrder[i + 1] + "."); + } + } + + function onload_test() + { + const frame_performance = document.getElementById("frameContext").contentWindow.performance; + assert_equals(frame_performance.getEntriesByType("navigation")[0].type, + "navigate", + "Expected navigation type to be navigate."); + assert_equals(frame_performance.getEntriesByType("navigation")[0].redirectCount, 0, + "Expected redirectCount to be 0."); + assert_equals(frame_performance.getEntriesByType("navigation")[0].redirectStart, 0, + "Expected redirectStart to be 0."); + assert_equals(frame_performance.getEntriesByType("navigation")[0].redirectEnd, 0, + "Expected redirectEnd to be 0."); + done(); + } + </script> + + </head> + <body> + <h1>Description</h1> + <p>This test validates the values of the window.performance.getEntriesByType("navigation")[0].redirectCount and the + window.performance.getEntriesByType("navigation")[0].redirectStart/End times for a cross-origin server side redirect navigation when the redirect chooses to opt-in.</p> + + <iframe id="frameContext" src="" style="width: 250px; height: 250px;"></iframe> + <script> + // combine the page origin and redirect origin into the IFRAME's src URL + const destUrl_first = make_absolute_url({subdomain: "www", + path: "/common/redirect-opt-in.py", + query: "location=" + make_absolute_url( + {path: "/navigation-timing/resources/blank_page_green.html"}) + }); + const destUrl = make_absolute_url({subdomain: "www", + path: "/common/redirect.py", + query: "location=" + destUrl_first}); + let frameContext = document.getElementById("frameContext"); + frameContext.onload = onload_test; + frameContext.src = destUrl; + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html new file mode 100644 index 0000000..0b39786 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_chain_partial_opt_in.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <title>Navigation Timing 2 WPT</title> + <link rel="author" title="Google" href="http://www.google.com/" /> + <link rel="help" href="http://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> + <script> + + let reload_frame; + + function onload_test() + { + reload_frame = document.getElementById("frameContext"); + reload_frame.onload = do_test; + setTimeout("reload_the_frame();", 100); + } + + function reload_the_frame() + { + const destUrl_first = make_absolute_url({subdomain: "www", + path: "/common/redirect-opt-in.py", + query: "location=" + make_absolute_url( + {path: "/navigation-timing/resources/blank_page_yellow.html"}) + }); + const destUrl = make_absolute_url({subdomain: "www", + path: "/common/redirect.py", + query: "location=" + destUrl_first + }); + reload_frame.contentWindow.location.href = destUrl; + } + + function do_test() + { + const newNavTiming = document.getElementById("frameContext").contentWindow.performance.getEntriesByType("navigation")[0]; + assert_equals(newNavTiming.type, "navigate", "Expected navigation type to be navigate."); + assert_equals(newNavTiming.unloadEventStart, 0, "Expected unloadEventStart to be 0."); + assert_equals(newNavTiming.unloadEventEnd, 0, "Expected unloadEventEnd to be 0."); + done(); + } + </script> + </head> + <body> + <h1>Description</h1> + <p>This test validates the value of window.performance.getEntriesByType("navigation")[0].(type/unloadEventEnd/unloadEventStart) with a reloaded navigation.</p> + + <p>This page should be loaded with a green background frame below. The frame will be automatically reloaded + and then verified that + <ul> + <li>The window.performance.getEntriesByType("navigation").type = "navigate"</li> + <li>The window.performance.getEntriesByType("navigation").unloadEventStart == 0</li> + <li>The window.performance.getEntriesByType("navigation").unloadEventEnd == 0</li> + </ul> + </p> + + <iframe id="frameContext" onload="onload_test();" src="resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html new file mode 100644 index 0000000..d3ff5508 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/navigation-timing/nav2_test_unloadEvents_with_cross_origin_redirect_opt_in.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <title>Navigation Timing 2 WPT</title> + <link rel="author" title="Google" href="http://www.google.com/" /> + <link rel="help" href="http://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> + <script> + + let reload_frame; + + function onload_test() + { + reload_frame = document.getElementById("frameContext"); + reload_frame.onload = do_test; + setTimeout("reload_the_frame();", 100); + } + + function reload_the_frame() + { + const destUrl = make_absolute_url({subdomain: "www", + path: "/common/redirect-opt-in.py", + query: "location=" + make_absolute_url( + {path: "/navigation-timing/resources/blank_page_yellow.html"}) + }); + reload_frame.contentWindow.location.href = destUrl; + } + + function do_test() + { + const newNavTiming = document.getElementById("frameContext").contentWindow.performance.getEntriesByType("navigation")[0]; + assert_equals(newNavTiming.type, "navigate", "Expected navigation type to be navigate."); + assert_not_equals(newNavTiming.unloadEventStart, 0, "Expected unloadEventStart to not be 0."); + assert_not_equals(newNavTiming.unloadEventEnd, 0, "Expected unloadEventEnd to not be 0."); + done(); + } + </script> + </head> + <body> + <h1>Description</h1> + <p>This test validates the value of window.performance.getEntriesByType("navigation")[0].(type/unloadEventEnd/unloadEventStart) with a reloaded navigation.</p> + + <p>This page should be loaded with a green background frame below. The frame will be automatically reloaded + and then verified that + <ul> + <li>The window.performance.getEntriesByType("navigation").type = "navigate"</li> + <li>The window.performance.getEntriesByType("navigation").unloadEventStart == 0</li> + <li>The window.performance.getEntriesByType("navigation").unloadEventEnd == 0</li> + </ul> + </p> + + <iframe id="frameContext" onload="onload_test();" src="resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/notifications/META.yml b/third_party/blink/web_tests/external/wpt/notifications/META.yml index 2cb7972..0daa86e 100644 --- a/third_party/blink/web_tests/external/wpt/notifications/META.yml +++ b/third_party/blink/web_tests/external/wpt/notifications/META.yml
@@ -1,4 +1,3 @@ spec: https://notifications.spec.whatwg.org/ suggested_reviewers: - sideshowbarker - - ibelem
diff --git a/third_party/blink/web_tests/external/wpt/offscreen-canvas/META.yml b/third_party/blink/web_tests/external/wpt/offscreen-canvas/META.yml index bcb30ed..d3e4c38 100644 --- a/third_party/blink/web_tests/external/wpt/offscreen-canvas/META.yml +++ b/third_party/blink/web_tests/external/wpt/offscreen-canvas/META.yml
@@ -3,5 +3,4 @@ - AmeliaBR - annevk - kenrussell - - jdashg - fserb
diff --git a/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml b/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml index 99d61666..4273858 100644 --- a/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml +++ b/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml
@@ -1,7 +1,6 @@ spec: https://w3c.github.io/orientation-sensor/ suggested_reviewers: - zqzhang - - dontcallmedom - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/paint-timing/META.yml b/third_party/blink/web_tests/external/wpt/paint-timing/META.yml index 24acb25..1892a41e 100644 --- a/third_party/blink/web_tests/external/wpt/paint-timing/META.yml +++ b/third_party/blink/web_tests/external/wpt/paint-timing/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/paint-timing/ suggested_reviewers: - spanicker - - tdresser
diff --git a/third_party/blink/web_tests/external/wpt/payment-method-id/META.yml b/third_party/blink/web_tests/external/wpt/payment-method-id/META.yml index e0931f4..5e9fe05a 100644 --- a/third_party/blink/web_tests/external/wpt/payment-method-id/META.yml +++ b/third_party/blink/web_tests/external/wpt/payment-method-id/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/payment-method-id/ suggested_reviewers: - - alphan102 - marcoscaceres
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html index 45f3f0a5..226fd88 100644 --- a/third_party/blink/web_tests/external/wpt/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html
@@ -72,6 +72,7 @@ city: 'Chapel Hill', dependentLocality: '', postalCode: '6095', + region: 'QLD', sortingCode: '', organization: 'w3c', recipient: 'web platform test',
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html index c8dd926..f3f3f76 100644 --- a/third_party/blink/web_tests/external/wpt/payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html
@@ -16,7 +16,14 @@ await response.retry({ error }); const event = await eventPromise; assert_true(event instanceof PaymentRequestUpdateEvent); - for(const [prop, value] of Object.entries(expected)){ + for([prop, value] of Object.entries(expected)){ + if (prop === 'payerPhone') { + // |payerPhone| may optionally adhere to E164 structure, which does not + // contain formatting, e.g. +180000000 instead of +1-800-000-0000. + // Strip out the formatting in case the user agent implements E164. + // https://w3c.github.io/payment-request/#addressinit-dictionary + value = value.replace(/[-\(\) ]/g, ''); + } assert_equals(response[prop], value); } await response.complete("success"); @@ -52,7 +59,7 @@ <p> Change payer's phone to "+1-800-000-0000". </p> - <button onclick="runTest(this, {requestPayerPhone: true}, { payerPhone: '+1-800-000-0000' })"> + <button onclick="runTest(this, {requestPayerPhone: true}, { payerPhone: '+18000000000' })"> PaymentRequestUpdateEvent is dispatched when payer phone changes. </button> </li>
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/show-method-postmessage-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-request/show-method-postmessage-manual.https.html index 05fce4f..920e0a99 100644 --- a/third_party/blink/web_tests/external/wpt/payment-request/show-method-postmessage-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/payment-request/show-method-postmessage-manual.https.html
@@ -12,43 +12,6 @@ allow_uncaught_exception: true, }); -const defaultMethods = Object.freeze([ - { supportedMethods: "basic-card" }, - { - supportedMethods: "https://apple.com/apple-pay", - data: { - version: 3, - merchantIdentifier: "merchant.com.example", - countryCode: "US", - merchantCapabilities: ["supports3DS"], - supportedNetworks: ["visa"], - } - }, -]); - -const defaultDetails = Object.freeze({ - id: "fail", - total: { - label: "Total", - amount: { - currency: "USD", - value: "1.00", - }, - }, -}); - -test(() => { - assert_throws( - "SecurityError", - () => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - request.show(); // <--- should throw here - request.abort(); - }, - "throws a SecurityError if not triggered by user activation" - ); -}); - async function runUserActivation(button) { button.disabled = true; const { contentWindow: iframeWindow } = document.getElementById("iframe");
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/META.yml b/third_party/blink/web_tests/external/wpt/pointerevents/META.yml index be61ddd..1962feaf 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/META.yml +++ b/third_party/blink/web_tests/external/wpt/pointerevents/META.yml
@@ -1,8 +1,6 @@ spec: https://w3c.github.io/pointerevents/ suggested_reviewers: - Steditor - - jacobrossi - plehegar - - scottgonzalez - RByers - NavidZ
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/META.yml b/third_party/blink/web_tests/external/wpt/referrer-policy/META.yml index a622289..8ead043 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/META.yml +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/META.yml
@@ -1,5 +1,3 @@ spec: https://w3c.github.io/webappsec-referrer-policy/ suggested_reviewers: - - estark37 - - jeisinger - domfarolino
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/META.yml b/third_party/blink/web_tests/external/wpt/resource-timing/META.yml index a2ce7c48..76176970 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/META.yml +++ b/third_party/blink/web_tests/external/wpt/resource-timing/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/resource-timing/ suggested_reviewers: - - haoxli - plehegar - zqzhang - igrigorik
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/TAO-crossorigin-port.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/TAO-crossorigin-port.sub.html new file mode 100644 index 0000000..0601217 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/TAO-crossorigin-port.sub.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing TAO - "null" and opaque origin</title> +<link rel="author" title="Google" href="http://www.google.com/" /> +<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#timing-allow-origin"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +const t = async_test("Makes sure that the iframe passed the test and had an entry which passed the timing allow check"); +window.addEventListener("message", t.step_func_done(e=>{ + assert_equals(e.data, "PASS"); +})); +</script> +</head> +<body> +<h1>Description</h1> +<p>This test validates that for a cross origin resource with different ports, the timing allow check algorithm will fail when the value of Timing-Allow-Origin value has the right host but the wrong port in it.</p> +<div id="log"></div> +<!-- The frame is being requested on the default port ([0]), while the subresource in it will be requested on a separate port ([1]) --> +<iframe id="frameContext" src="{{location[scheme]}}://{{host}}:{{ports[http][0]}}/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations.html b/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations.html new file mode 100644 index 0000000..483cc5b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<meta name=timeout content=long> +<title>Resource Timing embed navigate - back button navigation</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/nested-contexts.js"></script> +<script> + open_test_window("resources/embed-navigate-back.html", "Test that embed navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/embed-navigate-back.html?crossorigin", "Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/embed-navigate.html", "Test that embed navigations are not observable by the parent"); + open_test_window("resources/embed-navigate.html?crossorigin", "Test that crossorigin embed navigations are not observable by the parent"); + open_test_window("resources/embed-refresh.html", "Test that embed refreshes are not observable by the parent"); + open_test_window("resources/embed-refresh.html?crossorigin", "Test that crossorigin embed refreshes are not observable by the parent"); + open_test_window("resources/iframe-navigate-back.html", "Test that iframe navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/iframe-navigate-back.html?crossorigin", "Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/iframe-navigate.html", "Test that iframe navigations are not observable by the parent"); + open_test_window("resources/iframe-navigate.html?crossorigin", "Test that crossorigin iframe navigations are not observable by the parent"); + open_test_window("resources/iframe-refresh.html", "Test that iframe refreshes are not observable by the parent"); + open_test_window("resources/iframe-refresh.html?crossorigin", "Test that crossorigin iframe refreshes are not observable by the parent"); + open_test_window("resources/object-navigate-back.html", "Test that object navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/object-navigate-back.html?crossorigin", "Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent"); + open_test_window("resources/object-navigate.html", "Test that object navigations are not observable by the parent"); + open_test_window("resources/object-navigate.html?crossorigin", "Test that crossorigin object navigations are not observable by the parent"); + open_test_window("resources/object-refresh.html", "Test that object refreshes are not observable by the parent"); + open_test_window("resources/object-refresh.html?crossorigin", "Test that crossorigin object refreshes are not observable by the parent"); +</script> +
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/TAOResponse.py b/third_party/blink/web_tests/external/wpt/resource-timing/resources/TAOResponse.py index fefc75b7..d98098c 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/TAOResponse.py +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/TAOResponse.py
@@ -16,6 +16,12 @@ elif tao == 'origin': # case-sensitive match for origin, pass response.headers.set('Timing-Allow-Origin', origin) + elif tao.startswith('origin_port'): + # case-sensitive match for origin and port, pass + origin_parts = origin.split(':') + host = origin_parts[0] + ':' + origin_parts[1] + port = tao.split('origin_port_')[1] + response.headers.set('Timing-Allow-Origin', host + ':' + port) elif tao == 'space': # space separated list of origin and wildcard, fail response.headers.set('Timing-Allow-Origin', (origin + ' *'))
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-navigated.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-navigated.html new file mode 100644 index 0000000..fa87355 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-navigated.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +</head> +<body> + navigated document! +<script> + top.postMessage("navigated", "*"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-refreshed.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-refreshed.html new file mode 100644 index 0000000..7e4ca09 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-refreshed.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +</head> +<body> + Refreshed document! +<script> + top.postMessage("refreshed", "*"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-navigates.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-navigates.html new file mode 100644 index 0000000..cb567bf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-navigates.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +</head> +<body> +<script> + location.href="document-navigated.html"; +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-refreshes.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-refreshes.html new file mode 100644 index 0000000..7552278 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/document-that-refreshes.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<meta http-equiv="refresh" content="0;document-refreshed.html"> +</head> +<body></body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate-back.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate-back.html new file mode 100644 index 0000000..3c3def1d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate-back.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing embed navigate - back button navigation</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> +setup_back_navigation("embed-navigate-back.html"); +</script> +<embed type="text/html"> +<script> + document.getElementsByTagName("embed")[0].src = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate.html new file mode 100644 index 0000000..20a73c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-navigate.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing embed navigate</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_navigate_test(); +</script> +<div id=log></div> +<embed type="text/html"> +<script> + document.getElementsByTagName("embed")[0].src = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-refresh.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-refresh.html new file mode 100644 index 0000000..4a49fd0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/embed-refresh.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing embed refresh</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_refresh_test(); +</script> +<div id=log></div> +<embed type="text/html"> +<script> + document.getElementsByTagName("embed")[0].src = pre_refresh_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html new file mode 100644 index 0000000..39f5d13 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<body> +<script> + const url = '{{location[scheme]}}://{{host}}:{{ports[http][1]}}/resource-timing/resources/TAOResponse.py?tao=origin_port_{{ports[http][1]}}'; + const observe = (list, observer) => { + const entry = list.getEntries()[0]; + const sum = entry.redirectStart + + entry.redirectEnd + + entry.domainLookupStart + + entry.domainLookupEnd + + entry.connectStart + + entry.connectEnd + + entry.secureConnectionStart + + entry.requestStart + + entry.responseStart + + entry.transferSize + + entry.encodedBodySize + + entry.decodedBodySize; + + const result = sum == 0 ? 'PASS' : 'FAIL'; + window.top.postMessage(result, '*'); + } + let observer = new PerformanceObserver(observe); + observer.observe({ entryTypes: ["resource"] }); + fetch(url); +</script> +</body> +</html> + +
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate-back.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate-back.html new file mode 100644 index 0000000..c5c1fc1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate-back.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing iframe navigate - back button navigation</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> +setup_back_navigation("iframe-navigate-back.html"); +</script> +<iframe></iframe> +<script> + document.getElementsByTagName("iframe")[0].src = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate.html new file mode 100644 index 0000000..2a1a7e0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-navigate.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing iframe navigate</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_navigate_test(); +</script> +<div id=log></div> +<iframe></iframe> +<script> + document.getElementsByTagName("iframe")[0].src = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-refresh.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-refresh.html new file mode 100644 index 0000000..4ce3ea0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/iframe-refresh.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing iframe refresh</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_refresh_test(); +</script> +<div id=log></div> +<iframe></iframe> +<script> + document.getElementsByTagName("iframe")[0].src = pre_refresh_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/navigate_back.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/navigate_back.html new file mode 100644 index 0000000..345eee1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/navigate_back.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<script> +window.onload = function() {history.back();} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/nested-contexts.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/nested-contexts.js new file mode 100644 index 0000000..0c20224 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/nested-contexts.js
@@ -0,0 +1,95 @@ +let destination = location; +if (location.search == "?crossorigin") { + const host_info = get_host_info() + destination = location.protocol + "//" + host_info["REMOTE_HOST"] + ":" + location.port; +} + +const pre_navigate_url = new URL("/resource-timing/resources/document-that-navigates.html", destination).href; +const post_navigate_url = new URL("/resource-timing/resources/document-navigated.html", destination).href; +const pre_refresh_url = new URL("/resource-timing/resources/document-that-refreshes.html", destination).href; +const post_refresh_url = new URL("/resource-timing/resources/document-refreshed.html", destination).href; + +function setup_navigate_or_refresh(type, pre, post) { + function verify_document_navigate_not_observable() { + let entries = performance.getEntriesByType("resource"); + let found_first_document = false; + for (entry of entries) { + if (entry.name == pre) { + found_first_document = true; + } + if (entry.name == post) { + opener.postMessage("FAIL - " + type + " document should not be observable", "*"); + return; + } + } + if (!found_first_document) { + opener.postMessage("FAIL - initial document should be observable", "*"); + return; + } + opener.postMessage("PASS", "*"); + } + window.addEventListener("message", e=>{ + if (e.data == type) { + verify_document_navigate_not_observable(); + } + }); +} + +function setup_navigate_test() { + setup_navigate_or_refresh("navigated", pre_navigate_url, post_navigate_url); +} + +function setup_refresh_test() { + setup_navigate_or_refresh("refreshed", pre_refresh_url, post_refresh_url); +} + +function setup_back_navigation(pushed_url) { + function verify_document_navigate_not_observable() { + let entries = performance.getEntriesByType("resource"); + let found_first_document = false; + for (entry of entries) { + if (entry.name == pre_navigate_url) { + found_first_document = true; + } + if (entry.name == post_navigate_url) { + opener.postMessage("FAIL - navigated document exposed", "*"); + return; + } + } + if (!found_first_document) { + opener.postMessage("FAIL - first document not exposed", "*"); + return; + } + opener.postMessage("PASS", "*"); + } + window.addEventListener("message", e=>{ + if (e.data == "navigated") { + if (sessionStorage.navigated) { + delete sessionStorage.navigated; + verify_document_navigate_not_observable(); + } else { + sessionStorage.navigated = true; + setTimeout(() => { + history.pushState({}, "", pushed_url); + location.href="navigate_back.html"; + }, 0); + } + } + }); +} + +function open_test_window(url, message) { + promise_test(() => { + return new Promise((resolve, reject) => { + let openee = window.open(url); + addEventListener("message", e => { + openee.close(); + if (e.data == "PASS") { + resolve(); + } else { + reject(e.data); + } + }); + }); + }, message); +}
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate-back.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate-back.html new file mode 100644 index 0000000..64e5f58 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate-back.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing object navigate - back button navigation</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> +setup_back_navigation("object-navigate-back.html"); +</script> +<object></object> +<script> + document.getElementsByTagName("object")[0].data = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate.html new file mode 100644 index 0000000..cbb862e7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-navigate.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing object navigate</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_navigate_test(); +</script> +<div id=log></div> +<object></object> +<script> + document.getElementsByTagName("object")[0].data = pre_navigate_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-refresh.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-refresh.html new file mode 100644 index 0000000..b14cf7f1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-refresh.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing object refresh</title> +<script src="/common/get-host-info.sub.js"></script> +<script src="nested-contexts.js"></script> +<script> + setup_refresh_test(); +</script> +<div id=log></div> +<object></object> +<script> + document.getElementsByTagName("object")[0].data = pre_refresh_url; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml b/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml index dc3f290..3ddb3b0 100644 --- a/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml +++ b/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/screen-orientation/ suggested_reviewers: - - haoxli - marcoscaceres
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check-expected.txt b/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check-expected.txt new file mode 100644 index 0000000..b4d17d2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL lock-unlock-check Uncaught SyntaxError: Unexpected token { +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check.html b/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check.html new file mode 100644 index 0000000..129882d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen-orientation/lock-unlock-check.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> + import { getOppositeOrientation } from "/screen-orientation/resources/orientation-utils.js"; + promise_test(async t => { + await test_driver.bless("request full screen", () => { + return document.documentElement.requestFullscreen(); + }); + const newOrientation = getOppositeOrientation(); + // This will reject, because the event will call lock() again. + const pMustReject = screen.orientation.lock(newOrientation); + // This one resolves, because we are re-locking. + const pMustResolve = new Promise(r => { + screen.orientation.onchange = () => { + r(orientation.lock("any")); + }; + }); + await promise_rejects(t, new TypeError(), pMustReject); + await pMustResolve; + screen.orientation.unlock(); + return document.exitFullscreen(); + }, "Re-locking orientation during event dispatch must reject existing orientationPendingPromise"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/resources/orientation-utils.js b/third_party/blink/web_tests/external/wpt/screen-orientation/resources/orientation-utils.js new file mode 100644 index 0000000..8721818b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen-orientation/resources/orientation-utils.js
@@ -0,0 +1,17 @@ +export async function loadIframe(src = "/screen-orientation/resources/blank.html") { + const iframe = document.createElement("iframe"); + iframe.src = src; + document.body.appendChild(iframe); + return new Promise(r => { + if (iframe.contentDocument.readyState === "complete") { + return r(iframe); + } + iframe.onload = () => r(iframe); + }); +} + +export function getOppositeOrientation() { + const { type: currentOrientation } = screen.orientation; + const isPortrait = currentOrientation.includes("portrait"); + return (newOrientation = `${isPortrait ? "landscape" : "portrait"}`); +}
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/META.yml b/third_party/blink/web_tests/external/wpt/scroll-animations/META.yml index 20f3c7e6..c53f1f432 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/META.yml +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/META.yml
@@ -1,6 +1,5 @@ spec: https://wicg.github.io/scroll-animations/ suggested_reviewers: - birtles - - theres-waldo - graouts - stephenmcgruer
diff --git a/third_party/blink/web_tests/external/wpt/selection/Document-open-expected.txt b/third_party/blink/web_tests/external/wpt/selection/Document-open-expected.txt new file mode 100644 index 0000000..eaa85d4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/selection/Document-open-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Selection must not be replaced with a new object after document.open() assert_equals: After document.open(), the Selection object must be the same expected object "" but got object "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/selection/Document-open.html b/third_party/blink/web_tests/external/wpt/selection/Document-open.html index 9d17091..9e3cb28 100644 --- a/third_party/blink/web_tests/external/wpt/selection/Document-open.html +++ b/third_party/blink/web_tests/external/wpt/selection/Document-open.html
@@ -6,39 +6,23 @@ <script> "use strict"; -// This tests the HTML spec requirement "Replace the Document's singleton -// objects with new instances of those objects. (This includes in particular -// the Window, Location, History, ApplicationCache, and Navigator, objects, the -// various BarProp objects, the two Storage objects, the various HTMLCollection -// objects, and objects defined by other specifications, like Selection and the -// document's UndoManager. It also includes all the Web IDL prototypes in the -// JavaScript binding, including the Document object's prototype.)" in the -// document.open() algorithm. +const iframe = document.createElement("iframe"); +async_test(t => { + iframe.onload = t.step_func_done(() => { + const originalSelection = iframe.contentWindow.getSelection(); + assert_equals(originalSelection.rangeCount, 0, "rangeCount must initially be 0"); + iframe.contentDocument.body.appendChild(iframe.contentDocument.createTextNode("foo")); + const range = iframe.contentDocument.createRange(); + range.selectNodeContents(iframe.contentDocument.body); + iframe.contentWindow.getSelection().addRange(range); + assert_equals(originalSelection.rangeCount, 1, "rangeCount must be 1 after adding a range"); -var iframe = document.createElement("iframe"); -var t = async_test("Selection must be replaced with a new object after document.open()"); -iframe.onload = function() { - t.step(function() { - var originalSelection = iframe.contentWindow.getSelection(); - assert_equals(originalSelection.rangeCount, 0, - "Sanity check: rangeCount must be initially 0"); - iframe.contentDocument.body.appendChild( - iframe.contentDocument.createTextNode("foo")); - var range = iframe.contentDocument.createRange(); - range.selectNodeContents(iframe.contentDocument.body); - iframe.contentWindow.getSelection().addRange(range); - assert_equals(originalSelection.rangeCount, 1, - "Sanity check: rangeCount must be 1 after adding a range"); + iframe.contentDocument.open(); - iframe.contentDocument.open(); - - assert_not_equals(iframe.contentWindow.getSelection(), originalSelection, - "After document.open(), the Selection object must no longer be the same"); - assert_equals(iframe.contentWindow.getSelection().rangeCount, 0, - "After document.open(), rangeCount must be 0 again"); - }); - t.done(); + assert_equals(iframe.contentWindow.getSelection(), originalSelection, "After document.open(), the Selection object must be the same"); + assert_equals(iframe.contentWindow.getSelection().rangeCount, 1, "After document.open(), rangeCount must still be 1"); document.body.removeChild(iframe); -}; -document.body.appendChild(iframe); + }); + document.body.appendChild(iframe); +}, "Selection must not be replaced with a new object after document.open()"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/speech-api/META.yml b/third_party/blink/web_tests/external/wpt/speech-api/META.yml index 4d1b42a..9ce8830 100644 --- a/third_party/blink/web_tests/external/wpt/speech-api/META.yml +++ b/third_party/blink/web_tests/external/wpt/speech-api/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/speech-api/ suggested_reviewers: - foolip - - gshires
diff --git a/third_party/blink/web_tests/external/wpt/streams/META.yml b/third_party/blink/web_tests/external/wpt/streams/META.yml index 108c774..1259a55 100644 --- a/third_party/blink/web_tests/external/wpt/streams/META.yml +++ b/third_party/blink/web_tests/external/wpt/streams/META.yml
@@ -3,6 +3,5 @@ - domenic - yutakahirano - youennf - - calvaris - wanderview - ricea
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/META.yml b/third_party/blink/web_tests/external/wpt/subresource-integrity/META.yml index 2b8891ec..f6980682f 100644 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/META.yml +++ b/third_party/blink/web_tests/external/wpt/subresource-integrity/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/webappsec-subresource-integrity/ suggested_reviewers: - metromoxie - - jonathanKingston - mikewest - hillbrad
diff --git a/third_party/blink/web_tests/external/wpt/svg/META.yml b/third_party/blink/web_tests/external/wpt/svg/META.yml index 09ef583b..2904d6f60 100644 --- a/third_party/blink/web_tests/external/wpt/svg/META.yml +++ b/third_party/blink/web_tests/external/wpt/svg/META.yml
@@ -1,6 +1,5 @@ spec: https://svgwg.org/svg2-draft/ suggested_reviewers: - - heycam - nikosandronikos - boggydigital - ewilligers
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml b/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml index 17fca51..8076bc3 100644 --- a/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml +++ b/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml
@@ -16,7 +16,7 @@ - template: install_safari.yml - template: update_hosts.yml - template: update_manifest.yml -- script: no_proxy='*' ./wpt run --yes --no-pause --no-fail-on-unexpected --no-restart-on-unexpected --affected ${{ parameters.affectedRange }} --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report.json --channel preview safari +- script: no_proxy='*' ./wpt run --yes --no-pause --no-fail-on-unexpected --no-restart-on-unexpected --affected ${{ parameters.affectedRange }} --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report.json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot.txt --channel preview safari displayName: 'Run tests' - task: PublishBuildArtifacts@1 displayName: 'Publish results'
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/taskcluster-run.py b/third_party/blink/web_tests/external/wpt/tools/ci/taskcluster-run.py index 78c50a6..fbd2f2ab 100755 --- a/third_party/blink/web_tests/external/wpt/tools/ci/taskcluster-run.py +++ b/third_party/blink/web_tests/external/wpt/tools/ci/taskcluster-run.py
@@ -19,6 +19,12 @@ return parser.parse_known_args(args)[0].log_wptreport +def find_wptscreenshot(args): + parser = argparse.ArgumentParser() + parser.add_argument('--log-wptscreenshot', action='store') + return parser.parse_known_args(args)[0].log_wptscreenshot + + def gzip_file(filename, delete_original=True): with open(filename, 'rb') as f_in: with gzip.open('%s.gz' % filename, 'wb') as f_out: @@ -72,6 +78,9 @@ wptreport = find_wptreport(wpt_args) if wptreport: gzip_file(wptreport) + wptscreenshot = find_wptscreenshot(wpt_args) + if wptscreenshot: + gzip_file(wptscreenshot) if __name__ == "__main__":
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py index 7640136..dc57c24d 100644 --- a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py +++ b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
@@ -302,9 +302,8 @@ elif is_new or hash_changed: self._data[new_type][rel_path] = set(manifest_items) - self._path_hash[rel_path] = (file_hash, new_type) - if is_new or hash_changed: + self._path_hash[rel_path] = (file_hash, new_type) changed = True deleted = prev_files - seen_files
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py index df34e59..a19851d1 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py +++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -277,8 +277,6 @@ if kwargs["browser_channel"] == "dev": logger.info("Automatically turning on experimental features for Chrome Dev") kwargs["binary_args"].append("--enable-experimental-web-platform-features") - # TODO(foolip): remove after unified plan is enabled on Chrome stable - kwargs["binary_args"].append("--enable-features=RTCUnifiedPlanByDefault") # Allow audio autoplay without a user gesture. kwargs["binary_args"].append("--autoplay-policy=no-user-gesture-required")
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/virtualenv.py b/third_party/blink/web_tests/external/wpt/tools/wpt/virtualenv.py index 61de936..357ddcbe 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wpt/virtualenv.py +++ b/third_party/blink/web_tests/external/wpt/tools/wpt/virtualenv.py
@@ -4,6 +4,8 @@ import logging from distutils.spawn import find_executable +import pkg_resources + from tools.wpt.utils import call logger = logging.getLogger(__name__) @@ -16,6 +18,7 @@ self.virtualenv = find_executable("virtualenv") if not self.virtualenv: raise ValueError("virtualenv must be installed and on the PATH") + self._working_set = None @property def exists(self): @@ -24,6 +27,7 @@ def create(self): if os.path.exists(self.path): shutil.rmtree(self.path) + self._working_set = None call(self.virtualenv, self.path, "-p", sys.executable) @property @@ -39,6 +43,22 @@ raise ValueError("pip not found") return path + @property + def lib_path(self): + if sys.platform == 'win32': + return os.path.join(self.path, 'Lib', 'site-packages') + return os.path.join(self.path, 'lib', 'python%s' % sys.version[:3], 'site-packages') + + @property + def working_set(self): + if not self.exists: + raise ValueError("trying to read working_set when venv doesn't exist") + + if self._working_set is None: + self._working_set = pkg_resources.WorkingSet((self.lib_path,)) + + return self._working_set + def activate(self): path = os.path.join(self.bin_path, "activate_this.py") execfile(path, {"__file__": path}) # noqa: F821 @@ -49,11 +69,26 @@ self.activate() def install(self, *requirements): + try: + self.working_set.require(*requirements) + except pkg_resources.ResolutionError: + pass + else: + return + # `--prefer-binary` guards against race conditions when installation # occurs while packages are in the process of being published. call(self.pip_path, "install", "--prefer-binary", *requirements) def install_requirements(self, requirements_path): + with open(requirements_path) as f: + try: + self.working_set.require(f.read()) + except pkg_resources.ResolutionError: + pass + else: + return + # `--prefer-binary` guards against race conditions when installation # occurs while packages are in the process of being published. call(
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt index 6216fb6..f17b12b 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
@@ -2,6 +2,6 @@ mozinfo==0.10 mozlog==4.0 mozdebug==0.1.1 -pillow==5.2.0 +pillow==5.4.1 urllib3[secure]==1.24.1 requests==2.21.0
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt index ee84d840f..668cea3 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt
@@ -1,4 +1,4 @@ -marionette_driver==2.7.0 +marionette_driver==2.8.0 mozprofile==2.2.0 mozprocess==1.0.0 mozcrash==1.1.0
diff --git a/third_party/blink/web_tests/external/wpt/url/META.yml b/third_party/blink/web_tests/external/wpt/url/META.yml index 3a789a0..094b266 100644 --- a/third_party/blink/web_tests/external/wpt/url/META.yml +++ b/third_party/blink/web_tests/external/wpt/url/META.yml
@@ -2,7 +2,6 @@ suggested_reviewers: - mikewest - domenic - - Sebmaster - annevk - GPHemsley - TimothyGu
diff --git a/third_party/blink/web_tests/external/wpt/vibration/META.yml b/third_party/blink/web_tests/external/wpt/vibration/META.yml index 0165889..91cd8c9d 100644 --- a/third_party/blink/web_tests/external/wpt/vibration/META.yml +++ b/third_party/blink/web_tests/external/wpt/vibration/META.yml
@@ -1,4 +1,3 @@ spec: https://w3c.github.io/vibration/ suggested_reviewers: - - dontcallmedom - zqzhang
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/META.yml b/third_party/blink/web_tests/external/wpt/wake-lock/META.yml index a5ff852..7ca3da2 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/META.yml +++ b/third_party/blink/web_tests/external/wpt/wake-lock/META.yml
@@ -1,5 +1,4 @@ spec: https://w3c.github.io/wake-lock/ suggested_reviewers: - - andrey-logvinov - marcoscaceres - Honry
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/META.yml b/third_party/blink/web_tests/external/wpt/webmessaging/META.yml index e70b780b..95d5071 100644 --- a/third_party/blink/web_tests/external/wpt/webmessaging/META.yml +++ b/third_party/blink/web_tests/external/wpt/webmessaging/META.yml
@@ -1,7 +1,6 @@ spec: https://html.spec.whatwg.org/multipage/web-messaging.html suggested_reviewers: - zqzhang - - aogilvie - jdm - mkruisselbrink - annevk
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/META.yml b/third_party/blink/web_tests/external/wpt/webrtc/META.yml index 2025a11..eed4ac834 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/META.yml +++ b/third_party/blink/web_tests/external/wpt/webrtc/META.yml
@@ -3,10 +3,8 @@ - snuggs - agouaillard - alvestrand - - dontcallmedom - guidou - henbos - - phoglund - youennf - rwaldron - jan-ivar
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https.html index 247402b8..c2c4e8e 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https.html
@@ -173,19 +173,18 @@ - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats objects added. */ - promise_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - return getTrackFromUserMedia('audio') - .then(([track, mediaStream]) => { - pc.addTrack(track, mediaStream); + promise_test(async t => { + const pc = createPeerConnectionWithCleanup(t); + const pc2 = createPeerConnectionWithCleanup(t); - return pc.getStats(track) - .then(statsReport => { - validateStatsReport(statsReport); - assert_stats_report_has_stats(statsReport, ['outbound-rtp']); - }); - }); + let [track, mediaStream] = await getTrackFromUserMedia('audio'); + pc.addTrack(track, mediaStream); + exchangeIceCandidates(pc, pc2); + await doSignalingHandshake(pc, pc2); + await listenToIceConnected(pc); + const stats = await pc.getStats(track); + validateStatsReport(stats); + assert_stats_report_has_stats(stats, ['outbound-rtp']); }, `getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats`); @@ -197,16 +196,20 @@ - All stats objects referenced directly or indirectly by the RTCInboundRTPStreamStats added. */ - promise_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - const transceiver = pc.addTransceiver('audio'); + promise_test(async t => { + const pc = createPeerConnectionWithCleanup(t); + const pc2 = createPeerConnectionWithCleanup(t); - return pc.getStats(transceiver.receiver.track) - .then(statsReport => { - validateStatsReport(statsReport); - assert_stats_report_has_stats(statsReport, ['inbound-rtp']); + let [track, mediaStream] = await getTrackFromUserMedia('audio'); + pc.addTrack(track, mediaStream); + exchangeIceCandidates(pc, pc2); + await doSignalingHandshake(pc, pc2); + await new Promise(resolve => { + pc2.getReceivers()[0].track.addEventListener('unmute', resolve); }); + const stats = await pc2.getStats(track); + validateStatsReport(stats); + assert_stats_report_has_stats(stats, ['inbound-rtp']); }, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats`); /*
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt index 0861101..62c3abf 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt
@@ -5,6 +5,6 @@ FAIL Calling addTransceiver() twice should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code PASS negotiationneeded event should not fire if signaling state is not stable -FAIL negotiationneeded event should fire only after signaling state go back to stable assert_unreached: Expect negotiationneeded promise to resolve after pc has set remote answer and go back to stable state Reached unreachable code +FAIL negotiationneeded event should fire only after signaling state go back to stable assert_false: negotiationneeded should not fire until the next iteration of the event loop after returning to stable expected false got true Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html index ac9d70c..f7bf8bd3 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html
@@ -187,22 +187,21 @@ 2. If connection's [[NegotiationNeeded]] slot is false, abort these steps. 3. Fire a simple event named negotiationneeded at connection. */ - promise_test(t => { + promise_test(async t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - return assert_first_promise_fulfill_after_second( - awaitNegotiation(pc), - generateAudioReceiveOnlyOffer(pc) - .then(offer => - pc.setLocalDescription(offer) - .then(() => { - pc.createDataChannel('test'); - return generateAnswer(offer); - })) - .then(answer => pc.setRemoteDescription(answer)), - 'Expect negotiationneeded promise to resolve after pc has set remote answer and go back to stable state'); + pc.addTransceiver('audio'); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + let fired = false; + pc.onnegotiationneeded = e => fired = true; + pc.createDataChannel('test'); + const answer = await generateAnswer(offer); + await pc.setRemoteDescription(answer); + assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after returning to stable"); + await new Promise(resolve => pc.onnegotiationneeded = resolve); }, 'negotiationneeded event should fire only after signaling state go back to stable'); /*
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription.html index 5e9b543..2becbd3 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription.html
@@ -72,29 +72,55 @@ }))); }, 'Calling createOffer() and setLocalDescription() again after one round of local-offer/remote-answer should succeed'); - promise_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); + promise_test(async t => { + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + + const pc2 = new RTCPeerConnection(); + t.add_cleanup(() => pc2.close()); const states = []; - pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState)); + pc1.addEventListener('signalingstatechange', () => states.push(pc1.signalingState)); - return generateDataChannelOffer(pc) - .then(offer => pc.setRemoteDescription(offer)) - .then(() => pc.createAnswer()) - .then(answer => - pc.setLocalDescription(answer) - .then(() => generateVideoReceiveOnlyOffer(pc)) - .then(offer => - pc.setLocalDescription(offer) - .then(() => { - assert_equals(pc.signalingState, 'have-local-offer'); - assert_session_desc_similar(pc.localDescription, offer); - assert_session_desc_similar(pc.currentLocalDescription, answer); - assert_session_desc_similar(pc.pendingLocalDescription, offer); + assert_equals(pc1.localDescription, null); + assert_equals(pc1.currentLocalDescription, null); + assert_equals(pc1.pendingLocalDescription, null); - assert_array_equals(states, ['have-remote-offer', 'stable', 'have-local-offer']); - }))); + pc1.createDataChannel('test'); + const offer = await pc1.createOffer(); + + assert_equals(pc1.localDescription, null); + assert_equals(pc1.currentLocalDescription, null); + assert_equals(pc1.pendingLocalDescription, null); + + await pc1.setLocalDescription(offer); + + assert_session_desc_similar(pc1.localDescription, offer); + assert_equals(pc1.currentLocalDescription, null); + assert_session_desc_similar(pc1.pendingLocalDescription, offer); + + await pc2.setRemoteDescription(offer); + const answer = await pc2.createAnswer(); + await pc2.setLocalDescription(answer); + await pc1.setRemoteDescription(answer); + + assert_equals(pc1.signalingState, 'stable'); + assert_session_desc_similar(pc1.localDescription, offer); + assert_session_desc_similar(pc1.currentLocalDescription, offer); + assert_equals(pc1.pendingLocalDescription, null); + + const stream = await getNoiseStream({audio:true}); + pc2.addTrack(stream.getTracks()[0], stream); + + const reoffer = await pc2.createOffer(); + await pc2.setLocalDescription(reoffer); + await pc1.setRemoteDescription(reoffer); + const reanswer = await pc1.createAnswer(); + await pc1.setLocalDescription(reanswer); + + assert_session_desc_similar(pc1.localDescription, reanswer); + assert_session_desc_similar(pc1.currentLocalDescription, reanswer); + assert_equals(pc1.pendingLocalDescription, null); }, 'Switching role from answerer to offerer after going back to stable state should succeed'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html index f56a170..9b3a9a8 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html
@@ -139,9 +139,13 @@ const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2); assert_true(trackEvent.track instanceof MediaStreamTrack, 'trackEvent.track instanceof MediaStreamTrack'); - assert_equals(trackEvent.track.id, track.id, - 'trackEvent.track.id == track.id'); -}, 'setRemoteDescription(offer): ontrack\'s track.id is the same as track.id'); + assert_equals(trackEvent.streams.length, 1, + 'trackEvent contains a single stream'); + assert_true(trackEvent.streams[0] instanceof MediaStream, + 'trackEvent has a MediaStream'); + assert_equals(trackEvent.streams[0].id, stream.id, + 'trackEvent.streams[0].id == stream.id'); +}, 'setRemoteDescription(offer): ontrack\'s stream.id is the same as stream.id'); promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t);
diff --git a/third_party/blink/web_tests/external/wpt/webstorage/META.yml b/third_party/blink/web_tests/external/wpt/webstorage/META.yml index 0da67a58..020075c3 100644 --- a/third_party/blink/web_tests/external/wpt/webstorage/META.yml +++ b/third_party/blink/web_tests/external/wpt/webstorage/META.yml
@@ -3,5 +3,4 @@ - siusin - inexorabletash - zqzhang - - ibelem - jdm
diff --git a/third_party/blink/web_tests/external/wpt/webxr/META.yml b/third_party/blink/web_tests/external/wpt/webxr/META.yml index b5e3e65a..520afec 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/META.yml +++ b/third_party/blink/web_tests/external/wpt/webxr/META.yml
@@ -1,5 +1,3 @@ spec: https://immersive-web.github.io/webxr/spec/latest/ suggested_reviewers: - - toji - - paezagon - klausw
diff --git a/third_party/blink/web_tests/external/wpt/xhr/META.yml b/third_party/blink/web_tests/external/wpt/xhr/META.yml index 4b2ecf3..c343ceac 100644 --- a/third_party/blink/web_tests/external/wpt/xhr/META.yml +++ b/third_party/blink/web_tests/external/wpt/xhr/META.yml
@@ -2,9 +2,6 @@ suggested_reviewers: - caitp - Manishearth - - jungkees - - ibelem - - mathiasbynens - jdm - annevk - wisniewskit
diff --git a/third_party/blink/web_tests/fast/spatial-navigation/snav-focusless-focused-editable-blocks-movement.html b/third_party/blink/web_tests/fast/spatial-navigation/snav-focusless-focused-editable-blocks-movement.html new file mode 100644 index 0000000..dca44e9 --- /dev/null +++ b/third_party/blink/web_tests/fast/spatial-navigation/snav-focusless-focused-editable-blocks-movement.html
@@ -0,0 +1,89 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="resources/snav-testharness.js"></script> + +<style> + .box { + width: 100px; + height: 30px; + margin: 5px; + border: 1px solid black; + display: inline-block; + } +</style> + +<div class="box" tabindex="0">Top-Left</div> +<div class="box" tabindex="0">Top</div> + +<div class="container"> + <div class="box" tabindex="0">Left</div> + <input class="box" id="input" type="text" value="center"> + <div class="box" tabindex="0">Right</div> +</div> + +<div class="box" tabindex="0">Bottom-Left</div> +<div class="box" tabindex="0">Bottom</div> + +<script> + // This test ensures that when an editable has focus, arrow keys don't cause + // spatial-navigation movement. + let first = document.getElementById("first"); + let second = document.getElementById("second"); + let third = document.getElementById("third"); + + let input = document.getElementById("input"); + + snav.assertSnavEnabledAndTestable(true /* focuslessSpatNav */ ); + + function testDirection(direction, expectMove) { + // We move twice because the first move will be interpreted as an editor + // command while the second will be ignored by the editor. We shouldn't + // move interest in either case. + snav.triggerMove(direction); + snav.triggerMove(direction); + + if (expectMove) { + assert_not_equals( + window.internals.interestedElement, + input, + direction + " key expected to move interest but didn't,"); + } else { + assert_equals( + window.internals.interestedElement, + input, + direction + " key did not expect to move interest but did,"); + } + + // Reset focus so the focused input box starts in a consistent state (fully + // selected) for the next test. + eventSender.keyDown('Escape'); + eventSender.keyDown('Enter'); + } + + test(() => { + // Move interest to editable 'input' box and focus it. + snav.triggerMove('Down'); + snav.triggerMove('Down'); + snav.triggerMove('Right'); + eventSender.keyDown('Enter'); + assert_equals(document.activeElement, input); + assert_equals(window.internals.interestedElement, input); + + // Ensure directional keys don't cause spatial navigation to move interest. + // We move twice because the first move will be interpreted as an editor + // command while the second will be ignored by the editor. We shouldn't + // move interest in either case. + let expectMove = false; + testDirection('Down', expectMove); + testDirection('Left', expectMove); + testDirection('Right', expectMove); + testDirection('Up', expectMove); + + // Ensure removing focus allows movement again. + eventSender.keyDown('Escape'); + + expectMove = true; + testDirection('Down', expectMove); + }, "Enter key moves focus into interested element"); +</script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/profiler/agents-disabled-check-expected.txt b/third_party/blink/web_tests/http/tests/devtools/profiler/agents-disabled-check-expected.txt index 1042f9a..615bad0 100644 --- a/third_party/blink/web_tests/http/tests/devtools/profiler/agents-disabled-check-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/profiler/agents-disabled-check-expected.txt
@@ -3,10 +3,9 @@ --> SDK.targetManager.suspendAllTargets(); frontend: {"id":<number>,"method":"Debugger.disable"} frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":0}} -frontend: {"id":<number>,"method":"Overlay.setPausedInDebuggerMessage"} frontend: {"id":<number>,"method":"DOM.disable"} frontend: {"id":<number>,"method":"CSS.disable"} -frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":true}} +frontend: {"id":<number>,"method":"Overlay.disable"} frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":false,"flatten":true}} --> SDK.targetManager.resumeAllTargets(); @@ -15,7 +14,8 @@ frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":32}} frontend: {"id":<number>,"method":"DOM.enable"} frontend: {"id":<number>,"method":"CSS.enable"} -frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":false}} +frontend: {"id":<number>,"method":"Overlay.enable"} +frontend: {"id":<number>,"method":"Overlay.setShowViewportSizeOnResize","params":{"show":true}} frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":true,"flatten":true}} --> done
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt new file mode 100644 index 0000000..39e546e --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that embed navigations are not observable by the parent +PASS Test that crossorigin embed navigations are not observable by the parent +PASS Test that embed refreshes are not observable by the parent +PASS Test that crossorigin embed refreshes are not observable by the parent +PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that iframe navigations are not observable by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent +PASS Test that iframe refreshes are not observable by the parent +PASS Test that crossorigin iframe refreshes are not observable by the parent +FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +FAIL Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +PASS Test that object navigations are not observable by the parent +PASS Test that crossorigin object navigations are not observable by the parent +PASS Test that object refreshes are not observable by the parent +PASS Test that crossorigin object refreshes are not observable by the parent +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt new file mode 100644 index 0000000..b88a5245 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that embed navigations are not observable by the parent +PASS Test that crossorigin embed navigations are not observable by the parent +PASS Test that embed refreshes are not observable by the parent +PASS Test that crossorigin embed refreshes are not observable by the parent +PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that iframe navigations are not observable by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent +PASS Test that iframe refreshes are not observable by the parent +PASS Test that crossorigin iframe refreshes are not observable by the parent +FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +PASS Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent +PASS Test that object navigations are not observable by the parent +PASS Test that crossorigin object navigations are not observable by the parent +PASS Test that object refreshes are not observable by the parent +PASS Test that crossorigin object refreshes are not observable by the parent +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt new file mode 100644 index 0000000..39e546e --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that embed navigations are not observable by the parent +PASS Test that crossorigin embed navigations are not observable by the parent +PASS Test that embed refreshes are not observable by the parent +PASS Test that crossorigin embed refreshes are not observable by the parent +PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that iframe navigations are not observable by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent +PASS Test that iframe refreshes are not observable by the parent +PASS Test that crossorigin iframe refreshes are not observable by the parent +FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +FAIL Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +PASS Test that object navigations are not observable by the parent +PASS Test that crossorigin object navigations are not observable by the parent +PASS Test that object refreshes are not observable by the parent +PASS Test that crossorigin object refreshes are not observable by the parent +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt new file mode 100644 index 0000000..b88a5245 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that embed navigations are not observable by the parent +PASS Test that crossorigin embed navigations are not observable by the parent +PASS Test that embed refreshes are not observable by the parent +PASS Test that crossorigin embed refreshes are not observable by the parent +PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that iframe navigations are not observable by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent +PASS Test that iframe refreshes are not observable by the parent +PASS Test that crossorigin iframe refreshes are not observable by the parent +FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +PASS Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent +PASS Test that object navigations are not observable by the parent +PASS Test that crossorigin object navigations are not observable by the parent +PASS Test that object refreshes are not observable by the parent +PASS Test that crossorigin object refreshes are not observable by the parent +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt new file mode 100644 index 0000000..39e546e --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent +PASS Test that embed navigations are not observable by the parent +PASS Test that crossorigin embed navigations are not observable by the parent +PASS Test that embed refreshes are not observable by the parent +PASS Test that crossorigin embed refreshes are not observable by the parent +PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent +PASS Test that iframe navigations are not observable by the parent +PASS Test that crossorigin iframe navigations are not observable by the parent +PASS Test that iframe refreshes are not observable by the parent +PASS Test that crossorigin iframe refreshes are not observable by the parent +FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +FAIL Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" +PASS Test that object navigations are not observable by the parent +PASS Test that crossorigin object navigations are not observable by the parent +PASS Test that object refreshes are not observable by the parent +PASS Test that crossorigin object refreshes are not observable by the parent +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/binary-for-devtools/http/tests/devtools/README.txt b/third_party/blink/web_tests/virtual/binary-for-devtools/http/tests/devtools/README.txt new file mode 100644 index 0000000..0ac69026 --- /dev/null +++ b/third_party/blink/web_tests/virtual/binary-for-devtools/http/tests/devtools/README.txt
@@ -0,0 +1,2 @@ +# This suite runs the tests in http/tests/devtools with +# the additional flag --enable-internal-devtools-binary-protocol.
diff --git a/third_party/blink/web_tests/virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/README.txt b/third_party/blink/web_tests/virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/README.txt new file mode 100644 index 0000000..36800ce --- /dev/null +++ b/third_party/blink/web_tests/virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/README.txt
@@ -0,0 +1,2 @@ +# This suite runs the tests in http/tests/inspector-protocol with +# the additional flag --enable-internal-devtools-binary-protocol.
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt index 64d94456..2da577f 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt
@@ -5,6 +5,6 @@ FAIL Calling addTransceiver() twice should fire negotiationneeded event once Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument. FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is rejected with: InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument. Reached unreachable code PASS negotiationneeded event should not fire if signaling state is not stable -FAIL negotiationneeded event should fire only after signaling state go back to stable assert_unreached: Expect negotiationneeded promise to resolve after pc has set remote answer and go back to stable state Reached unreachable code +FAIL negotiationneeded event should fire only after signaling state go back to stable promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt index f265ed42..f6cc537 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt
@@ -11,7 +11,7 @@ FAIL setLocalDescription(offer): transceiver gets associated with an m-section promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'mid' of null" FAIL setLocalDescription(offer): transceiver.mid matches the offer SDP promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'mid' of null" PASS setRemoteDescription(offer): ontrack fires with a track -PASS setRemoteDescription(offer): ontrack's track.id is the same as track.id +PASS setRemoteDescription(offer): ontrack's stream.id is the same as stream.id FAIL setRemoteDescription(offer): ontrack fires with a transceiver. assert_true: trackEvent.transceiver instanceof RTCRtpTransceiver expected true got false FAIL setRemoteDescription(offer): transceiver.mid is the same on both ends promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'mid' of null" FAIL setRemoteDescription(offer): "transceiver == {sender,receiver}" assert_array_equals: pc2.getTransceivers() equals [transceiver] lengths differ, expected 1 got 0
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index a7681dd4..a5901da0 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 99bf283e54d049b6f5d2ad5522c6e3094b7156b4 +Revision: 1bb8ca4059d8bcc933478e02d7869dda7daa0263 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/BUILD.gn b/third_party/crashpad/crashpad/BUILD.gn index ce9edf7..10850c6 100644 --- a/third_party/crashpad/crashpad/BUILD.gn +++ b/third_party/crashpad/crashpad/BUILD.gn
@@ -37,7 +37,6 @@ import("//build/package.gni") package("crashpad_test") { testonly = true - deprecated_system_image = true deps = [ ":crashpad_tests", @@ -55,19 +54,21 @@ }, ] - # Note that the infix of "crashpad_tests" below in - # binary/resource entries should be removed once - # crashpad_tests is moved out of the system image; - # until then, it is used to disambiguate the crashpad - # binaries and data from others within /system/(bin|data). + meta = [ + { + path = "test/fuchsia_crashpad_tests.cmx" + dest = "crashpad_tests.cmx" + }, + ] + binaries = [ { name = "crashpad_test_test_multiprocess_exec_test_child" - dest = "crashpad_tests/crashpad_test_test_multiprocess_exec_test_child" + dest = "crashpad_test_test_multiprocess_exec_test_child" }, { name = "http_transport_test_server" - dest = "crashpad_tests/http_transport_test_server" + dest = "http_transport_test_server" }, ] @@ -89,52 +90,34 @@ resources = [ { path = "util/net/testdata/ascii_http_body.txt" - dest = "crashpad_tests/util/net/testdata/ascii_http_body.txt" + dest = "util/net/testdata/ascii_http_body.txt" }, { path = "util/net/testdata/binary_http_body.dat" - dest = "crashpad_tests/util/net/testdata/binary_http_body.dat" + dest = "util/net/testdata/binary_http_body.dat" }, { path = "test/test_paths_test_data_root.txt" - dest = "crashpad_tests/test/test_paths_test_data_root.txt" + dest = "test/test_paths_test_data_root.txt" }, ] if (crashpad_use_boringssl_for_http_transport_socket) { - deps += [ - "util:generate_test_server_key", - ] + deps += [ "util:generate_test_server_key" ] resources += [ { path = "$root_out_dir/crashpad_util_test_cert.pem" - dest = "crashpad_tests/crashpad_util_test_cert.pem" + dest = "crashpad_util_test_cert.pem" }, { path = "$root_out_dir/crashpad_util_test_key.pem" - dest = "crashpad_tests/crashpad_util_test_key.pem" + dest = "crashpad_util_test_key.pem" }, ] } } - package("crashpad_handler") { - deprecated_system_image = true - - deps = [ - "handler:crashpad_handler", - ] - - binaries = [ - { - name = "crashpad_handler" - }, - ] - } - package("crashpad_database_util") { - deprecated_system_image = true - deps = [ "tools:crashpad_database_util", ] @@ -142,6 +125,7 @@ binaries = [ { name = "crashpad_database_util" + shell = true }, ] }
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 0c8edf20..4bb7d65e 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -20,17 +20,17 @@ deps = { 'buildtools': - Var('chromium_git') + '/chromium/buildtools.git@' + - '6fe4a3251488f7af86d64fc25cf442e817cf6133', + Var('chromium_git') + '/chromium/src/buildtools.git@' + + '3e50219fc4503f461b2176a9976891b28d80f9ab', 'crashpad/third_party/gtest/gtest': Var('chromium_git') + '/external/github.com/google/googletest@' + - '9518a57428ae0a7ed450c1361768e84a2a38af5a', + '8b6d3f9c4a774bef3081195d422993323b6bb2e0', 'crashpad/third_party/gyp/gyp': Var('chromium_git') + '/external/gyp@' + - '5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f', + '8bee09f4a57807136593ddc906b0b213c21f9014', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '737433ebade4d446643c6c07daae02a67e8decca', + 'df0c375531b7cd554e10ad757c5d2372780a1138', 'crashpad/third_party/libfuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + 'fda403cf93ecb8792cb1d061564d89a6553ca020', @@ -89,22 +89,24 @@ 'condition': 'checkout_fuchsia and host_os == "linux"', 'dep_type': 'cipd' }, - 'crashpad/third_party/fuchsia/sdk/linux-amd64': { - # The SDK is keyed to the host system because it contains build tools. - # Currently, linux-amd64 is the only SDK published (see - # https://chrome-infra-packages.appspot.com/#/?path=fuchsia/sdk). - # As long as this is the case, use that SDK package - # even on other build hosts. - # The sysroot (containing headers and libraries) and other components are - # related to the target and should be functional with an appropriate - # toolchain that runs on the build host (fuchsia_clang, above). + 'crashpad/third_party/fuchsia/sdk/mac-amd64': { 'packages': [ { - 'package': 'fuchsia/sdk/linux-amd64', + 'package': 'fuchsia/sdk/core/mac-amd64', 'version': 'latest' }, ], - 'condition': 'checkout_fuchsia', + 'condition': 'checkout_fuchsia and host_os == "mac"', + 'dep_type': 'cipd' + }, + 'crashpad/third_party/fuchsia/sdk/linux-amd64': { + 'packages': [ + { + 'package': 'fuchsia/sdk/core/linux-amd64', + 'version': 'latest' + }, + ], + 'condition': 'checkout_fuchsia and host_os == "linux"', 'dep_type': 'cipd' }, 'crashpad/third_party/win/toolchain': {
diff --git a/third_party/crashpad/crashpad/compat/BUILD.gn b/third_party/crashpad/crashpad/compat/BUILD.gn index 9f247a45..7a33d7ca 100644 --- a/third_party/crashpad/crashpad/compat/BUILD.gn +++ b/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -19,6 +19,8 @@ if (crashpad_is_mac) { include_dirs += [ "mac" ] + } else { + include_dirs += [ "non_mac" ] } if (crashpad_is_linux || crashpad_is_android) { @@ -34,6 +36,10 @@ } else { include_dirs += [ "non_win" ] } + + if (!crashpad_is_linux && !crashpad_is_android && !crashpad_is_fuchsia) { + include_dirs += [ "non_elf" ] + } } template("compat_target") { @@ -62,7 +68,12 @@ "mac/sys/resource.h", ] } else { - sources += [ "non_mac/mach/mach.h" ] + sources += [ + "non_mac/mach-o/loader.h", + "non_mac/mach/mach.h", + "non_mac/mach/machine.h", + "non_mac/mach/vm_prot.h", + ] } if (crashpad_is_linux || crashpad_is_android) { @@ -116,6 +127,10 @@ ] } + if (!crashpad_is_linux && !crashpad_is_android && !crashpad_is_fuchsia) { + sources += [ "non_elf/elf.h" ] + } + public_configs = [ ":compat_config", "..:crashpad_config", @@ -123,7 +138,15 @@ deps = [] + if (!crashpad_is_mac) { + deps += [ "../third_party/xnu" ] + } + if (crashpad_is_win) { deps += [ "../third_party/getopt" ] } + + if (!crashpad_is_linux && !crashpad_is_android && !crashpad_is_fuchsia) { + deps += [ "../third_party/glibc" ] + } }
diff --git a/third_party/crashpad/crashpad/compat/non_elf/elf.h b/third_party/crashpad/crashpad/compat/non_elf/elf.h new file mode 100644 index 0000000..1245f16 --- /dev/null +++ b/third_party/crashpad/crashpad/compat/non_elf/elf.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_NON_ELF_ELF_H_ +#define CRASHPAD_COMPAT_NON_ELF_ELF_H_ + +#include "third_party/glibc/elf/elf.h" + +#endif // CRASHPAD_COMPAT_NON_ELF_ELF_H_
diff --git a/third_party/crashpad/crashpad/compat/non_mac/mach-o/loader.h b/third_party/crashpad/crashpad/compat/non_mac/mach-o/loader.h new file mode 100644 index 0000000..98a8b5f --- /dev/null +++ b/third_party/crashpad/crashpad/compat/non_mac/mach-o/loader.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_NON_MAC_MACH_O_LOADER_H_ +#define CRASHPAD_COMPAT_NON_MAC_MACH_O_LOADER_H_ + +#include "third_party/xnu/EXTERNAL_HEADERS/mach-o/loader.h" + +#endif // CRASHPAD_COMPAT_NON_MAC_MACH_O_LOADER_H_
diff --git a/third_party/crashpad/crashpad/compat/non_mac/mach/machine.h b/third_party/crashpad/crashpad/compat/non_mac/mach/machine.h new file mode 100644 index 0000000..54d4742 --- /dev/null +++ b/third_party/crashpad/crashpad/compat/non_mac/mach/machine.h
@@ -0,0 +1,21 @@ +// Copyright 2019 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_NON_MAC_MACH_MACHINE_H_ +#define CRASHPAD_COMPAT_NON_MAC_MACH_MACHINE_H_ + +typedef int cpu_type_t; +typedef int cpu_subtype_t; + +#endif // CRASHPAD_COMPAT_NON_MAC_MACH_MACHINE_H_
diff --git a/third_party/crashpad/crashpad/compat/non_mac/mach/vm_prot.h b/third_party/crashpad/crashpad/compat/non_mac/mach/vm_prot.h new file mode 100644 index 0000000..1200179 --- /dev/null +++ b/third_party/crashpad/crashpad/compat/non_mac/mach/vm_prot.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_NON_MAC_MACH_VM_PROT_H_ +#define CRASHPAD_COMPAT_NON_MAC_MACH_VM_PROT_H_ + +typedef int vm_prot_t; + +#endif // CRASHPAD_COMPAT_NON_MAC_MACH_VM_PROT_H_
diff --git a/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc b/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc index e77bab8..30b2d71 100644 --- a/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc +++ b/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc
@@ -86,7 +86,6 @@ } if (context_.architecture == CPUArchitecture::kCPUArchitectureX86) { - LOG(WARNING) << "Snapshot X86 context support has no unit tests."; context_memory_.resize(sizeof(CPUContextX86)); context_.x86 = reinterpret_cast<CPUContextX86*>(context_memory_.data()); const MinidumpContextX86* src = @@ -180,7 +179,6 @@ context_.x86_64->dr4 = src->dr6; context_.x86_64->dr5 = src->dr7; } else if (context_.architecture == CPUArchitecture::kCPUArchitectureARM) { - LOG(WARNING) << "Snapshot ARM32 context support has no unit tests."; context_memory_.resize(sizeof(CPUContextARM)); context_.arm = reinterpret_cast<CPUContextARM*>(context_memory_.data()); const MinidumpContextARM* src = @@ -242,7 +240,6 @@ context_.arm64->fpsr = src->fpsr; context_.arm64->spsr = src->cpsr; } else if (context_.architecture == CPUArchitecture::kCPUArchitectureMIPSEL) { - LOG(WARNING) << "Snapshot MIPS context support has no unit tests."; context_memory_.resize(sizeof(CPUContextMIPS)); context_.mipsel = reinterpret_cast<CPUContextMIPS*>(context_memory_.data()); const MinidumpContextMIPS* src = @@ -278,7 +275,6 @@ memcpy(&context_.mipsel->fpregs, &src->fpregs, sizeof(src->fpregs)); } else if (context_.architecture == CPUArchitecture::kCPUArchitectureMIPS64EL) { - LOG(WARNING) << "Snapshot MIPS64 context support has no unit tests."; context_memory_.resize(sizeof(CPUContextMIPS64)); context_.mips64 = reinterpret_cast<CPUContextMIPS64*>(context_memory_.data());
diff --git a/third_party/crashpad/crashpad/test/fuchsia_crashpad_tests.cmx b/third_party/crashpad/crashpad/test/fuchsia_crashpad_tests.cmx new file mode 100644 index 0000000..6b666379 --- /dev/null +++ b/third_party/crashpad/crashpad/test/fuchsia_crashpad_tests.cmx
@@ -0,0 +1,21 @@ +{ + "facets": { + "fuchsia.test": { + "system-services": [ + "fuchsia.net.SocketProvider" + ] + } + }, + "program": { + "binary": "test/crashpad_tests" + }, + "sandbox": { + "features": [ + "system-temp" + ], + "services": [ + "fuchsia.net.SocketProvider", + "fuchsia.process.Launcher" + ] + } +}
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc index 3b611b1..10bae7a2 100644 --- a/third_party/crashpad/crashpad/test/test_paths.cc +++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -44,14 +44,7 @@ base::FilePath TestDataRootInternal() { #if defined(OS_FUCHSIA) - base::FilePath asset_path("/pkg/assets"); -#if defined(CRASHPAD_IS_IN_FUCHSIA) - // Tests are not yet packaged when running in the Fuchsia tree, so assets do - // not appear as expected at /pkg/assets. Override the default so that tests - // can find their data for now. - // https://crashpad.chromium.org/bug/196. - asset_path = base::FilePath("/system/data/crashpad_tests"); -#endif + base::FilePath asset_path("/pkg/data"); if (!IsTestDataRoot(asset_path)) { LOG(WARNING) << "Test data root seems invalid, continuing anyway"; } @@ -129,11 +122,7 @@ base::FilePath executable_path; CHECK(Paths::Executable(&executable_path)); #if defined(CRASHPAD_IS_IN_FUCHSIA) - // Tests are not yet packaged when running in the Fuchsia tree, so binaries do - // not appear as expected at /pkg/bin. Override the default of /pkg/bin/app - // so that tests can find the correct location for now. - // https://crashpad.chromium.org/bug/196. - executable_path = base::FilePath("/system/bin/crashpad_tests/app"); + executable_path = base::FilePath("/pkg/bin/app"); #endif return executable_path; } @@ -202,16 +191,7 @@ #if defined(OS_WIN) extension = FILE_PATH_LITERAL(".exe"); #elif defined(OS_FUCHSIA) -#if defined(CRASHPAD_IS_IN_FUCHSIA) - // Tests are not yet packaged when running in the Fuchsia tree, so - // binaries do not appear as expected at /pkg/bin. Override the default of - // /pkg/bin/app so that tests can find the correct location for now. - // https://crashpad.chromium.org/bug/196. - directory = - base::FilePath(FILE_PATH_LITERAL("/system/bin/crashpad_tests")); -#else directory = base::FilePath(FILE_PATH_LITERAL("/pkg/bin")); -#endif #endif // OS_WIN break; @@ -233,12 +213,7 @@ case FileType::kCertificate: #if defined(CRASHPAD_IS_IN_FUCHSIA) - // When running in the Fuchsia tree, the .pem files are packaged as assets - // into the test data folder. This will need to be rationalized when - // things are actually run from a package. - // https://crashpad.chromium.org/bug/196. - directory = - base::FilePath(FILE_PATH_LITERAL("/system/data/crashpad_tests")); + directory = base::FilePath(FILE_PATH_LITERAL("/pkg/data")); #endif extension = FILE_PATH_LITERAL(".pem"); break;
diff --git a/third_party/crashpad/crashpad/third_party/apple_cf/BUILD.gn b/third_party/crashpad/crashpad/third_party/apple_cf/BUILD.gn new file mode 100644 index 0000000..43c62eb --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/apple_cf/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2019 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source_set("apple_cf") { + sources = [ + "CFStreamAbstract.h", + ] +}
diff --git a/third_party/crashpad/crashpad/third_party/apple_cf/CFStreamAbstract.h b/third_party/crashpad/crashpad/third_party/apple_cf/CFStreamAbstract.h index bf12c92..ac26664 100644 --- a/third_party/crashpad/crashpad/third_party/apple_cf/CFStreamAbstract.h +++ b/third_party/crashpad/crashpad/third_party/apple_cf/CFStreamAbstract.h
@@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Apple Inc. All rights reserved. + * Copyright (c) 2015 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStreamAbstract.h - Copyright (c) 2000-2009, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAMABSTRACT__) @@ -134,11 +134,18 @@ void *_CFWriteStreamGetClient(CFWriteStreamRef writeStream); // Returns an array of the runloops and modes on which the stream is currently scheduled +// Note that these are unretained mutable arrays - use the copy variant instead. CF_EXPORT CFArrayRef _CFReadStreamGetRunLoopsAndModes(CFReadStreamRef readStream); CF_EXPORT CFArrayRef _CFWriteStreamGetRunLoopsAndModes(CFWriteStreamRef writeStream); +// Returns an array of the runloops and modes on which the stream is currently scheduled +CF_EXPORT +CFArrayRef _CFReadStreamCopyRunLoopsAndModes(CFReadStreamRef readStream); +CF_EXPORT +CFArrayRef _CFWriteStreamCopyRunLoopsAndModes(CFWriteStreamRef writeStream); + /* Deprecated versions; here for backwards compatibility. */ typedef struct { CFIndex version; /* == 1 */
diff --git a/third_party/crashpad/crashpad/third_party/apple_cf/README.crashpad b/third_party/crashpad/crashpad/third_party/apple_cf/README.crashpad index b6c6cfa..20066484 100644 --- a/third_party/crashpad/crashpad/third_party/apple_cf/README.crashpad +++ b/third_party/crashpad/crashpad/third_party/apple_cf/README.crashpad
@@ -2,7 +2,7 @@ Short Name: CF URL: https://opensource.apple.com/source/CF/ URL: https://opensource.apple.com/tarballs/CF/ -Version: 550.43 (from Mac OS X 10.6.8) +Version: 1153.18 (from OS X 10.10.3) License: APSL 2.0 License File: APPLE_LICENSE Security Critical: no
diff --git a/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn b/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn index 1e6d94d..6965dfe 100644 --- a/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn +++ b/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn
@@ -26,12 +26,12 @@ group("zx") { public_deps = [ "//third_party/fuchsia-sdk/sdk:fdio", - "//third_party/fuchsia-sdk/sdk:zx", "//third_party/fuchsia-sdk/sdk:sysinfo", + "//third_party/fuchsia-sdk/sdk:zx", ] } } else { - sdk_path = "sdk/linux-amd64" + sdk_path = "sdk/$host_os-amd64" sdk_pkg_path = "$sdk_path/pkg" sdk_fidl_path = "$sdk_path/fidl" @@ -40,6 +40,7 @@ include_dirs = [ "$root_gen_dir/fidl/include", "$sdk_pkg_path/fidl/include", + "$sdk_pkg_path/fidl_base/include", "$sdk_pkg_path/zx/include", ] } @@ -70,17 +71,20 @@ script = "runner.py" args = [ - rebase_path("$sdk_path/tools/fidlc", root_build_dir), - "--c-header", - rebase_path(c_header, root_build_dir), - "--c-client", - rebase_path(c_client, root_build_dir), - "--tables", - rebase_path(coding_tables, root_build_dir), - "--files", - ] + [ rebase_path(fidl_source.fidl, root_build_dir) ] + rebase_path("$sdk_path/tools/fidlc", root_build_dir), + "--c-header", + rebase_path(c_header, root_build_dir), + "--c-client", + rebase_path(c_client, root_build_dir), + "--tables", + rebase_path(coding_tables, root_build_dir), + "--files", + ] + [ rebase_path(fidl_source.fidl, root_build_dir) ] - inputs = [ fidl_source.fidl, "$sdk_path/tools/fidlc" ] + inputs = [ + fidl_source.fidl, + "$sdk_path/tools/fidlc", + ] outputs = [ c_client, @@ -91,47 +95,76 @@ } static_library("zx") { - sources = [ - "$sdk_pkg_path/zx/channel.cpp", - "$sdk_pkg_path/zx/event.cpp", - "$sdk_pkg_path/zx/eventpair.cpp", - "$sdk_pkg_path/zx/fifo.cpp", - "$sdk_pkg_path/zx/guest.cpp", - "$sdk_pkg_path/zx/include/lib/zx/bti.h", - "$sdk_pkg_path/zx/include/lib/zx/channel.h", - "$sdk_pkg_path/zx/include/lib/zx/event.h", - "$sdk_pkg_path/zx/include/lib/zx/eventpair.h", - "$sdk_pkg_path/zx/include/lib/zx/fifo.h", - "$sdk_pkg_path/zx/include/lib/zx/guest.h", - "$sdk_pkg_path/zx/include/lib/zx/handle.h", - "$sdk_pkg_path/zx/include/lib/zx/interrupt.h", - "$sdk_pkg_path/zx/include/lib/zx/job.h", - "$sdk_pkg_path/zx/include/lib/zx/object.h", - "$sdk_pkg_path/zx/include/lib/zx/object_traits.h", - "$sdk_pkg_path/zx/include/lib/zx/pmt.h", - "$sdk_pkg_path/zx/include/lib/zx/port.h", - "$sdk_pkg_path/zx/include/lib/zx/process.h", - "$sdk_pkg_path/zx/include/lib/zx/resource.h", - "$sdk_pkg_path/zx/include/lib/zx/socket.h", - "$sdk_pkg_path/zx/include/lib/zx/task.h", - "$sdk_pkg_path/zx/include/lib/zx/thread.h", - "$sdk_pkg_path/zx/include/lib/zx/time.h", - "$sdk_pkg_path/zx/include/lib/zx/timer.h", - "$sdk_pkg_path/zx/include/lib/zx/vmar.h", - "$sdk_pkg_path/zx/include/lib/zx/vmo.h", - "$sdk_pkg_path/zx/interrupt.cpp", - "$sdk_pkg_path/zx/job.cpp", - "$sdk_pkg_path/zx/port.cpp", - "$sdk_pkg_path/zx/process.cpp", - "$sdk_pkg_path/zx/resource.cpp", - "$sdk_pkg_path/zx/socket.cpp", - "$sdk_pkg_path/zx/thread.cpp", - "$sdk_pkg_path/zx/timer.cpp", - "$sdk_pkg_path/zx/vmar.cpp", - "$sdk_pkg_path/zx/vmo.cpp", - ] + fidl_gen_sources + sources = + [ + # This is the zx library. + "$sdk_pkg_path/zx/channel.cpp", + "$sdk_pkg_path/zx/event.cpp", + "$sdk_pkg_path/zx/eventpair.cpp", + "$sdk_pkg_path/zx/fifo.cpp", + "$sdk_pkg_path/zx/guest.cpp", + "$sdk_pkg_path/zx/include/lib/zx/bti.h", + "$sdk_pkg_path/zx/include/lib/zx/channel.h", + "$sdk_pkg_path/zx/include/lib/zx/event.h", + "$sdk_pkg_path/zx/include/lib/zx/eventpair.h", + "$sdk_pkg_path/zx/include/lib/zx/fifo.h", + "$sdk_pkg_path/zx/include/lib/zx/guest.h", + "$sdk_pkg_path/zx/include/lib/zx/handle.h", + "$sdk_pkg_path/zx/include/lib/zx/interrupt.h", + "$sdk_pkg_path/zx/include/lib/zx/job.h", + "$sdk_pkg_path/zx/include/lib/zx/object.h", + "$sdk_pkg_path/zx/include/lib/zx/object_traits.h", + "$sdk_pkg_path/zx/include/lib/zx/pmt.h", + "$sdk_pkg_path/zx/include/lib/zx/port.h", + "$sdk_pkg_path/zx/include/lib/zx/process.h", + "$sdk_pkg_path/zx/include/lib/zx/resource.h", + "$sdk_pkg_path/zx/include/lib/zx/socket.h", + "$sdk_pkg_path/zx/include/lib/zx/task.h", + "$sdk_pkg_path/zx/include/lib/zx/thread.h", + "$sdk_pkg_path/zx/include/lib/zx/time.h", + "$sdk_pkg_path/zx/include/lib/zx/timer.h", + "$sdk_pkg_path/zx/include/lib/zx/vmar.h", + "$sdk_pkg_path/zx/include/lib/zx/vmo.h", + "$sdk_pkg_path/zx/interrupt.cpp", + "$sdk_pkg_path/zx/job.cpp", + "$sdk_pkg_path/zx/port.cpp", + "$sdk_pkg_path/zx/process.cpp", + "$sdk_pkg_path/zx/resource.cpp", + "$sdk_pkg_path/zx/socket.cpp", + "$sdk_pkg_path/zx/thread.cpp", + "$sdk_pkg_path/zx/timer.cpp", + "$sdk_pkg_path/zx/vmar.cpp", + "$sdk_pkg_path/zx/vmo.cpp", - deps = [ ":fuchsia.sysinfo" ] + # This is the fidl_base library. + "$sdk_pkg_path/fidl_base/builder.cpp", + "$sdk_pkg_path/fidl_base/decoding.cpp", + "$sdk_pkg_path/fidl_base/encoding.cpp", + "$sdk_pkg_path/fidl_base/envelope_frames.h", + "$sdk_pkg_path/fidl_base/formatting.cpp", + "$sdk_pkg_path/fidl_base/include/lib/fidl/coding.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/builder.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/message.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/message_buffer.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/message_builder.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/message_part.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/string_view.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/cpp/vector_view.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/internal.h", + "$sdk_pkg_path/fidl_base/include/lib/fidl/internal_callable_traits.h", + "$sdk_pkg_path/fidl_base/linearizing.cpp", + "$sdk_pkg_path/fidl_base/message.cpp", + "$sdk_pkg_path/fidl_base/message_buffer.cpp", + "$sdk_pkg_path/fidl_base/message_builder.cpp", + "$sdk_pkg_path/fidl_base/validating.cpp", + "$sdk_pkg_path/fidl_base/visitor.h", + "$sdk_pkg_path/fidl_base/walker.cpp", + "$sdk_pkg_path/fidl_base/walker.h", + ] + fidl_gen_sources + + deps = [ + ":fuchsia.sysinfo", + ] public_configs = [ ":zx_config" ] }
diff --git a/third_party/crashpad/crashpad/third_party/glibc/BUILD.gn b/third_party/crashpad/crashpad/third_party/glibc/BUILD.gn new file mode 100644 index 0000000..e12febf --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/glibc/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2019 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source_set("glibc") { + sources = [ + "elf/elf.h", + ] +}
diff --git a/third_party/crashpad/crashpad/third_party/glibc/COPYING.LIB b/third_party/crashpad/crashpad/third_party/glibc/COPYING.LIB new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/glibc/COPYING.LIB
@@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed 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. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it!
diff --git a/third_party/crashpad/crashpad/third_party/glibc/README.crashpad b/third_party/crashpad/crashpad/third_party/glibc/README.crashpad new file mode 100644 index 0000000..b550ad9 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/glibc/README.crashpad
@@ -0,0 +1,16 @@ +Name: GNU C Library +Short Name: glibc +URL: https://www.gnu.org/software/libc/ +URL: https://sourceware.org/git/?p=glibc.git +Version: 2.29 +License: GNU LGPL 2.1 +License File: COPYING.LIB +Security Critical: no + +Description: +glibc is the GNU Project’s implementation of the C standard library. + +Local Modifications: + - Only elf/elf.h is included. Its #include of <features.h> has been removed, + and it uses of __BEGIN_DECLS and __END_DECLS have been replaced with inline + versions in the manner that misc/sys/cdefs.h defines those macros.
diff --git a/third_party/crashpad/crashpad/third_party/glibc/elf/elf.h b/third_party/crashpad/crashpad/third_party/glibc/elf/elf.h new file mode 100644 index 0000000..331536b49 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/glibc/elf/elf.h
@@ -0,0 +1,4003 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed 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. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _ELF_H +#define _ELF_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard ELF types. */ + +#include <stdint.h> + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ +#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_IAMCU 6 /* Intel MCU */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + /* reserved 11-14 */ +#define EM_PARISC 15 /* HPPA */ + /* reserved 16 */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ +#define EM_SPU 23 /* IBM SPU/SPC */ + /* reserved 24-35 */ +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ +#define EM_PDP10 64 /* Digital PDP-10 */ +#define EM_PDP11 65 /* Digital PDP-11 */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit emb.proc */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit emb.proc */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_COMPACT 93 /* ARC International ARCompact */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Proc */ +#define EM_NS32K 97 /* National Semi. 32000 */ +#define EM_TPC 98 /* Tenor Network TPC */ +#define EM_SNP1K 99 /* Trebia SNP 1000 */ +#define EM_ST200 100 /* STMicroelectronics ST200 */ +#define EM_IP2K 101 /* Ubicom IP2xxx */ +#define EM_MAX 102 /* MAX processor */ +#define EM_CR 103 /* National Semi. CompactRISC */ +#define EM_F2MC16 104 /* Fujitsu F2MC16 */ +#define EM_MSP430 105 /* Texas Instruments msp430 */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ +#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ +#define EM_SEP 108 /* Sharp embedded microprocessor */ +#define EM_ARCA 109 /* Arca RISC */ +#define EM_UNICORE 110 /* PKU-Unity & MPRC Peking Uni. mc series */ +#define EM_EXCESS 111 /* eXcess configurable cpu */ +#define EM_DXP 112 /* Icera Semi. Deep Execution Processor */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II */ +#define EM_CRX 114 /* National Semi. CompactRISC CRX */ +#define EM_XGATE 115 /* Motorola XGATE */ +#define EM_C166 116 /* Infineon C16x/XC16x */ +#define EM_M16C 117 /* Renesas M16C */ +#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F */ +#define EM_CE 119 /* Freescale Communication Engine RISC */ +#define EM_M32C 120 /* Renesas M32C */ + /* reserved 121-130 */ +#define EM_TSK3000 131 /* Altium TSK3000 */ +#define EM_RS08 132 /* Freescale RS08 */ +#define EM_SHARC 133 /* Analog Devices SHARC family */ +#define EM_ECOG2 134 /* Cyan Technology eCOG2 */ +#define EM_SCORE7 135 /* Sunplus S+core7 RISC */ +#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP */ +#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III */ +#define EM_LATTICEMICO32 138 /* RISC for Lattice FPGA */ +#define EM_SE_C17 139 /* Seiko Epson C17 */ +#define EM_TI_C6000 140 /* Texas Instruments TMS320C6000 DSP */ +#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP */ +#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP */ +#define EM_TI_ARP32 143 /* Texas Instruments App. Specific RISC */ +#define EM_TI_PRU 144 /* Texas Instruments Prog. Realtime Unit */ + /* reserved 145-159 */ +#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW DSP */ +#define EM_CYPRESS_M8C 161 /* Cypress M8C */ +#define EM_R32C 162 /* Renesas R32C */ +#define EM_TRIMEDIA 163 /* NXP Semi. TriMedia */ +#define EM_QDSP6 164 /* QUALCOMM DSP6 */ +#define EM_8051 165 /* Intel 8051 and variants */ +#define EM_STXP7X 166 /* STMicroelectronics STxP7x */ +#define EM_NDS32 167 /* Andes Tech. compact code emb. RISC */ +#define EM_ECOG1X 168 /* Cyan Technology eCOG1X */ +#define EM_MAXQ30 169 /* Dallas Semi. MAXQ30 mc */ +#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP */ +#define EM_MANIK 171 /* M2000 Reconfigurable RISC */ +#define EM_CRAYNV2 172 /* Cray NV2 vector architecture */ +#define EM_RX 173 /* Renesas RX */ +#define EM_METAG 174 /* Imagination Tech. META */ +#define EM_MCST_ELBRUS 175 /* MCST Elbrus */ +#define EM_ECOG16 176 /* Cyan Technology eCOG16 */ +#define EM_CR16 177 /* National Semi. CompactRISC CR16 */ +#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */ +#define EM_SLE9X 179 /* Infineon Tech. SLE9X */ +#define EM_L10M 180 /* Intel L10M */ +#define EM_K10M 181 /* Intel K10M */ + /* reserved 182 */ +#define EM_AARCH64 183 /* ARM AARCH64 */ + /* reserved 184 */ +#define EM_AVR32 185 /* Amtel 32-bit microprocessor */ +#define EM_STM8 186 /* STMicroelectronics STM8 */ +#define EM_TILE64 187 /* Tileta TILE64 */ +#define EM_TILEPRO 188 /* Tilera TILEPro */ +#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ +#define EM_CUDA 190 /* NVIDIA CUDA */ +#define EM_TILEGX 191 /* Tilera TILE-Gx */ +#define EM_CLOUDSHIELD 192 /* CloudShield */ +#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st gen. */ +#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd gen. */ +#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */ +#define EM_OPEN8 196 /* Open8 RISC */ +#define EM_RL78 197 /* Renesas RL78 */ +#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V */ +#define EM_78KOR 199 /* Renesas 78KOR */ +#define EM_56800EX 200 /* Freescale 56800EX DSC */ +#define EM_BA1 201 /* Beyond BA1 */ +#define EM_BA2 202 /* Beyond BA2 */ +#define EM_XCORE 203 /* XMOS xCORE */ +#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) */ + /* reserved 205-209 */ +#define EM_KM32 210 /* KM211 KM32 */ +#define EM_KMX32 211 /* KM211 KMX32 */ +#define EM_EMX16 212 /* KM211 KMX16 */ +#define EM_EMX8 213 /* KM211 KMX8 */ +#define EM_KVARC 214 /* KM211 KVARC */ +#define EM_CDP 215 /* Paneve CDP */ +#define EM_COGE 216 /* Cognitive Smart Memory Processor */ +#define EM_COOL 217 /* Bluechip CoolEngine */ +#define EM_NORC 218 /* Nanoradio Optimized RISC */ +#define EM_CSR_KALIMBA 219 /* CSR Kalimba */ +#define EM_Z80 220 /* Zilog Z80 */ +#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore */ +#define EM_FT32 222 /* FTDI Chip FT32 */ +#define EM_MOXIE 223 /* Moxie processor */ +#define EM_AMDGPU 224 /* AMD GPU */ + /* reserved 225-242 */ +#define EM_RISCV 243 /* RISC-V */ + +#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ +#define EM_CSKY 252 /* C_SKY */ + +#define EM_NUM 253 + +/* Old spellings/synonyms. */ + +#define EM_ARC_A5 EM_ARC_COMPACT + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section compression header. Used when SHF_COMPRESSED is set. */ + +typedef struct +{ + Elf32_Word ch_type; /* Compression format. */ + Elf32_Word ch_size; /* Uncompressed data size. */ + Elf32_Word ch_addralign; /* Uncompressed data alignment. */ +} Elf32_Chdr; + +typedef struct +{ + Elf64_Word ch_type; /* Compression format. */ + Elf64_Word ch_reserved; + Elf64_Xword ch_size; /* Uncompressed data size. */ + Elf64_Xword ch_addralign; /* Uncompressed data alignment. */ +} Elf64_Chdr; + +/* Legal values for ch_type (compression algorithm). */ +#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */ +#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */ +#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */ +#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */ +#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_GNU_UNIQUE 10 /* Unique symbol. */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Special value for e_phnum. This indicates that the real number of + program headers is too large to fit into e_phnum. Instead the real + value is in the field sh_info of section 0. */ + +#define PN_XNUM 0xffff + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_PRFPREG 2 /* Contains copy of fpregset + struct. */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ +#define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, + size might increase */ +#define NT_FILE 0x46494c45 /* Contains information about mapped + files */ +#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ +#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_PPC_TAR 0x103 /* Target Address Register */ +#define NT_PPC_PPR 0x104 /* Program Priority Register */ +#define NT_PPC_DSCR 0x105 /* Data Stream Control Register */ +#define NT_PPC_EBB 0x106 /* Event Based Branch Registers */ +#define NT_PPC_PMU 0x107 /* Performance Monitor Registers */ +#define NT_PPC_TM_CGPR 0x108 /* TM checkpointed GPR Registers */ +#define NT_PPC_TM_CFPR 0x109 /* TM checkpointed FPR Registers */ +#define NT_PPC_TM_CVMX 0x10a /* TM checkpointed VMX Registers */ +#define NT_PPC_TM_CVSX 0x10b /* TM checkpointed VSX Registers */ +#define NT_PPC_TM_SPR 0x10c /* TM Special Purpose Registers */ +#define NT_PPC_TM_CTAR 0x10d /* TM checkpointed Target Address + Register */ +#define NT_PPC_TM_CPPR 0x10e /* TM checkpointed Program Priority + Register */ +#define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control + Register */ +#define NT_PPC_PKEY 0x110 /* Memory Protection Keys + registers. */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ +#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ +#define NT_S390_TIMER 0x301 /* s390 timer register */ +#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ +#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ +#define NT_S390_CTRS 0x304 /* s390 control registers */ +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ +#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */ +#define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 + upper half. */ +#define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31. */ +#define NT_S390_GS_CB 0x30b /* s390 guarded storage registers. */ +#define NT_S390_GS_BC 0x30c /* s390 guarded storage + broadcast control block. */ +#define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation. */ +#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ +#define NT_ARM_TLS 0x401 /* ARM TLS register */ +#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ +#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ +#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ +#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension + registers */ +#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note. */ +#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */ +#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_SYMTAB_SHNDX 34 /* Address of SYMTAB_SHNDX section */ +#define DT_NUM 35 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 11 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ +#define DF_1_NODIRECT 0x00020000 /* Object has no-direct binding. */ +#define DF_1_IGNMULDEF 0x00040000 +#define DF_1_NOKSYMS 0x00080000 +#define DF_1_NOHDR 0x00100000 +#define DF_1_EDITED 0x00200000 /* Object is modified after built. */ +#define DF_1_NORELOC 0x00400000 +#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */ +#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */ +#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ +#define DF_1_STUB 0x04000000 +#define DF_1_PIE 0x08000000 + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard <elf.h> file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + uint32_t a_type; /* Entry type */ + union + { + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + uint64_t a_type; /* Entry type */ + union + { + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine-dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ + +#define AT_RANDOM 25 /* Address of 16 random bytes. */ + +#define AT_HWCAP2 26 /* More machine-dependent hints about + processor capabilities. */ + +#define AT_EXECFN 31 /* Filename of executable. */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Shapes of the caches, with more room to describe them. + *GEOMETRY are comprised of cache line size in bytes in the bottom 16 bits + and the cache associativity in the next 16 bits. */ +#define AT_L1I_CACHESIZE 40 +#define AT_L1I_CACHEGEOMETRY 41 +#define AT_L1D_CACHESIZE 42 +#define AT_L1D_CACHEGEOMETRY 43 +#define AT_L2_CACHESIZE 44 +#define AT_L2_CACHEGEOMETRY 45 +#define AT_L3_CACHESIZE 46 +#define AT_L3_CACHEGEOMETRY 47 + +#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery + (AArch64). */ + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define NT_GNU_ABI_TAG 1 +#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ + +/* Known OSes. These values can appear in word 0 of an + NT_GNU_ABI_TAG note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + +/* Synthetic hwcap information. The descriptor begins with two words: + word 0: number of entries + word 1: bitmask of enabled entries + Then follow variable-length entries, one byte followed by a + '\0'-terminated hwcap name string. The byte gives the bit + number to test if enabled, (1U << bit) & bitmask. */ +#define NT_GNU_HWCAP 2 + +/* Build ID bits as generated by ld --build-id. + The descriptor consists of any nonzero number of bytes. */ +#define NT_GNU_BUILD_ID 3 + +/* Version note generated by GNU gold containing a version string. */ +#define NT_GNU_GOLD_VERSION 4 + +/* Program property. */ +#define NT_GNU_PROPERTY_TYPE_0 5 + +/* Note section name of program property. */ +#define NOTE_GNU_PROPERTY_SECTION_NAME ".note.gnu.property" + +/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */ + +/* Stack size. */ +#define GNU_PROPERTY_STACK_SIZE 1 +/* No copy relocation on protected data symbol. */ +#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2 + +/* Processor-specific semantics, lo */ +#define GNU_PROPERTY_LOPROC 0xc0000000 +/* Processor-specific semantics, hi */ +#define GNU_PROPERTY_HIPROC 0xdfffffff +/* Application-specific semantics, lo */ +#define GNU_PROPERTY_LOUSER 0xe0000000 +/* Application-specific semantics, hi */ +#define GNU_PROPERTY_HIUSER 0xffffffff + +/* The x86 instruction sets indicated by the corresponding bits are + used in program. Their support in the hardware is optional. */ +#define GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 +/* The x86 instruction sets indicated by the corresponding bits are + used in program and they must be supported by the hardware. */ +#define GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 +/* X86 processor-specific features used in program. */ +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 + +#define GNU_PROPERTY_X86_ISA_1_486 (1U << 0) +#define GNU_PROPERTY_X86_ISA_1_586 (1U << 1) +#define GNU_PROPERTY_X86_ISA_1_686 (1U << 2) +#define GNU_PROPERTY_X86_ISA_1_SSE (1U << 3) +#define GNU_PROPERTY_X86_ISA_1_SSE2 (1U << 4) +#define GNU_PROPERTY_X86_ISA_1_SSE3 (1U << 5) +#define GNU_PROPERTY_X86_ISA_1_SSSE3 (1U << 6) +#define GNU_PROPERTY_X86_ISA_1_SSE4_1 (1U << 7) +#define GNU_PROPERTY_X86_ISA_1_SSE4_2 (1U << 8) +#define GNU_PROPERTY_X86_ISA_1_AVX (1U << 9) +#define GNU_PROPERTY_X86_ISA_1_AVX2 (1U << 10) +#define GNU_PROPERTY_X86_ISA_1_AVX512F (1U << 11) +#define GNU_PROPERTY_X86_ISA_1_AVX512CD (1U << 12) +#define GNU_PROPERTY_X86_ISA_1_AVX512ER (1U << 13) +#define GNU_PROPERTY_X86_ISA_1_AVX512PF (1U << 14) +#define GNU_PROPERTY_X86_ISA_1_AVX512VL (1U << 15) +#define GNU_PROPERTY_X86_ISA_1_AVX512DQ (1U << 16) +#define GNU_PROPERTY_X86_ISA_1_AVX512BW (1U << 17) + +/* This indicates that all executable sections are compatible with + IBT. */ +#define GNU_PROPERTY_X86_FEATURE_1_IBT (1U << 0) +/* This indicates that all executable sections are compatible with + SHSTK. */ +#define GNU_PROPERTY_X86_FEATURE_1_SHSTK (1U << 1) + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ +#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ +#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ +#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ +#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ +#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ +#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ +#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ +#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ +#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ +#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ +#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ +#define R_68K_TLS_LE32 37 /* 32 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE16 38 /* 16 bit offset relative to + static TLS block */ +#define R_68K_TLS_LE8 39 /* 8 bit offset relative to + static TLS block */ +#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ +#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ +#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ +/* Keep this the last entry. */ +#define R_68K_NUM 43 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +#define R_386_SIZE32 38 /* 32-bit symbol size */ +#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ +#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS + descriptor for + relaxation. */ +#define R_386_TLS_DESC 41 /* TLS descriptor containing + pointer to code and to + argument, returning the TLS + offset for the symbol. */ +#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ +#define R_386_GOT32X 43 /* Load from 32 bit GOT entry, + relaxable. */ +/* Keep this the last entry. */ +#define R_386_NUM 44 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +#define R_SPARC_GOTDATA_HIX22 80 +#define R_SPARC_GOTDATA_LOX10 81 +#define R_SPARC_GOTDATA_OP_HIX22 82 +#define R_SPARC_GOTDATA_OP_LOX10 83 +#define R_SPARC_GOTDATA_OP 84 +#define R_SPARC_H34 85 +#define R_SPARC_SIZE32 86 +#define R_SPARC_SIZE64 87 +#define R_SPARC_WDISP10 88 +#define R_SPARC_JMP_IREL 248 +#define R_SPARC_IRELATIVE 249 +#define R_SPARC_GNU_VTINHERIT 250 +#define R_SPARC_GNU_VTENTRY 251 +#define R_SPARC_REV32 252 +/* Keep this the last entry. */ +#define R_SPARC_NUM 253 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used. */ +#define EF_MIPS_PIC 2 /* Contains PIC code. */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */ +#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */ +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x50000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x60000000 /* MIPS64 code. */ +#define EF_MIPS_ARCH_32R2 0x70000000 /* MIPS32r2 code. */ +#define EF_MIPS_ARCH_64R2 0x80000000 /* MIPS64r2 code. */ + +/* The following are unofficial names and should not be used. */ + +#define E_MIPS_ARCH_1 EF_MIPS_ARCH_1 +#define E_MIPS_ARCH_2 EF_MIPS_ARCH_2 +#define E_MIPS_ARCH_3 EF_MIPS_ARCH_3 +#define E_MIPS_ARCH_4 EF_MIPS_ARCH_4 +#define E_MIPS_ARCH_5 EF_MIPS_ARCH_5 +#define E_MIPS_ARCH_32 EF_MIPS_ARCH_32 +#define E_MIPS_ARCH_64 EF_MIPS_ARCH_64 + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols. */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols. */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link. */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols. */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes. */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging info. */ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information. */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be in global data area. */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_PLT 0x8 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation. */ + Elf32_Word gt_unused; /* Not used. */ + } gt_header; /* First entry in section. */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G. */ + Elf32_Word gt_bytes; /* This many bytes would be used. */ + } gt_entry; /* Subsequent entries in section. */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used. */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used. */ + Elf32_Sword ri_gp_value; /* $gp register value. */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ +#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ +#define R_MIPS_GLOB_DAT 51 +#define R_MIPS_COPY 126 +#define R_MIPS_JUMP_SLOT 127 +/* Keep this the last entry. */ +#define R_MIPS_NUM 128 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information. */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 +#define PT_MIPS_ABIFLAGS 0x70000003 /* FP mode requirement. */ + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +/* The address of .got.plt in an executable using the new non-PIC ABI. */ +#define DT_MIPS_PLTGOT 0x70000032 +/* The base of the PLT in an executable using the new non-PIC ABI if that + PLT is writable. For a non-writable PLT, this is omitted or has a zero + value. */ +#define DT_MIPS_RWPLT 0x70000034 +/* An alternative description of the classic MIPS RLD_MAP that is usable + in a PIE as it stores a relative offset from the address of the tag + rather than an absolute address. */ +#define DT_MIPS_RLD_MAP_REL 0x70000035 +#define DT_MIPS_NUM 0x36 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + +typedef struct +{ + /* Version of flags structure. */ + Elf32_Half version; + /* The level of the ISA: 1-5, 32, 64. */ + unsigned char isa_level; + /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */ + unsigned char isa_rev; + /* The size of general purpose registers. */ + unsigned char gpr_size; + /* The size of co-processor 1 registers. */ + unsigned char cpr1_size; + /* The size of co-processor 2 registers. */ + unsigned char cpr2_size; + /* The floating-point ABI. */ + unsigned char fp_abi; + /* Processor-specific extension. */ + Elf32_Word isa_ext; + /* Mask of ASEs used. */ + Elf32_Word ases; + /* Mask of general flags. */ + Elf32_Word flags1; + Elf32_Word flags2; +} Elf_MIPS_ABIFlags_v0; + +/* Values for the register size bytes of an abi flags structure. */ + +#define MIPS_AFL_REG_NONE 0x00 /* No registers. */ +#define MIPS_AFL_REG_32 0x01 /* 32-bit registers. */ +#define MIPS_AFL_REG_64 0x02 /* 64-bit registers. */ +#define MIPS_AFL_REG_128 0x03 /* 128-bit registers. */ + +/* Masks for the ases word of an ABI flags structure. */ + +#define MIPS_AFL_ASE_DSP 0x00000001 /* DSP ASE. */ +#define MIPS_AFL_ASE_DSPR2 0x00000002 /* DSP R2 ASE. */ +#define MIPS_AFL_ASE_EVA 0x00000004 /* Enhanced VA Scheme. */ +#define MIPS_AFL_ASE_MCU 0x00000008 /* MCU (MicroController) ASE. */ +#define MIPS_AFL_ASE_MDMX 0x00000010 /* MDMX ASE. */ +#define MIPS_AFL_ASE_MIPS3D 0x00000020 /* MIPS-3D ASE. */ +#define MIPS_AFL_ASE_MT 0x00000040 /* MT ASE. */ +#define MIPS_AFL_ASE_SMARTMIPS 0x00000080 /* SmartMIPS ASE. */ +#define MIPS_AFL_ASE_VIRT 0x00000100 /* VZ ASE. */ +#define MIPS_AFL_ASE_MSA 0x00000200 /* MSA ASE. */ +#define MIPS_AFL_ASE_MIPS16 0x00000400 /* MIPS16 ASE. */ +#define MIPS_AFL_ASE_MICROMIPS 0x00000800 /* MICROMIPS ASE. */ +#define MIPS_AFL_ASE_XPA 0x00001000 /* XPA ASE. */ +#define MIPS_AFL_ASE_MASK 0x00001fff /* All ASEs. */ + +/* Values for the isa_ext word of an ABI flags structure. */ + +#define MIPS_AFL_EXT_XLR 1 /* RMI Xlr instruction. */ +#define MIPS_AFL_EXT_OCTEON2 2 /* Cavium Networks Octeon2. */ +#define MIPS_AFL_EXT_OCTEONP 3 /* Cavium Networks OcteonP. */ +#define MIPS_AFL_EXT_LOONGSON_3A 4 /* Loongson 3A. */ +#define MIPS_AFL_EXT_OCTEON 5 /* Cavium Networks Octeon. */ +#define MIPS_AFL_EXT_5900 6 /* MIPS R5900 instruction. */ +#define MIPS_AFL_EXT_4650 7 /* MIPS R4650 instruction. */ +#define MIPS_AFL_EXT_4010 8 /* LSI R4010 instruction. */ +#define MIPS_AFL_EXT_4100 9 /* NEC VR4100 instruction. */ +#define MIPS_AFL_EXT_3900 10 /* Toshiba R3900 instruction. */ +#define MIPS_AFL_EXT_10000 11 /* MIPS R10000 instruction. */ +#define MIPS_AFL_EXT_SB1 12 /* Broadcom SB-1 instruction. */ +#define MIPS_AFL_EXT_4111 13 /* NEC VR4111/VR4181 instruction. */ +#define MIPS_AFL_EXT_4120 14 /* NEC VR4120 instruction. */ +#define MIPS_AFL_EXT_5400 15 /* NEC VR5400 instruction. */ +#define MIPS_AFL_EXT_5500 16 /* NEC VR5500 instruction. */ +#define MIPS_AFL_EXT_LOONGSON_2E 17 /* ST Microelectronics Loongson 2E. */ +#define MIPS_AFL_EXT_LOONGSON_2F 18 /* ST Microelectronics Loongson 2F. */ + +/* Masks for the flags1 word of an ABI flags structure. */ +#define MIPS_AFL_FLAGS1_ODDSPREG 1 /* Uses odd single-precision registers. */ + +/* Object attribute values. */ +enum +{ + /* Not tagged or not using any ABIs affected by the differences. */ + Val_GNU_MIPS_ABI_FP_ANY = 0, + /* Using hard-float -mdouble-float. */ + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, + /* Using hard-float -msingle-float. */ + Val_GNU_MIPS_ABI_FP_SINGLE = 2, + /* Using soft-float. */ + Val_GNU_MIPS_ABI_FP_SOFT = 3, + /* Using -mips32r2 -mfp64. */ + Val_GNU_MIPS_ABI_FP_OLD_64 = 4, + /* Using -mfpxx. */ + Val_GNU_MIPS_ABI_FP_XX = 5, + /* Using -mips32r2 -mfp64. */ + Val_GNU_MIPS_ABI_FP_64 = 6, + /* Using -mips32r2 -mfp64 -mno-odd-spreg. */ + Val_GNU_MIPS_ABI_FP_64A = 7, + /* Maximum allocated FP ABI value. */ + Val_GNU_MIPS_ABI_FP_MAX = 7 +}; + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ +#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_GNU_VTENTRY 232 +#define R_PARISC_GNU_VTINHERIT 233 +#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ +#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ +#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ +#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ +#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ +#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ +#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ +#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ +#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ +#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ +#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ +#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ +#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L +#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R +#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L +#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R +#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 +#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + +/* Legal values for d_tag of Elf64_Dyn. */ +#define DT_ALPHA_PLTRO (DT_LOPROC + 0) +#define DT_ALPHA_NUM 1 + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ +#define R_PPC_TLSGD 95 /* none (sym+add)@tlsgd */ +#define R_PPC_TLSLD 96 /* none (sym+add)@tlsld */ + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* GNU extension to support local ifunc. */ +#define R_PPC_IRELATIVE 248 + +/* GNU relocs used in PIC code sequences. */ +#define R_PPC_REL16 249 /* half16 (sym+add-.) */ +#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ +#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ +#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +/* PowerPC specific values for the Dyn d_tag field. */ +#define DT_PPC_GOT (DT_LOPROC + 0) +#define DT_PPC_OPT (DT_LOPROC + 1) +#define DT_PPC_NUM 2 + +/* PowerPC specific values for the DT_PPC_OPT Dyn entry. */ +#define PPC_OPT_TLS 1 + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ +#define R_PPC64_TLSGD 107 /* none (sym+add)@tlsgd */ +#define R_PPC64_TLSLD 108 /* none (sym+add)@tlsld */ +#define R_PPC64_TOCSAVE 109 /* none */ + +/* Added when HA and HI relocs were changed to report overflows. */ +#define R_PPC64_ADDR16_HIGH 110 +#define R_PPC64_ADDR16_HIGHA 111 +#define R_PPC64_TPREL16_HIGH 112 +#define R_PPC64_TPREL16_HIGHA 113 +#define R_PPC64_DTPREL16_HIGH 114 +#define R_PPC64_DTPREL16_HIGHA 115 + +/* GNU extension to support local ifunc. */ +#define R_PPC64_JMP_IREL 247 +#define R_PPC64_IRELATIVE 248 +#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ +#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ +#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ +#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ + +/* e_flags bits specifying ABI. + 1 for original function descriptor using ABI, + 2 for revised ABI without function descriptors, + 0 for unspecified or not using any features affected by the differences. */ +#define EF_PPC64_ABI 3 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_OPT (DT_LOPROC + 3) +#define DT_PPC64_NUM 4 + +/* PowerPC64 specific bits in the DT_PPC64_OPT Dyn entry. */ +#define PPC64_OPT_TLS 1 +#define PPC64_OPT_MULTI_TOC 2 +#define PPC64_OPT_LOCALENTRY 4 + +/* PowerPC64 specific values for the Elf64_Sym st_other field. */ +#define STO_PPC64_LOCAL_BIT 5 +#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) +#define PPC64_LOCAL_ENTRY_OFFSET(other) \ + (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) + + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_SOFT_FLOAT 0x200 +#define EF_ARM_VFP_FLOAT 0x400 +#define EF_ARM_MAVERICK_FLOAT 0x800 + +#define EF_ARM_ABI_FLOAT_SOFT 0x200 /* NB conflicts with EF_ARM_SOFT_FLOAT */ +#define EF_ARM_ABI_FLOAT_HARD 0x400 /* NB conflicts with EF_ARM_VFP_FLOAT */ + + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +/* Constants defined in AAELF. */ +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_LE8 0x00400000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step. */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base. */ +#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ +#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ +#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ +#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ + + +/* AArch64 relocs. */ + +#define R_AARCH64_NONE 0 /* No relocation. */ + +/* ILP32 AArch64 relocs. */ +#define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */ +#define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */ +#define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */ +#define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */ +#define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */ +#define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */ +#define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */ +#define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */ +#define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */ +#define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */ + +/* LP64 AArch64 relocs. */ +#define R_AARCH64_ABS64 257 /* Direct 64 bit. */ +#define R_AARCH64_ABS32 258 /* Direct 32 bit. */ +#define R_AARCH64_ABS16 259 /* Direct 16-bit. */ +#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ +#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ +#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ +#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */ +#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ +#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ +#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */ +#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ +#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ +#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */ +#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ +#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ +#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ +#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ +#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */ +#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ +#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ +#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ +#define R_AARCH64_CALL26 283 /* Likewise for CALL. */ +#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */ +#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */ +#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */ +#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ +#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ +#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ +#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ +#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */ +#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ +#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */ +#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ +#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */ +#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ +#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ +#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ +#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ +#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */ +#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ +#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ +#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ +#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ +#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */ +#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ +#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ +#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ +#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ +#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ +#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ +#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ +#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ +#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ +#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ +#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */ +#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ +#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ +#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ +#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ +#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ +#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ +#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ +#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ +#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ +#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */ +#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ +#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */ +#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ +#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */ +#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ +#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ +#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ +#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ +#define R_AARCH64_TLS_DTPMOD 1028 /* Module number, 64 bit. */ +#define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset, 64 bit. */ +#define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset, 64 bit. */ +#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ +#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ + +/* ARM relocs. */ + +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* Deprecated PC relative 26 + bit branch. */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 /* Direct & 0x7C (LDR, STR). */ +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 /* PC relative 24 bit (Thumb32 BL). */ +#define R_ARM_THM_PC8 11 /* PC relative & 0x3FC + (Thumb16 LDR, ADD, ADR). */ +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 /* Obsolete static relocation. */ +#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ +#define R_ARM_THM_SWI8 14 /* Reserved. */ +#define R_ARM_XPC25 15 /* Reserved. */ +#define R_ARM_THM_XPC22 16 /* Reserved. */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* Deprecated, 32 bit PLT address. */ +#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */ +#define R_ARM_JUMP24 29 /* PC relative 24 bit + (B, BL<cond>). */ +#define R_ARM_THM_JUMP24 30 /* PC relative 24 bit (Thumb32 B.W). */ +#define R_ARM_BASE_ABS 31 /* Adjust by program base. */ +#define R_ARM_ALU_PCREL_7_0 32 /* Obsolete. */ +#define R_ARM_ALU_PCREL_15_8 33 /* Obsolete. */ +#define R_ARM_ALU_PCREL_23_15 34 /* Obsolete. */ +#define R_ARM_LDR_SBREL_11_0 35 /* Deprecated, prog. base relative. */ +#define R_ARM_ALU_SBREL_19_12 36 /* Deprecated, prog. base relative. */ +#define R_ARM_ALU_SBREL_27_20 37 /* Deprecated, prog. base relative. */ +#define R_ARM_TARGET1 38 +#define R_ARM_SBREL31 39 /* Program base relative. */ +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 /* 32 bit PC relative. */ +#define R_ARM_MOVW_ABS_NC 43 /* Direct 16-bit (MOVW). */ +#define R_ARM_MOVT_ABS 44 /* Direct high 16-bit (MOVT). */ +#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */ +#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */ +#define R_ARM_THM_MOVW_ABS_NC 47 /* Direct 16 bit (Thumb32 MOVW). */ +#define R_ARM_THM_MOVT_ABS 48 /* Direct high 16 bit + (Thumb32 MOVT). */ +#define R_ARM_THM_MOVW_PREL_NC 49 /* PC relative 16 bit + (Thumb32 MOVW). */ +#define R_ARM_THM_MOVT_PREL 50 /* PC relative high 16 bit + (Thumb32 MOVT). */ +#define R_ARM_THM_JUMP19 51 /* PC relative 20 bit + (Thumb32 B<cond>.W). */ +#define R_ARM_THM_JUMP6 52 /* PC relative X & 0x7E + (Thumb16 CBZ, CBNZ). */ +#define R_ARM_THM_ALU_PREL_11_0 53 /* PC relative 12 bit + (Thumb32 ADR.W). */ +#define R_ARM_THM_PC12 54 /* PC relative 12 bit + (Thumb32 LDR{D,SB,H,SH}). */ +#define R_ARM_ABS32_NOI 55 /* Direct 32-bit. */ +#define R_ARM_REL32_NOI 56 /* PC relative 32-bit. */ +#define R_ARM_ALU_PC_G0_NC 57 /* PC relative (ADD, SUB). */ +#define R_ARM_ALU_PC_G0 58 /* PC relative (ADD, SUB). */ +#define R_ARM_ALU_PC_G1_NC 59 /* PC relative (ADD, SUB). */ +#define R_ARM_ALU_PC_G1 60 /* PC relative (ADD, SUB). */ +#define R_ARM_ALU_PC_G2 61 /* PC relative (ADD, SUB). */ +#define R_ARM_LDR_PC_G1 62 /* PC relative (LDR,STR,LDRB,STRB). */ +#define R_ARM_LDR_PC_G2 63 /* PC relative (LDR,STR,LDRB,STRB). */ +#define R_ARM_LDRS_PC_G0 64 /* PC relative (STR{D,H}, + LDR{D,SB,H,SH}). */ +#define R_ARM_LDRS_PC_G1 65 /* PC relative (STR{D,H}, + LDR{D,SB,H,SH}). */ +#define R_ARM_LDRS_PC_G2 66 /* PC relative (STR{D,H}, + LDR{D,SB,H,SH}). */ +#define R_ARM_LDC_PC_G0 67 /* PC relative (LDC, STC). */ +#define R_ARM_LDC_PC_G1 68 /* PC relative (LDC, STC). */ +#define R_ARM_LDC_PC_G2 69 /* PC relative (LDC, STC). */ +#define R_ARM_ALU_SB_G0_NC 70 /* Program base relative (ADD,SUB). */ +#define R_ARM_ALU_SB_G0 71 /* Program base relative (ADD,SUB). */ +#define R_ARM_ALU_SB_G1_NC 72 /* Program base relative (ADD,SUB). */ +#define R_ARM_ALU_SB_G1 73 /* Program base relative (ADD,SUB). */ +#define R_ARM_ALU_SB_G2 74 /* Program base relative (ADD,SUB). */ +#define R_ARM_LDR_SB_G0 75 /* Program base relative (LDR, + STR, LDRB, STRB). */ +#define R_ARM_LDR_SB_G1 76 /* Program base relative + (LDR, STR, LDRB, STRB). */ +#define R_ARM_LDR_SB_G2 77 /* Program base relative + (LDR, STR, LDRB, STRB). */ +#define R_ARM_LDRS_SB_G0 78 /* Program base relative + (LDR, STR, LDRB, STRB). */ +#define R_ARM_LDRS_SB_G1 79 /* Program base relative + (LDR, STR, LDRB, STRB). */ +#define R_ARM_LDRS_SB_G2 80 /* Program base relative + (LDR, STR, LDRB, STRB). */ +#define R_ARM_LDC_SB_G0 81 /* Program base relative (LDC,STC). */ +#define R_ARM_LDC_SB_G1 82 /* Program base relative (LDC,STC). */ +#define R_ARM_LDC_SB_G2 83 /* Program base relative (LDC,STC). */ +#define R_ARM_MOVW_BREL_NC 84 /* Program base relative 16 + bit (MOVW). */ +#define R_ARM_MOVT_BREL 85 /* Program base relative high + 16 bit (MOVT). */ +#define R_ARM_MOVW_BREL 86 /* Program base relative 16 + bit (MOVW). */ +#define R_ARM_THM_MOVW_BREL_NC 87 /* Program base relative 16 + bit (Thumb32 MOVW). */ +#define R_ARM_THM_MOVT_BREL 88 /* Program base relative high + 16 bit (Thumb32 MOVT). */ +#define R_ARM_THM_MOVW_BREL 89 /* Program base relative 16 + bit (Thumb32 MOVW). */ +#define R_ARM_TLS_GOTDESC 90 +#define R_ARM_TLS_CALL 91 +#define R_ARM_TLS_DESCSEQ 92 /* TLS relaxation. */ +#define R_ARM_THM_TLS_CALL 93 +#define R_ARM_PLT32_ABS 94 +#define R_ARM_GOT_ABS 95 /* GOT entry. */ +#define R_ARM_GOT_PREL 96 /* PC relative GOT entry. */ +#define R_ARM_GOT_BREL12 97 /* GOT entry relative to GOT + origin (LDR). */ +#define R_ARM_GOTOFF12 98 /* 12 bit, GOT entry relative + to GOT origin (LDR, STR). */ +#define R_ARM_GOTRELAX 99 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* PC relative & 0xFFE (Thumb16 B). */ +#define R_ARM_THM_PC9 103 /* PC relative & 0x1FE + (Thumb16 B/B<cond>). */ +#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic + thread local data */ +#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic + thread local data */ +#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS + block */ +#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of + static TLS block offset */ +#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static + TLS block */ +#define R_ARM_TLS_LDO12 109 /* 12 bit relative to TLS + block (LDR, STR). */ +#define R_ARM_TLS_LE12 110 /* 12 bit relative to static + TLS block (LDR, STR). */ +#define R_ARM_TLS_IE12GP 111 /* 12 bit GOT entry relative + to GOT origin (LDR). */ +#define R_ARM_ME_TOO 128 /* Obsolete. */ +#define R_ARM_THM_TLS_DESCSEQ 129 +#define R_ARM_THM_TLS_DESCSEQ16 129 +#define R_ARM_THM_TLS_DESCSEQ32 130 +#define R_ARM_THM_GOT_BREL12 131 /* GOT entry relative to GOT + origin, 12 bit (Thumb32 LDR). */ +#define R_ARM_IRELATIVE 160 +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* csky */ +#define R_CKCORE_NONE 0 /* no reloc */ +#define R_CKCORE_ADDR32 1 /* direct 32 bit (S + A) */ +#define R_CKCORE_PCRELIMM8BY4 2 /* disp ((S + A - P) >> 2) & 0xff */ +#define R_CKCORE_PCRELIMM11BY2 3 /* disp ((S + A - P) >> 1) & 0x7ff */ +#define R_CKCORE_PCREL32 5 /* 32-bit rel (S + A - P) */ +#define R_CKCORE_PCRELJSR_IMM11BY2 6 /* disp ((S + A - P) >>1) & 0x7ff */ +#define R_CKCORE_RELATIVE 9 /* 32 bit adjust program base(B + A)*/ +#define R_CKCORE_COPY 10 /* 32 bit adjust by program base */ +#define R_CKCORE_GLOB_DAT 11 /* off between got and sym (S) */ +#define R_CKCORE_JUMP_SLOT 12 /* PLT entry (S) */ +#define R_CKCORE_GOTOFF 13 /* offset to GOT (S + A - GOT) */ +#define R_CKCORE_GOTPC 14 /* PC offset to GOT (GOT + A - P) */ +#define R_CKCORE_GOT32 15 /* 32 bit GOT entry (G) */ +#define R_CKCORE_PLT32 16 /* 32 bit PLT entry (G) */ +#define R_CKCORE_ADDRGOT 17 /* GOT entry in GLOB_DAT (GOT + G) */ +#define R_CKCORE_ADDRPLT 18 /* PLT entry in GLOB_DAT (GOT + G) */ +#define R_CKCORE_PCREL_IMM26BY2 19 /* ((S + A - P) >> 1) & 0x3ffffff */ +#define R_CKCORE_PCREL_IMM16BY2 20 /* disp ((S + A - P) >> 1) & 0xffff */ +#define R_CKCORE_PCREL_IMM16BY4 21 /* disp ((S + A - P) >> 2) & 0xffff */ +#define R_CKCORE_PCREL_IMM10BY2 22 /* disp ((S + A - P) >> 1) & 0x3ff */ +#define R_CKCORE_PCREL_IMM10BY4 23 /* disp ((S + A - P) >> 2) & 0x3ff */ +#define R_CKCORE_ADDR_HI16 24 /* high & low 16 bit ADDR */ + /* ((S + A) >> 16) & 0xffff */ +#define R_CKCORE_ADDR_LO16 25 /* (S + A) & 0xffff */ +#define R_CKCORE_GOTPC_HI16 26 /* high & low 16 bit GOTPC */ + /* ((GOT + A - P) >> 16) & 0xffff */ +#define R_CKCORE_GOTPC_LO16 27 /* (GOT + A - P) & 0xffff */ +#define R_CKCORE_GOTOFF_HI16 28 /* high & low 16 bit GOTOFF */ + /* ((S + A - GOT) >> 16) & 0xffff */ +#define R_CKCORE_GOTOFF_LO16 29 /* (S + A - GOT) & 0xffff */ +#define R_CKCORE_GOT12 30 /* 12 bit disp GOT entry (G) */ +#define R_CKCORE_GOT_HI16 31 /* high & low 16 bit GOT */ + /* (G >> 16) & 0xffff */ +#define R_CKCORE_GOT_LO16 32 /* (G & 0xffff) */ +#define R_CKCORE_PLT12 33 /* 12 bit disp PLT entry (G) */ +#define R_CKCORE_PLT_HI16 34 /* high & low 16 bit PLT */ + /* (G >> 16) & 0xffff */ +#define R_CKCORE_PLT_LO16 35 /* G & 0xffff */ +#define R_CKCORE_ADDRGOT_HI16 36 /* high & low 16 bit ADDRGOT */ + /* (GOT + G * 4) & 0xffff */ +#define R_CKCORE_ADDRGOT_LO16 37 /* (GOT + G * 4) & 0xffff */ +#define R_CKCORE_ADDRPLT_HI16 38 /* high & low 16 bit ADDRPLT */ + /* ((GOT + G * 4) >> 16) & 0xFFFF */ +#define R_CKCORE_ADDRPLT_LO16 39 /* (GOT+G*4) & 0xffff */ +#define R_CKCORE_PCREL_JSR_IMM26BY2 40 /* disp ((S+A-P) >>1) & x3ffffff */ +#define R_CKCORE_TOFFSET_LO16 41 /* (S+A-BTEXT) & 0xffff */ +#define R_CKCORE_DOFFSET_LO16 42 /* (S+A-BTEXT) & 0xffff */ +#define R_CKCORE_PCREL_IMM18BY2 43 /* disp ((S+A-P) >>1) & 0x3ffff */ +#define R_CKCORE_DOFFSET_IMM18 44 /* disp (S+A-BDATA) & 0x3ffff */ +#define R_CKCORE_DOFFSET_IMM18BY2 45 /* disp ((S+A-BDATA)>>1) & 0x3ffff */ +#define R_CKCORE_DOFFSET_IMM18BY4 46 /* disp ((S+A-BDATA)>>2) & 0x3ffff */ +#define R_CKCORE_GOT_IMM18BY4 48 /* disp (G >> 2) */ +#define R_CKCORE_PLT_IMM18BY4 49 /* disp (G >> 2) */ +#define R_CKCORE_PCREL_IMM7BY4 50 /* disp ((S+A-P) >>2) & 0x7f */ +#define R_CKCORE_TLS_LE32 51 /* 32 bit offset to TLS block */ +#define R_CKCORE_TLS_IE32 52 +#define R_CKCORE_TLS_GD32 53 +#define R_CKCORE_TLS_LDM32 54 +#define R_CKCORE_TLS_LDO32 55 +#define R_CKCORE_TLS_DTPMOD32 56 +#define R_CKCORE_TLS_DTPOFF32 57 +#define R_CKCORE_TLS_TPOFF32 58 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_SH_MACH_MASK 0x1f +#define EF_SH_UNKNOWN 0x0 +#define EF_SH1 0x1 +#define EF_SH2 0x2 +#define EF_SH3 0x3 +#define EF_SH_DSP 0x4 +#define EF_SH3_DSP 0x5 +#define EF_SH4AL_DSP 0x6 +#define EF_SH3E 0x8 +#define EF_SH4 0x9 +#define EF_SH2E 0xb +#define EF_SH4A 0xc +#define EF_SH2A 0xd +#define EF_SH4_NOFPU 0x10 +#define EF_SH4A_NOFPU 0x11 +#define EF_SH4_NOMMU_NOFPU 0x12 +#define EF_SH2A_NOFPU 0x13 +#define EF_SH3_NOMMU 0x14 +#define EF_SH2A_SH4_NOFPU 0x15 +#define EF_SH2A_SH3_NOFPU 0x16 +#define EF_SH2A_SH4 0x17 +#define EF_SH2A_SH3E 0x18 + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* S/390 specific definitions. */ + +/* Valid values for the e_flags field. */ + +#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ +/* Keep this the last entry. */ +#define R_390_NUM 62 + + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset + to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset + to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS + descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ + /* 39 Reserved was R_X86_64_PC32_BND */ + /* 40 Reserved was R_X86_64_PLT32_BND */ +#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative + offset to GOT entry without REX + prefix, relaxable. */ +#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative + offset to GOT entry with REX prefix, + relaxable. */ +#define R_X86_64_NUM 43 + +/* x86-64 sh_type values. */ +#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */ + + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ +#define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */ +#define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */ +#define R_MN10300_TLS_LDO 26 /* Module-relative offset. */ +#define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block + offset. */ +#define R_MN10300_TLS_IE 28 /* GOT address for static TLS block + offset. */ +#define R_MN10300_TLS_LE 29 /* Offset relative to static TLS + block. */ +#define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */ +#define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */ +#define R_MN10300_TLS_TPOFF 32 /* Offset in static TLS block. */ +#define R_MN10300_SYM_DIFF 33 /* Adjustment for next reloc as needed + by linker relaxation. */ +#define R_MN10300_ALIGN 34 /* Alignment requirement for linker + relaxation. */ +#define R_MN10300_NUM 35 + + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 +#define R_M32R_REL32 45 /* PC relative 32 bit. */ + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned + low */ +#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to + GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to + GOT with signed low */ +#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to + GOT */ +#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT + with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + +/* MicroBlaze relocations */ +#define R_MICROBLAZE_NONE 0 /* No reloc. */ +#define R_MICROBLAZE_32 1 /* Direct 32 bit. */ +#define R_MICROBLAZE_32_PCREL 2 /* PC relative 32 bit. */ +#define R_MICROBLAZE_64_PCREL 3 /* PC relative 64 bit. */ +#define R_MICROBLAZE_32_PCREL_LO 4 /* Low 16 bits of PCREL32. */ +#define R_MICROBLAZE_64 5 /* Direct 64 bit. */ +#define R_MICROBLAZE_32_LO 6 /* Low 16 bit. */ +#define R_MICROBLAZE_SRO32 7 /* Read-only small data area. */ +#define R_MICROBLAZE_SRW32 8 /* Read-write small data area. */ +#define R_MICROBLAZE_64_NONE 9 /* No reloc. */ +#define R_MICROBLAZE_32_SYM_OP_SYM 10 /* Symbol Op Symbol relocation. */ +#define R_MICROBLAZE_GNU_VTINHERIT 11 /* GNU C++ vtable hierarchy. */ +#define R_MICROBLAZE_GNU_VTENTRY 12 /* GNU C++ vtable member usage. */ +#define R_MICROBLAZE_GOTPC_64 13 /* PC-relative GOT offset. */ +#define R_MICROBLAZE_GOT_64 14 /* GOT entry offset. */ +#define R_MICROBLAZE_PLT_64 15 /* PLT offset (PC-relative). */ +#define R_MICROBLAZE_REL 16 /* Adjust by program base. */ +#define R_MICROBLAZE_JUMP_SLOT 17 /* Create PLT entry. */ +#define R_MICROBLAZE_GLOB_DAT 18 /* Create GOT entry. */ +#define R_MICROBLAZE_GOTOFF_64 19 /* 64 bit offset to GOT. */ +#define R_MICROBLAZE_GOTOFF_32 20 /* 32 bit offset to GOT. */ +#define R_MICROBLAZE_COPY 21 /* Runtime copy. */ +#define R_MICROBLAZE_TLS 22 /* TLS Reloc. */ +#define R_MICROBLAZE_TLSGD 23 /* TLS General Dynamic. */ +#define R_MICROBLAZE_TLSLD 24 /* TLS Local Dynamic. */ +#define R_MICROBLAZE_TLSDTPMOD32 25 /* TLS Module ID. */ +#define R_MICROBLAZE_TLSDTPREL32 26 /* TLS Offset Within TLS Block. */ +#define R_MICROBLAZE_TLSDTPREL64 27 /* TLS Offset Within TLS Block. */ +#define R_MICROBLAZE_TLSGOTTPREL32 28 /* TLS Offset From Thread Pointer. */ +#define R_MICROBLAZE_TLSTPREL32 29 /* TLS Offset From Thread Pointer. */ + +/* Legal values for d_tag (dynamic entry type). */ +#define DT_NIOS2_GP 0x70000002 /* Address of _gp. */ + +/* Nios II relocations. */ +#define R_NIOS2_NONE 0 /* No reloc. */ +#define R_NIOS2_S16 1 /* Direct signed 16 bit. */ +#define R_NIOS2_U16 2 /* Direct unsigned 16 bit. */ +#define R_NIOS2_PCREL16 3 /* PC relative 16 bit. */ +#define R_NIOS2_CALL26 4 /* Direct call. */ +#define R_NIOS2_IMM5 5 /* 5 bit constant expression. */ +#define R_NIOS2_CACHE_OPX 6 /* 5 bit expression, shift 22. */ +#define R_NIOS2_IMM6 7 /* 6 bit constant expression. */ +#define R_NIOS2_IMM8 8 /* 8 bit constant expression. */ +#define R_NIOS2_HI16 9 /* High 16 bit. */ +#define R_NIOS2_LO16 10 /* Low 16 bit. */ +#define R_NIOS2_HIADJ16 11 /* High 16 bit, adjusted. */ +#define R_NIOS2_BFD_RELOC_32 12 /* 32 bit symbol value + addend. */ +#define R_NIOS2_BFD_RELOC_16 13 /* 16 bit symbol value + addend. */ +#define R_NIOS2_BFD_RELOC_8 14 /* 8 bit symbol value + addend. */ +#define R_NIOS2_GPREL 15 /* 16 bit GP pointer offset. */ +#define R_NIOS2_GNU_VTINHERIT 16 /* GNU C++ vtable hierarchy. */ +#define R_NIOS2_GNU_VTENTRY 17 /* GNU C++ vtable member usage. */ +#define R_NIOS2_UJMP 18 /* Unconditional branch. */ +#define R_NIOS2_CJMP 19 /* Conditional branch. */ +#define R_NIOS2_CALLR 20 /* Indirect call through register. */ +#define R_NIOS2_ALIGN 21 /* Alignment requirement for + linker relaxation. */ +#define R_NIOS2_GOT16 22 /* 16 bit GOT entry. */ +#define R_NIOS2_CALL16 23 /* 16 bit GOT entry for function. */ +#define R_NIOS2_GOTOFF_LO 24 /* %lo of offset to GOT pointer. */ +#define R_NIOS2_GOTOFF_HA 25 /* %hiadj of offset to GOT pointer. */ +#define R_NIOS2_PCREL_LO 26 /* %lo of PC relative offset. */ +#define R_NIOS2_PCREL_HA 27 /* %hiadj of PC relative offset. */ +#define R_NIOS2_TLS_GD16 28 /* 16 bit GOT offset for TLS GD. */ +#define R_NIOS2_TLS_LDM16 29 /* 16 bit GOT offset for TLS LDM. */ +#define R_NIOS2_TLS_LDO16 30 /* 16 bit module relative offset. */ +#define R_NIOS2_TLS_IE16 31 /* 16 bit GOT offset for TLS IE. */ +#define R_NIOS2_TLS_LE16 32 /* 16 bit LE TP-relative offset. */ +#define R_NIOS2_TLS_DTPMOD 33 /* Module number. */ +#define R_NIOS2_TLS_DTPREL 34 /* Module-relative offset. */ +#define R_NIOS2_TLS_TPREL 35 /* TP-relative offset. */ +#define R_NIOS2_COPY 36 /* Copy symbol at runtime. */ +#define R_NIOS2_GLOB_DAT 37 /* Create GOT entry. */ +#define R_NIOS2_JUMP_SLOT 38 /* Create PLT entry. */ +#define R_NIOS2_RELATIVE 39 /* Adjust by program base. */ +#define R_NIOS2_GOTOFF 40 /* 16 bit offset to GOT pointer. */ +#define R_NIOS2_CALL26_NOAT 41 /* Direct call in .noat section. */ +#define R_NIOS2_GOT_LO 42 /* %lo() of GOT entry. */ +#define R_NIOS2_GOT_HA 43 /* %hiadj() of GOT entry. */ +#define R_NIOS2_CALL_LO 44 /* %lo() of function GOT entry. */ +#define R_NIOS2_CALL_HA 45 /* %hiadj() of function GOT entry. */ + +/* TILEPro relocations. */ +#define R_TILEPRO_NONE 0 /* No reloc */ +#define R_TILEPRO_32 1 /* Direct 32 bit */ +#define R_TILEPRO_16 2 /* Direct 16 bit */ +#define R_TILEPRO_8 3 /* Direct 8 bit */ +#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ +#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ +#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ +#define R_TILEPRO_LO16 7 /* Low 16 bit */ +#define R_TILEPRO_HI16 8 /* High 16 bit */ +#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ +#define R_TILEPRO_COPY 10 /* Copy relocation */ +#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ +#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ +#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ +#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ +#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ +#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ +#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ +#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ +#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ +#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ +#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ +#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ +#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ +#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ +#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ +#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ +#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ +#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ +#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ +#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ +#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ +#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ +#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ +#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ +#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ +#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ +#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ +#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ +#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ +#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ +#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ +#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ +#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ +#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ +#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ +#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ +#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ +#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ +#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ +/* Relocs 56-59 are currently not defined. */ +#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ +#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ +#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ +#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ +#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ +#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ +#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ +#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ +#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ +#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ +#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ +#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ +#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ +#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ + +#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ +#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ + +#define R_TILEPRO_NUM 130 + + +/* TILE-Gx relocations. */ +#define R_TILEGX_NONE 0 /* No reloc */ +#define R_TILEGX_64 1 /* Direct 64 bit */ +#define R_TILEGX_32 2 /* Direct 32 bit */ +#define R_TILEGX_16 3 /* Direct 16 bit */ +#define R_TILEGX_8 4 /* Direct 8 bit */ +#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ +#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ +#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ +#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ +#define R_TILEGX_HW0 9 /* hword 0 16-bit */ +#define R_TILEGX_HW1 10 /* hword 1 16-bit */ +#define R_TILEGX_HW2 11 /* hword 2 16-bit */ +#define R_TILEGX_HW3 12 /* hword 3 16-bit */ +#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ +#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ +#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ +#define R_TILEGX_COPY 16 /* Copy relocation */ +#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ +#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ +#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ +#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ +#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ +#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ +#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ +#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ +#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ +#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ +#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ +#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ +#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ +#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ +#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ +#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ +#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ +#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ +#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ +#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ +#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ +#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ +#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ +#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ +#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ +#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ +#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ +#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ +#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ +#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ +#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ +#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ +#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ +#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ +#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ +#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ +#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ +#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ +#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ +#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ +#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ +#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ +#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ +#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ +#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ +#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ +#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ +#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ +#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ +#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */ +#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */ +#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */ +#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */ +#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */ +#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */ +#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ +#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ +#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ +#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ +#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */ +#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */ +#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ +#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ +#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ +#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ +#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ +#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ +#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ +#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ +#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ +#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ +#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ +#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ +/* Relocs 90-91 are currently not defined. */ +#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ +#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ +#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */ +#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */ +#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */ +#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */ +#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */ +#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */ +#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ +#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ +#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ +#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ +/* Relocs 104-105 are currently not defined. */ +#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ +#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ +#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ +#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ +#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ +#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ +#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ +#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ +#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ +#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ +#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ +#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ +#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ +#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ +#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ +#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ + +#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ +#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ + +#define R_TILEGX_NUM 130 + +/* RISC-V ELF Flags */ +#define EF_RISCV_RVC 0x0001 +#define EF_RISCV_FLOAT_ABI 0x0006 +#define EF_RISCV_FLOAT_ABI_SOFT 0x0000 +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002 +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004 +#define EF_RISCV_FLOAT_ABI_QUAD 0x0006 + +/* RISC-V relocations. */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#define R_RISCV_32_PCREL 57 + +#define R_RISCV_NUM 58 + +/* BPF specific declarations. */ + +#define R_BPF_NONE 0 /* No reloc */ +#define R_BPF_64_64 1 +#define R_BPF_64_32 10 + +/* Imagination Meta specific relocations. */ + +#define R_METAG_HIADDR16 0 +#define R_METAG_LOADDR16 1 +#define R_METAG_ADDR32 2 /* 32bit absolute address */ +#define R_METAG_NONE 3 /* No reloc */ +#define R_METAG_RELBRANCH 4 +#define R_METAG_GETSETOFF 5 + +/* Backward compatability */ +#define R_METAG_REG32OP1 6 +#define R_METAG_REG32OP2 7 +#define R_METAG_REG32OP3 8 +#define R_METAG_REG16OP1 9 +#define R_METAG_REG16OP2 10 +#define R_METAG_REG16OP3 11 +#define R_METAG_REG32OP4 12 + +#define R_METAG_HIOG 13 +#define R_METAG_LOOG 14 + +#define R_METAG_REL8 15 +#define R_METAG_REL16 16 + +/* GNU */ +#define R_METAG_GNU_VTINHERIT 30 +#define R_METAG_GNU_VTENTRY 31 + +/* PIC relocations */ +#define R_METAG_HI16_GOTOFF 32 +#define R_METAG_LO16_GOTOFF 33 +#define R_METAG_GETSET_GOTOFF 34 +#define R_METAG_GETSET_GOT 35 +#define R_METAG_HI16_GOTPC 36 +#define R_METAG_LO16_GOTPC 37 +#define R_METAG_HI16_PLT 38 +#define R_METAG_LO16_PLT 39 +#define R_METAG_RELBRANCH_PLT 40 +#define R_METAG_GOTOFF 41 +#define R_METAG_PLT 42 +#define R_METAG_COPY 43 +#define R_METAG_JMP_SLOT 44 +#define R_METAG_RELATIVE 45 +#define R_METAG_GLOB_DAT 46 + +/* TLS relocations */ +#define R_METAG_TLS_GD 47 +#define R_METAG_TLS_LDM 48 +#define R_METAG_TLS_LDO_HI16 49 +#define R_METAG_TLS_LDO_LO16 50 +#define R_METAG_TLS_LDO 51 +#define R_METAG_TLS_IE 52 +#define R_METAG_TLS_IENONPIC 53 +#define R_METAG_TLS_IENONPIC_HI16 54 +#define R_METAG_TLS_IENONPIC_LO16 55 +#define R_METAG_TLS_TPOFF 56 +#define R_METAG_TLS_DTPMOD 57 +#define R_METAG_TLS_DTPOFF 58 +#define R_METAG_TLS_LE 59 +#define R_METAG_TLS_LE_HI16 60 +#define R_METAG_TLS_LE_LO16 61 + +/* NDS32 relocations. */ +#define R_NDS32_NONE 0 +#define R_NDS32_32_RELA 20 +#define R_NDS32_COPY 39 +#define R_NDS32_GLOB_DAT 40 +#define R_NDS32_JMP_SLOT 41 +#define R_NDS32_RELATIVE 42 +#define R_NDS32_TLS_TPOFF 102 +#define R_NDS32_TLS_DESC 119 + +#ifdef __cplusplus +} +#endif + +#endif /* elf.h */
diff --git a/third_party/crashpad/crashpad/third_party/xnu/APPLE_LICENSE b/third_party/crashpad/crashpad/third_party/xnu/APPLE_LICENSE new file mode 100644 index 0000000..fe81a60 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/xnu/APPLE_LICENSE
@@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License."
diff --git a/third_party/crashpad/crashpad/third_party/xnu/BUILD.gn b/third_party/crashpad/crashpad/third_party/xnu/BUILD.gn new file mode 100644 index 0000000..b6a9404 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/xnu/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2019 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +source_set("xnu") { + sources = [ + "EXTERNAL_HEADERS/mach-o/loader.h", + ] +}
diff --git a/third_party/crashpad/crashpad/third_party/xnu/EXTERNAL_HEADERS/mach-o/loader.h b/third_party/crashpad/crashpad/third_party/xnu/EXTERNAL_HEADERS/mach-o/loader.h new file mode 100644 index 0000000..3b7f0ee --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/xnu/EXTERNAL_HEADERS/mach-o/loader.h
@@ -0,0 +1,1531 @@ +/* + * Copyright (c) 1999-2010 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef _MACHO_LOADER_H_ +#define _MACHO_LOADER_H_ + +/* + * This file describes the format of mach object files. + */ +#include <stdint.h> + +/* + * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types + * and contains the constants for the possible values of these types. + */ +#include <mach/machine.h> + +/* + * <mach/vm_prot.h> is needed here for the vm_prot_t type and contains the + * constants that are or'ed together for the possible values of this type. + */ +#include <mach/vm_prot.h> + +/* + * The 32-bit mach header appears at the very beginning of the object file for + * 32-bit architectures. + */ +struct mach_header { + uint32_t magic; /* mach magic number identifier */ + cpu_type_t cputype; /* cpu specifier */ + cpu_subtype_t cpusubtype; /* machine specifier */ + uint32_t filetype; /* type of file */ + uint32_t ncmds; /* number of load commands */ + uint32_t sizeofcmds; /* the size of all the load commands */ + uint32_t flags; /* flags */ +}; + +/* Constant for the magic field of the mach_header (32-bit architectures) */ +#define MH_MAGIC 0xfeedface /* the mach magic number */ +#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ + +/* + * The 64-bit mach header appears at the very beginning of object files for + * 64-bit architectures. + */ +struct mach_header_64 { + uint32_t magic; /* mach magic number identifier */ + cpu_type_t cputype; /* cpu specifier */ + cpu_subtype_t cpusubtype; /* machine specifier */ + uint32_t filetype; /* type of file */ + uint32_t ncmds; /* number of load commands */ + uint32_t sizeofcmds; /* the size of all the load commands */ + uint32_t flags; /* flags */ + uint32_t reserved; /* reserved */ +}; + +/* Constant for the magic field of the mach_header_64 (64-bit architectures) */ +#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ +#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ + +/* + * The layout of the file depends on the filetype. For all but the MH_OBJECT + * file type the segments are padded out and aligned on a segment alignment + * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB, + * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part + * of their first segment. + * + * The file type MH_OBJECT is a compact format intended as output of the + * assembler and input (and possibly output) of the link editor (the .o + * format). All sections are in one unnamed segment with no segment padding. + * This format is used as an executable format when the file is so small the + * segment padding greatly increases its size. + * + * The file type MH_PRELOAD is an executable format intended for things that + * are not executed under the kernel (proms, stand alones, kernels, etc). The + * format can be executed under the kernel but may demand paged it and not + * preload it before execution. + * + * A core file is in MH_CORE format and can be any in an arbritray legal + * Mach-O file. + * + * Constants for the filetype field of the mach_header + */ +#define MH_OBJECT 0x1 /* relocatable object file */ +#define MH_EXECUTE 0x2 /* demand paged executable file */ +#define MH_FVMLIB 0x3 /* fixed VM shared library file */ +#define MH_CORE 0x4 /* core file */ +#define MH_PRELOAD 0x5 /* preloaded executable file */ +#define MH_DYLIB 0x6 /* dynamically bound shared library */ +#define MH_DYLINKER 0x7 /* dynamic link editor */ +#define MH_BUNDLE 0x8 /* dynamically bound bundle file */ +#define MH_DYLIB_STUB 0x9 /* shared library stub for static */ + /* linking only, no section contents */ +#define MH_DSYM 0xa /* companion file with only debug */ + /* sections */ +#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */ + +/* Constants for the flags field of the mach_header */ +#define MH_NOUNDEFS 0x1 /* the object file has no undefined + references */ +#define MH_INCRLINK 0x2 /* the object file is the output of an + incremental link against a base file + and can't be link edited again */ +#define MH_DYLDLINK 0x4 /* the object file is input for the + dynamic linker and can't be staticly + link edited again */ +#define MH_BINDATLOAD 0x8 /* the object file's undefined + references are bound by the dynamic + linker when loaded. */ +#define MH_PREBOUND 0x10 /* the file has its dynamic undefined + references prebound. */ +#define MH_SPLIT_SEGS 0x20 /* the file has its read-only and + read-write segments split */ +#define MH_LAZY_INIT 0x40 /* the shared library init routine is + to be run lazily via catching memory + faults to its writeable segments + (obsolete) */ +#define MH_TWOLEVEL 0x80 /* the image is using two-level name + space bindings */ +#define MH_FORCE_FLAT 0x100 /* the executable is forcing all images + to use flat name space bindings */ +#define MH_NOMULTIDEFS 0x200 /* this umbrella guarantees no multiple + defintions of symbols in its + sub-images so the two-level namespace + hints can always be used. */ +#define MH_NOFIXPREBINDING 0x400 /* do not have dyld notify the + prebinding agent about this + executable */ +#define MH_PREBINDABLE 0x800 /* the binary is not prebound but can + have its prebinding redone. only used + when MH_PREBOUND is not set. */ +#define MH_ALLMODSBOUND 0x1000 /* indicates that this binary binds to + all two-level namespace modules of + its dependent libraries. only used + when MH_PREBINDABLE and MH_TWOLEVEL + are both set. */ +#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000/* safe to divide up the sections into + sub-sections via symbols for dead + code stripping */ +#define MH_CANONICAL 0x4000 /* the binary has been canonicalized + via the unprebind operation */ +#define MH_WEAK_DEFINES 0x8000 /* the final linked image contains + external weak symbols */ +#define MH_BINDS_TO_WEAK 0x10000 /* the final linked image uses + weak symbols */ + +#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks + in the task will be given stack + execution privilege. Only used in + MH_EXECUTE filetypes. */ +#define MH_ROOT_SAFE 0x40000 /* When this bit is set, the binary + declares it is safe for use in + processes with uid zero */ + +#define MH_SETUID_SAFE 0x80000 /* When this bit is set, the binary + declares it is safe for use in + processes when issetugid() is true */ + +#define MH_NO_REEXPORTED_DYLIBS 0x100000 /* When this bit is set on a dylib, + the static linker does not need to + examine dependent dylibs to see + if any are re-exported */ +#define MH_PIE 0x200000 /* When this bit is set, the OS will + load the main executable at a + random address. Only used in + MH_EXECUTE filetypes. */ +#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 /* Only for use on dylibs. When + linking against a dylib that + has this bit set, the static linker + will automatically not create a + LC_LOAD_DYLIB load command to the + dylib if no symbols are being + referenced from the dylib. */ +#define MH_HAS_TLV_DESCRIPTORS 0x800000 /* Contains a section of type + S_THREAD_LOCAL_VARIABLES */ + +#define MH_NO_HEAP_EXECUTION 0x1000000 /* When this bit is set, the OS will + run the main executable with + a non-executable heap even on + platforms (e.g. i386) that don't + require it. Only used in MH_EXECUTE + filetypes. */ + +#define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an + application extension. */ + +/* + * The load commands directly follow the mach_header. The total size of all + * of the commands is given by the sizeofcmds field in the mach_header. All + * load commands must have as their first two fields cmd and cmdsize. The cmd + * field is filled in with a constant for that command type. Each command type + * has a structure specifically for it. The cmdsize field is the size in bytes + * of the particular load command structure plus anything that follows it that + * is a part of the load command (i.e. section structures, strings, etc.). To + * advance to the next load command the cmdsize can be added to the offset or + * pointer of the current load command. The cmdsize for 32-bit architectures + * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple + * of 8 bytes (these are forever the maximum alignment of any load commands). + * The padded bytes must be zero. All tables in the object file must also + * follow these rules so the file can be memory mapped. Otherwise the pointers + * to these tables will not work well or at all on some machines. With all + * padding zeroed like objects will compare byte for byte. + */ +struct load_command { + uint32_t cmd; /* type of load command */ + uint32_t cmdsize; /* total size of command in bytes */ +}; + +/* + * After MacOS X 10.1 when a new load command is added that is required to be + * understood by the dynamic linker for the image to execute properly the + * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic + * linker sees such a load command it it does not understand will issue a + * "unknown load command required for execution" error and refuse to use the + * image. Other load commands without this bit that are not understood will + * simply be ignored. + */ +#define LC_REQ_DYLD 0x80000000 + +/* Constants for the cmd field of all load commands, the type */ +#define LC_SEGMENT 0x1 /* segment of this file to be mapped */ +#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */ +#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */ +#define LC_THREAD 0x4 /* thread */ +#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */ +#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */ +#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */ +#define LC_IDENT 0x8 /* object identification info (obsolete) */ +#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */ +#define LC_PREPAGE 0xa /* prepage command (internal use) */ +#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */ +#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */ +#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */ +#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */ +#define LC_ID_DYLINKER 0xf /* dynamic linker identification */ +#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */ + /* linked shared library */ +#define LC_ROUTINES 0x11 /* image routines */ +#define LC_SUB_FRAMEWORK 0x12 /* sub framework */ +#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */ +#define LC_SUB_CLIENT 0x14 /* sub client */ +#define LC_SUB_LIBRARY 0x15 /* sub library */ +#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */ +#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */ + +/* + * load a dynamically linked shared library that is allowed to be missing + * (all symbols are weak imported). + */ +#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) + +#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be + mapped */ +#define LC_ROUTINES_64 0x1a /* 64-bit image routines */ +#define LC_UUID 0x1b /* the uuid */ +#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */ +#define LC_CODE_SIGNATURE 0x1d /* local of code signature */ +#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */ +#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */ +#define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */ +#define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */ +#define LC_DYLD_INFO 0x22 /* compressed dyld information */ +#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */ +#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */ +#define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */ +#define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */ +#define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */ +#define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat + like environment variable */ +#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ +#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */ +#define LC_SOURCE_VERSION 0x2A /* source version used to build binary */ +#define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */ +#define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */ +#define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */ +#define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */ +#define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */ +#define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ +#define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ +#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ + +/* + * A variable length string in a load command is represented by an lc_str + * union. The strings are stored just after the load command structure and + * the offset is from the start of the load command structure. The size + * of the string is reflected in the cmdsize field of the load command. + * Once again any padded bytes to bring the cmdsize field to a multiple + * of 4 bytes must be zero. + */ +union lc_str { + uint32_t offset; /* offset to the string */ +#ifndef __LP64__ + char *ptr; /* pointer to the string */ +#endif +}; + +/* + * The segment load command indicates that a part of this file is to be + * mapped into the task's address space. The size of this segment in memory, + * vmsize, maybe equal to or larger than the amount to map from this file, + * filesize. The file is mapped starting at fileoff to the beginning of + * the segment in memory, vmaddr. The rest of the memory of the segment, + * if any, is allocated zero fill on demand. The segment's maximum virtual + * memory protection and initial virtual memory protection are specified + * by the maxprot and initprot fields. If the segment has sections then the + * section structures directly follow the segment command and their size is + * reflected in cmdsize. + */ +struct segment_command { /* for 32-bit architectures */ + uint32_t cmd; /* LC_SEGMENT */ + uint32_t cmdsize; /* includes sizeof section structs */ + char segname[16]; /* segment name */ + uint32_t vmaddr; /* memory address of this segment */ + uint32_t vmsize; /* memory size of this segment */ + uint32_t fileoff; /* file offset of this segment */ + uint32_t filesize; /* amount to map from the file */ + vm_prot_t maxprot; /* maximum VM protection */ + vm_prot_t initprot; /* initial VM protection */ + uint32_t nsects; /* number of sections in segment */ + uint32_t flags; /* flags */ +}; + +/* + * The 64-bit segment load command indicates that a part of this file is to be + * mapped into a 64-bit task's address space. If the 64-bit segment has + * sections then section_64 structures directly follow the 64-bit segment + * command and their size is reflected in cmdsize. + */ +struct segment_command_64 { /* for 64-bit architectures */ + uint32_t cmd; /* LC_SEGMENT_64 */ + uint32_t cmdsize; /* includes sizeof section_64 structs */ + char segname[16]; /* segment name */ + uint64_t vmaddr; /* memory address of this segment */ + uint64_t vmsize; /* memory size of this segment */ + uint64_t fileoff; /* file offset of this segment */ + uint64_t filesize; /* amount to map from the file */ + vm_prot_t maxprot; /* maximum VM protection */ + vm_prot_t initprot; /* initial VM protection */ + uint32_t nsects; /* number of sections in segment */ + uint32_t flags; /* flags */ +}; + +/* Constants for the flags field of the segment_command */ +#define SG_HIGHVM 0x1 /* the file contents for this segment is for + the high part of the VM space, the low part + is zero filled (for stacks in core files) */ +#define SG_FVMLIB 0x2 /* this segment is the VM that is allocated by + a fixed VM library, for overlap checking in + the link editor */ +#define SG_NORELOC 0x4 /* this segment has nothing that was relocated + in it and nothing relocated to it, that is + it maybe safely replaced without relocation*/ +#define SG_PROTECTED_VERSION_1 0x8 /* This segment is protected. If the + segment starts at file offset 0, the + first page of the segment is not + protected. All other pages of the + segment are protected. */ + +/* + * A segment is made up of zero or more sections. Non-MH_OBJECT files have + * all of their segments with the proper sections in each, and padded to the + * specified segment alignment when produced by the link editor. The first + * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header + * and load commands of the object file before its first section. The zero + * fill sections are always last in their segment (in all formats). This + * allows the zeroed segment padding to be mapped into memory where zero fill + * sections might be. The gigabyte zero fill sections, those with the section + * type S_GB_ZEROFILL, can only be in a segment with sections of this type. + * These segments are then placed after all other segments. + * + * The MH_OBJECT format has all of its sections in one segment for + * compactness. There is no padding to a specified segment boundary and the + * mach_header and load commands are not part of the segment. + * + * Sections with the same section name, sectname, going into the same segment, + * segname, are combined by the link editor. The resulting section is aligned + * to the maximum alignment of the combined sections and is the new section's + * alignment. The combined sections are aligned to their original alignment in + * the combined section. Any padded bytes to get the specified alignment are + * zeroed. + * + * The format of the relocation entries referenced by the reloff and nreloc + * fields of the section structure for mach object files is described in the + * header file <reloc.h>. + */ +struct section { /* for 32-bit architectures */ + char sectname[16]; /* name of this section */ + char segname[16]; /* segment this section goes in */ + uint32_t addr; /* memory address of this section */ + uint32_t size; /* size in bytes of this section */ + uint32_t offset; /* file offset of this section */ + uint32_t align; /* section alignment (power of 2) */ + uint32_t reloff; /* file offset of relocation entries */ + uint32_t nreloc; /* number of relocation entries */ + uint32_t flags; /* flags (section type and attributes)*/ + uint32_t reserved1; /* reserved (for offset or index) */ + uint32_t reserved2; /* reserved (for count or sizeof) */ +}; + +struct section_64 { /* for 64-bit architectures */ + char sectname[16]; /* name of this section */ + char segname[16]; /* segment this section goes in */ + uint64_t addr; /* memory address of this section */ + uint64_t size; /* size in bytes of this section */ + uint32_t offset; /* file offset of this section */ + uint32_t align; /* section alignment (power of 2) */ + uint32_t reloff; /* file offset of relocation entries */ + uint32_t nreloc; /* number of relocation entries */ + uint32_t flags; /* flags (section type and attributes)*/ + uint32_t reserved1; /* reserved (for offset or index) */ + uint32_t reserved2; /* reserved (for count or sizeof) */ + uint32_t reserved3; /* reserved */ +}; + +/* + * The flags field of a section structure is separated into two parts a section + * type and section attributes. The section types are mutually exclusive (it + * can only have one type) but the section attributes are not (it may have more + * than one attribute). + */ +#define SECTION_TYPE 0x000000ff /* 256 section types */ +#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */ + +/* Constants for the type of a section */ +#define S_REGULAR 0x0 /* regular section */ +#define S_ZEROFILL 0x1 /* zero fill on demand section */ +#define S_CSTRING_LITERALS 0x2 /* section with only literal C strings*/ +#define S_4BYTE_LITERALS 0x3 /* section with only 4 byte literals */ +#define S_8BYTE_LITERALS 0x4 /* section with only 8 byte literals */ +#define S_LITERAL_POINTERS 0x5 /* section with only pointers to */ + /* literals */ +/* + * For the two types of symbol pointers sections and the symbol stubs section + * they have indirect symbol table entries. For each of the entries in the + * section the indirect symbol table entries, in corresponding order in the + * indirect symbol table, start at the index stored in the reserved1 field + * of the section structure. Since the indirect symbol table entries + * correspond to the entries in the section the number of indirect symbol table + * entries is inferred from the size of the section divided by the size of the + * entries in the section. For symbol pointers sections the size of the entries + * in the section is 4 bytes and for symbol stubs sections the byte size of the + * stubs is stored in the reserved2 field of the section structure. + */ +#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* section with only non-lazy + symbol pointers */ +#define S_LAZY_SYMBOL_POINTERS 0x7 /* section with only lazy symbol + pointers */ +#define S_SYMBOL_STUBS 0x8 /* section with only symbol + stubs, byte size of stub in + the reserved2 field */ +#define S_MOD_INIT_FUNC_POINTERS 0x9 /* section with only function + pointers for initialization*/ +#define S_MOD_TERM_FUNC_POINTERS 0xa /* section with only function + pointers for termination */ +#define S_COALESCED 0xb /* section contains symbols that + are to be coalesced */ +#define S_GB_ZEROFILL 0xc /* zero fill on demand section + (that can be larger than 4 + gigabytes) */ +#define S_INTERPOSING 0xd /* section with only pairs of + function pointers for + interposing */ +#define S_16BYTE_LITERALS 0xe /* section with only 16 byte + literals */ +#define S_DTRACE_DOF 0xf /* section contains + DTrace Object Format */ +#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 /* section with only lazy + symbol pointers to lazy + loaded dylibs */ +/* + * Section types to support thread local variables + */ +#define S_THREAD_LOCAL_REGULAR 0x11 /* template of initial + values for TLVs */ +#define S_THREAD_LOCAL_ZEROFILL 0x12 /* template of initial + values for TLVs */ +#define S_THREAD_LOCAL_VARIABLES 0x13 /* TLV descriptors */ +#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 /* pointers to TLV + descriptors */ +#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call + to initialize TLV + values */ + +/* + * Constants for the section attributes part of the flags field of a section + * structure. + */ +#define SECTION_ATTRIBUTES_USR 0xff000000 /* User setable attributes */ +#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section contains only true + machine instructions */ +#define S_ATTR_NO_TOC 0x40000000 /* section contains coalesced + symbols that are not to be + in a ranlib table of + contents */ +#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 /* ok to strip static symbols + in this section in files + with the MH_DYLDLINK flag */ +#define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */ +#define S_ATTR_LIVE_SUPPORT 0x08000000 /* blocks are live if they + reference live blocks */ +#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 /* Used with i386 code stubs + written on by dyld */ +/* + * If a segment contains any sections marked with S_ATTR_DEBUG then all + * sections in that segment must have this attribute. No section other than + * a section marked with this attribute may reference the contents of this + * section. A section with this attribute may contain no symbols and must have + * a section type S_REGULAR. The static linker will not copy section contents + * from sections with this attribute into its output file. These sections + * generally contain DWARF debugging info. + */ +#define S_ATTR_DEBUG 0x02000000 /* a debug section */ +#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */ +#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some + machine instructions */ +#define S_ATTR_EXT_RELOC 0x00000200 /* section has external + relocation entries */ +#define S_ATTR_LOC_RELOC 0x00000100 /* section has local + relocation entries */ + + +/* + * The names of segments and sections in them are mostly meaningless to the + * link-editor. But there are few things to support traditional UNIX + * executables that require the link-editor and assembler to use some names + * agreed upon by convention. + * + * The initial protection of the "__TEXT" segment has write protection turned + * off (not writeable). + * + * The link-editor will allocate common symbols at the end of the "__common" + * section in the "__DATA" segment. It will create the section and segment + * if needed. + */ + +/* The currently known segment names and the section names in those segments */ + +#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */ + /* protections and catches NULL */ + /* references for MH_EXECUTE files */ + + +#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */ +#define SECT_TEXT "__text" /* the real text part of the text */ + /* section no headers, and no padding */ +#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */ + /* section */ +#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */ + /* fvmlib initialization */ + /* section */ + +#define SEG_DATA "__DATA" /* the tradition UNIX data segment */ +#define SECT_DATA "__data" /* the real initialized data section */ + /* no padding, no bss overlap */ +#define SECT_BSS "__bss" /* the real uninitialized data section*/ + /* no padding */ +#define SECT_COMMON "__common" /* the section common symbols are */ + /* allocated in by the link editor */ + +#define SEG_OBJC "__OBJC" /* objective-C runtime segment */ +#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */ +#define SECT_OBJC_MODULES "__module_info" /* module information */ +#define SECT_OBJC_STRINGS "__selector_strs" /* string table */ +#define SECT_OBJC_REFS "__selector_refs" /* string table */ + +#define SEG_ICON "__ICON" /* the icon segment */ +#define SECT_ICON_HEADER "__header" /* the icon headers */ +#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */ + +#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */ + /* created and maintained by the link */ + /* editor. Created with -seglinkedit */ + /* option to ld(1) for MH_EXECUTE and */ + /* FVMLIB file types only */ + +#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */ + +#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */ + /* modifing code stubs that has read, */ + /* write and execute permissions */ + +/* + * Fixed virtual memory shared libraries are identified by two things. The + * target pathname (the name of the library as found for execution), and the + * minor version number. The address of where the headers are loaded is in + * header_addr. (THIS IS OBSOLETE and no longer supported). + */ +struct fvmlib { + union lc_str name; /* library's target pathname */ + uint32_t minor_version; /* library's minor version number */ + uint32_t header_addr; /* library's header address */ +}; + +/* + * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header) + * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library. + * An object that uses a fixed virtual shared library also contains a + * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses. + * (THIS IS OBSOLETE and no longer supported). + */ +struct fvmlib_command { + uint32_t cmd; /* LC_IDFVMLIB or LC_LOADFVMLIB */ + uint32_t cmdsize; /* includes pathname string */ + struct fvmlib fvmlib; /* the library identification */ +}; + +/* + * Dynamicly linked shared libraries are identified by two things. The + * pathname (the name of the library as found for execution), and the + * compatibility version number. The pathname must match and the compatibility + * number in the user of the library must be greater than or equal to the + * library being used. The time stamp is used to record the time a library was + * built and copied into user so it can be use to determined if the library used + * at runtime is exactly the same as used to built the program. + */ +struct dylib { + union lc_str name; /* library's path name */ + uint32_t timestamp; /* library's build time stamp */ + uint32_t current_version; /* library's current version number */ + uint32_t compatibility_version; /* library's compatibility vers number*/ +}; + +/* + * A dynamically linked shared library (filetype == MH_DYLIB in the mach header) + * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library. + * An object that uses a dynamically linked shared library also contains a + * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or + * LC_REEXPORT_DYLIB) for each library it uses. + */ +struct dylib_command { + uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, + LC_REEXPORT_DYLIB */ + uint32_t cmdsize; /* includes pathname string */ + struct dylib dylib; /* the library identification */ +}; + +/* + * A dynamically linked shared library may be a subframework of an umbrella + * framework. If so it will be linked with "-umbrella umbrella_name" where + * Where "umbrella_name" is the name of the umbrella framework. A subframework + * can only be linked against by its umbrella framework or other subframeworks + * that are part of the same umbrella framework. Otherwise the static link + * editor produces an error and states to link against the umbrella framework. + * The name of the umbrella framework for subframeworks is recorded in the + * following structure. + */ +struct sub_framework_command { + uint32_t cmd; /* LC_SUB_FRAMEWORK */ + uint32_t cmdsize; /* includes umbrella string */ + union lc_str umbrella; /* the umbrella framework name */ +}; + +/* + * For dynamically linked shared libraries that are subframework of an umbrella + * framework they can allow clients other than the umbrella framework or other + * subframeworks in the same umbrella framework. To do this the subframework + * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load + * command is created for each -allowable_client flag. The client_name is + * usually a framework name. It can also be a name used for bundles clients + * where the bundle is built with "-client_name client_name". + */ +struct sub_client_command { + uint32_t cmd; /* LC_SUB_CLIENT */ + uint32_t cmdsize; /* includes client string */ + union lc_str client; /* the client name */ +}; + +/* + * A dynamically linked shared library may be a sub_umbrella of an umbrella + * framework. If so it will be linked with "-sub_umbrella umbrella_name" where + * Where "umbrella_name" is the name of the sub_umbrella framework. When + * staticly linking when -twolevel_namespace is in effect a twolevel namespace + * umbrella framework will only cause its subframeworks and those frameworks + * listed as sub_umbrella frameworks to be implicited linked in. Any other + * dependent dynamic libraries will not be linked it when -twolevel_namespace + * is in effect. The primary library recorded by the static linker when + * resolving a symbol in these libraries will be the umbrella framework. + * Zero or more sub_umbrella frameworks may be use by an umbrella framework. + * The name of a sub_umbrella framework is recorded in the following structure. + */ +struct sub_umbrella_command { + uint32_t cmd; /* LC_SUB_UMBRELLA */ + uint32_t cmdsize; /* includes sub_umbrella string */ + union lc_str sub_umbrella; /* the sub_umbrella framework name */ +}; + +/* + * A dynamically linked shared library may be a sub_library of another shared + * library. If so it will be linked with "-sub_library library_name" where + * Where "library_name" is the name of the sub_library shared library. When + * staticly linking when -twolevel_namespace is in effect a twolevel namespace + * shared library will only cause its subframeworks and those frameworks + * listed as sub_umbrella frameworks and libraries listed as sub_libraries to + * be implicited linked in. Any other dependent dynamic libraries will not be + * linked it when -twolevel_namespace is in effect. The primary library + * recorded by the static linker when resolving a symbol in these libraries + * will be the umbrella framework (or dynamic library). Zero or more sub_library + * shared libraries may be use by an umbrella framework or (or dynamic library). + * The name of a sub_library framework is recorded in the following structure. + * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc". + */ +struct sub_library_command { + uint32_t cmd; /* LC_SUB_LIBRARY */ + uint32_t cmdsize; /* includes sub_library string */ + union lc_str sub_library; /* the sub_library name */ +}; + +/* + * A program (filetype == MH_EXECUTE) that is + * prebound to its dynamic libraries has one of these for each library that + * the static linker used in prebinding. It contains a bit vector for the + * modules in the library. The bits indicate which modules are bound (1) and + * which are not (0) from the library. The bit for module 0 is the low bit + * of the first byte. So the bit for the Nth module is: + * (linked_modules[N/8] >> N%8) & 1 + */ +struct prebound_dylib_command { + uint32_t cmd; /* LC_PREBOUND_DYLIB */ + uint32_t cmdsize; /* includes strings */ + union lc_str name; /* library's path name */ + uint32_t nmodules; /* number of modules in library */ + union lc_str linked_modules; /* bit vector of linked modules */ +}; + +/* + * A program that uses a dynamic linker contains a dylinker_command to identify + * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker + * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER). + * A file can have at most one of these. + * This struct is also used for the LC_DYLD_ENVIRONMENT load command and + * contains string for dyld to treat like environment variable. + */ +struct dylinker_command { + uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or + LC_DYLD_ENVIRONMENT */ + uint32_t cmdsize; /* includes pathname string */ + union lc_str name; /* dynamic linker's path name */ +}; + +/* + * Thread commands contain machine-specific data structures suitable for + * use in the thread state primitives. The machine specific data structures + * follow the struct thread_command as follows. + * Each flavor of machine specific data structure is preceded by an unsigned + * long constant for the flavor of that data structure, an uint32_t + * that is the count of longs of the size of the state data structure and then + * the state data structure follows. This triple may be repeated for many + * flavors. The constants for the flavors, counts and state data structure + * definitions are expected to be in the header file <machine/thread_status.h>. + * These machine specific data structures sizes must be multiples of + * 4 bytes The cmdsize reflects the total size of the thread_command + * and all of the sizes of the constants for the flavors, counts and state + * data structures. + * + * For executable objects that are unix processes there will be one + * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor. + * This is the same as a LC_THREAD, except that a stack is automatically + * created (based on the shell's limit for the stack size). Command arguments + * and environment variables are copied onto that stack. + */ +struct thread_command { + uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ + uint32_t cmdsize; /* total size of this command */ + /* uint32_t flavor flavor of thread state */ + /* uint32_t count count of longs in thread state */ + /* struct XXX_thread_state state thread state for this flavor */ + /* ... */ +}; + +/* + * The routines command contains the address of the dynamic shared library + * initialization routine and an index into the module table for the module + * that defines the routine. Before any modules are used from the library the + * dynamic linker fully binds the module that defines the initialization routine + * and then calls it. This gets called before any module initialization + * routines (used for C++ static constructors) in the library. + */ +struct routines_command { /* for 32-bit architectures */ + uint32_t cmd; /* LC_ROUTINES */ + uint32_t cmdsize; /* total size of this command */ + uint32_t init_address; /* address of initialization routine */ + uint32_t init_module; /* index into the module table that */ + /* the init routine is defined in */ + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; +}; + +/* + * The 64-bit routines command. Same use as above. + */ +struct routines_command_64 { /* for 64-bit architectures */ + uint32_t cmd; /* LC_ROUTINES_64 */ + uint32_t cmdsize; /* total size of this command */ + uint64_t init_address; /* address of initialization routine */ + uint64_t init_module; /* index into the module table that */ + /* the init routine is defined in */ + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; + uint64_t reserved4; + uint64_t reserved5; + uint64_t reserved6; +}; + +/* + * The symtab_command contains the offsets and sizes of the link-edit 4.3BSD + * "stab" style symbol table information as described in the header files + * <nlist.h> and <stab.h>. + */ +struct symtab_command { + uint32_t cmd; /* LC_SYMTAB */ + uint32_t cmdsize; /* sizeof(struct symtab_command) */ + uint32_t symoff; /* symbol table offset */ + uint32_t nsyms; /* number of symbol table entries */ + uint32_t stroff; /* string table offset */ + uint32_t strsize; /* string table size in bytes */ +}; + +/* + * This is the second set of the symbolic information which is used to support + * the data structures for the dynamically link editor. + * + * The original set of symbolic information in the symtab_command which contains + * the symbol and string tables must also be present when this load command is + * present. When this load command is present the symbol table is organized + * into three groups of symbols: + * local symbols (static and debugging symbols) - grouped by module + * defined external symbols - grouped by module (sorted by name if not lib) + * undefined external symbols (sorted by name if MH_BINDATLOAD is not set, + * and in order the were seen by the static + * linker if MH_BINDATLOAD is set) + * In this load command there are offsets and counts to each of the three groups + * of symbols. + * + * This load command contains a the offsets and sizes of the following new + * symbolic information tables: + * table of contents + * module table + * reference symbol table + * indirect symbol table + * The first three tables above (the table of contents, module table and + * reference symbol table) are only present if the file is a dynamically linked + * shared library. For executable and object modules, which are files + * containing only one module, the information that would be in these three + * tables is determined as follows: + * table of contents - the defined external symbols are sorted by name + * module table - the file contains only one module so everything in the + * file is part of the module. + * reference symbol table - is the defined and undefined external symbols + * + * For dynamically linked shared library files this load command also contains + * offsets and sizes to the pool of relocation entries for all sections + * separated into two groups: + * external relocation entries + * local relocation entries + * For executable and object modules the relocation entries continue to hang + * off the section structures. + */ +struct dysymtab_command { + uint32_t cmd; /* LC_DYSYMTAB */ + uint32_t cmdsize; /* sizeof(struct dysymtab_command) */ + + /* + * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command + * are grouped into the following three groups: + * local symbols (further grouped by the module they are from) + * defined external symbols (further grouped by the module they are from) + * undefined symbols + * + * The local symbols are used only for debugging. The dynamic binding + * process may have to use them to indicate to the debugger the local + * symbols for a module that is being bound. + * + * The last two groups are used by the dynamic binding process to do the + * binding (indirectly through the module table and the reference symbol + * table when this is a dynamically linked shared library file). + */ + uint32_t ilocalsym; /* index to local symbols */ + uint32_t nlocalsym; /* number of local symbols */ + + uint32_t iextdefsym;/* index to externally defined symbols */ + uint32_t nextdefsym;/* number of externally defined symbols */ + + uint32_t iundefsym; /* index to undefined symbols */ + uint32_t nundefsym; /* number of undefined symbols */ + + /* + * For the for the dynamic binding process to find which module a symbol + * is defined in the table of contents is used (analogous to the ranlib + * structure in an archive) which maps defined external symbols to modules + * they are defined in. This exists only in a dynamically linked shared + * library file. For executable and object modules the defined external + * symbols are sorted by name and is use as the table of contents. + */ + uint32_t tocoff; /* file offset to table of contents */ + uint32_t ntoc; /* number of entries in table of contents */ + + /* + * To support dynamic binding of "modules" (whole object files) the symbol + * table must reflect the modules that the file was created from. This is + * done by having a module table that has indexes and counts into the merged + * tables for each module. The module structure that these two entries + * refer to is described below. This exists only in a dynamically linked + * shared library file. For executable and object modules the file only + * contains one module so everything in the file belongs to the module. + */ + uint32_t modtaboff; /* file offset to module table */ + uint32_t nmodtab; /* number of module table entries */ + + /* + * To support dynamic module binding the module structure for each module + * indicates the external references (defined and undefined) each module + * makes. For each module there is an offset and a count into the + * reference symbol table for the symbols that the module references. + * This exists only in a dynamically linked shared library file. For + * executable and object modules the defined external symbols and the + * undefined external symbols indicates the external references. + */ + uint32_t extrefsymoff; /* offset to referenced symbol table */ + uint32_t nextrefsyms; /* number of referenced symbol table entries */ + + /* + * The sections that contain "symbol pointers" and "routine stubs" have + * indexes and (implied counts based on the size of the section and fixed + * size of the entry) into the "indirect symbol" table for each pointer + * and stub. For every section of these two types the index into the + * indirect symbol table is stored in the section header in the field + * reserved1. An indirect symbol table entry is simply a 32bit index into + * the symbol table to the symbol that the pointer or stub is referring to. + * The indirect symbol table is ordered to match the entries in the section. + */ + uint32_t indirectsymoff; /* file offset to the indirect symbol table */ + uint32_t nindirectsyms; /* number of indirect symbol table entries */ + + /* + * To support relocating an individual module in a library file quickly the + * external relocation entries for each module in the library need to be + * accessed efficiently. Since the relocation entries can't be accessed + * through the section headers for a library file they are separated into + * groups of local and external entries further grouped by module. In this + * case the presents of this load command who's extreloff, nextrel, + * locreloff and nlocrel fields are non-zero indicates that the relocation + * entries of non-merged sections are not referenced through the section + * structures (and the reloff and nreloc fields in the section headers are + * set to zero). + * + * Since the relocation entries are not accessed through the section headers + * this requires the r_address field to be something other than a section + * offset to identify the item to be relocated. In this case r_address is + * set to the offset from the vmaddr of the first LC_SEGMENT command. + * For MH_SPLIT_SEGS images r_address is set to the the offset from the + * vmaddr of the first read-write LC_SEGMENT command. + * + * The relocation entries are grouped by module and the module table + * entries have indexes and counts into them for the group of external + * relocation entries for that the module. + * + * For sections that are merged across modules there must not be any + * remaining external relocation entries for them (for merged sections + * remaining relocation entries must be local). + */ + uint32_t extreloff; /* offset to external relocation entries */ + uint32_t nextrel; /* number of external relocation entries */ + + /* + * All the local relocation entries are grouped together (they are not + * grouped by their module since they are only used if the object is moved + * from it staticly link edited address). + */ + uint32_t locreloff; /* offset to local relocation entries */ + uint32_t nlocrel; /* number of local relocation entries */ + +}; + +/* + * An indirect symbol table entry is simply a 32bit index into the symbol table + * to the symbol that the pointer or stub is refering to. Unless it is for a + * non-lazy symbol pointer section for a defined symbol which strip(1) as + * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the + * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. + */ +#define INDIRECT_SYMBOL_LOCAL 0x80000000 +#define INDIRECT_SYMBOL_ABS 0x40000000 + + +/* a table of contents entry */ +struct dylib_table_of_contents { + uint32_t symbol_index; /* the defined external symbol + (index into the symbol table) */ + uint32_t module_index; /* index into the module table this symbol + is defined in */ +}; + +/* a module table entry */ +struct dylib_module { + uint32_t module_name; /* the module name (index into string table) */ + + uint32_t iextdefsym; /* index into externally defined symbols */ + uint32_t nextdefsym; /* number of externally defined symbols */ + uint32_t irefsym; /* index into reference symbol table */ + uint32_t nrefsym; /* number of reference symbol table entries */ + uint32_t ilocalsym; /* index into symbols for local symbols */ + uint32_t nlocalsym; /* number of local symbols */ + + uint32_t iextrel; /* index into external relocation entries */ + uint32_t nextrel; /* number of external relocation entries */ + + uint32_t iinit_iterm; /* low 16 bits are the index into the init + section, high 16 bits are the index into + the term section */ + uint32_t ninit_nterm; /* low 16 bits are the number of init section + entries, high 16 bits are the number of + term section entries */ + + uint32_t /* for this module address of the start of */ + objc_module_info_addr; /* the (__OBJC,__module_info) section */ + uint32_t /* for this module size of */ + objc_module_info_size; /* the (__OBJC,__module_info) section */ +}; + +/* a 64-bit module table entry */ +struct dylib_module_64 { + uint32_t module_name; /* the module name (index into string table) */ + + uint32_t iextdefsym; /* index into externally defined symbols */ + uint32_t nextdefsym; /* number of externally defined symbols */ + uint32_t irefsym; /* index into reference symbol table */ + uint32_t nrefsym; /* number of reference symbol table entries */ + uint32_t ilocalsym; /* index into symbols for local symbols */ + uint32_t nlocalsym; /* number of local symbols */ + + uint32_t iextrel; /* index into external relocation entries */ + uint32_t nextrel; /* number of external relocation entries */ + + uint32_t iinit_iterm; /* low 16 bits are the index into the init + section, high 16 bits are the index into + the term section */ + uint32_t ninit_nterm; /* low 16 bits are the number of init section + entries, high 16 bits are the number of + term section entries */ + + uint32_t /* for this module size of */ + objc_module_info_size; /* the (__OBJC,__module_info) section */ + uint64_t /* for this module address of the start of */ + objc_module_info_addr; /* the (__OBJC,__module_info) section */ +}; + +/* + * The entries in the reference symbol table are used when loading the module + * (both by the static and dynamic link editors) and if the module is unloaded + * or replaced. Therefore all external symbols (defined and undefined) are + * listed in the module's reference table. The flags describe the type of + * reference that is being made. The constants for the flags are defined in + * <mach-o/nlist.h> as they are also used for symbol table entries. + */ +struct dylib_reference { + uint32_t isym:24, /* index into the symbol table */ + flags:8; /* flags to indicate the type of reference */ +}; + +/* + * The twolevel_hints_command contains the offset and number of hints in the + * two-level namespace lookup hints table. + */ +struct twolevel_hints_command { + uint32_t cmd; /* LC_TWOLEVEL_HINTS */ + uint32_t cmdsize; /* sizeof(struct twolevel_hints_command) */ + uint32_t offset; /* offset to the hint table */ + uint32_t nhints; /* number of hints in the hint table */ +}; + +/* + * The entries in the two-level namespace lookup hints table are twolevel_hint + * structs. These provide hints to the dynamic link editor where to start + * looking for an undefined symbol in a two-level namespace image. The + * isub_image field is an index into the sub-images (sub-frameworks and + * sub-umbrellas list) that made up the two-level image that the undefined + * symbol was found in when it was built by the static link editor. If + * isub-image is 0 the the symbol is expected to be defined in library and not + * in the sub-images. If isub-image is non-zero it is an index into the array + * of sub-images for the umbrella with the first index in the sub-images being + * 1. The array of sub-images is the ordered list of sub-images of the umbrella + * that would be searched for a symbol that has the umbrella recorded as its + * primary library. The table of contents index is an index into the + * library's table of contents. This is used as the starting point of the + * binary search or a directed linear search. + */ +struct twolevel_hint { + uint32_t + isub_image:8, /* index into the sub images */ + itoc:24; /* index into the table of contents */ +}; + +/* + * The prebind_cksum_command contains the value of the original check sum for + * prebound files or zero. When a prebound file is first created or modified + * for other than updating its prebinding information the value of the check sum + * is set to zero. When the file has it prebinding re-done and if the value of + * the check sum is zero the original check sum is calculated and stored in + * cksum field of this load command in the output file. If when the prebinding + * is re-done and the cksum field is non-zero it is left unchanged from the + * input file. + */ +struct prebind_cksum_command { + uint32_t cmd; /* LC_PREBIND_CKSUM */ + uint32_t cmdsize; /* sizeof(struct prebind_cksum_command) */ + uint32_t cksum; /* the check sum or zero */ +}; + +/* + * The uuid load command contains a single 128-bit unique random number that + * identifies an object produced by the static link editor. + */ +struct uuid_command { + uint32_t cmd; /* LC_UUID */ + uint32_t cmdsize; /* sizeof(struct uuid_command) */ + uint8_t uuid[16]; /* the 128-bit uuid */ +}; + +/* + * The rpath_command contains a path which at runtime should be added to + * the current run path used to find @rpath prefixed dylibs. + */ +struct rpath_command { + uint32_t cmd; /* LC_RPATH */ + uint32_t cmdsize; /* includes string */ + union lc_str path; /* path to add to run path */ +}; + +/* + * The linkedit_data_command contains the offsets and sizes of a blob + * of data in the __LINKEDIT segment. + */ +struct linkedit_data_command { + uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, + LC_FUNCTION_STARTS, LC_DATA_IN_CODE, + LC_DYLIB_CODE_SIGN_DRS or + LC_LINKER_OPTIMIZATION_HINT. */ + uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ + uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ + uint32_t datasize; /* file size of data in __LINKEDIT segment */ +}; + +/* + * The encryption_info_command contains the file offset and size of an + * of an encrypted segment. + */ +struct encryption_info_command { + uint32_t cmd; /* LC_ENCRYPTION_INFO */ + uint32_t cmdsize; /* sizeof(struct encryption_info_command) */ + uint32_t cryptoff; /* file offset of encrypted range */ + uint32_t cryptsize; /* file size of encrypted range */ + uint32_t cryptid; /* which enryption system, + 0 means not-encrypted yet */ +}; + +/* + * The encryption_info_command_64 contains the file offset and size of an + * of an encrypted segment (for use in x86_64 targets). + */ +struct encryption_info_command_64 { + uint32_t cmd; /* LC_ENCRYPTION_INFO_64 */ + uint32_t cmdsize; /* sizeof(struct encryption_info_command_64) */ + uint32_t cryptoff; /* file offset of encrypted range */ + uint32_t cryptsize; /* file size of encrypted range */ + uint32_t cryptid; /* which enryption system, + 0 means not-encrypted yet */ + uint32_t pad; /* padding to make this struct's size a multiple + of 8 bytes */ +}; + +/* + * The version_min_command contains the min OS version on which this + * binary was built to run. + */ +struct version_min_command { + uint32_t cmd; /* LC_VERSION_MIN_MACOSX or + LC_VERSION_MIN_IPHONEOS or + LC_VERSION_MIN_WATCHOS or + LC_VERSION_MIN_TVOS */ + uint32_t cmdsize; /* sizeof(struct min_version_command) */ + uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ +}; + +/* + * The build_version_command contains the min OS version on which this + * binary was built to run for its platform. The list of known platforms and + * tool values following it. + */ +struct build_version_command { + uint32_t cmd; /* LC_BUILD_VERSION */ + uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ + /* ntools * sizeof(struct build_tool_version) */ + uint32_t platform; /* platform */ + uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t ntools; /* number of tool entries following this */ +}; + +struct build_tool_version { + uint32_t tool; /* enum for the tool */ + uint32_t version; /* version number of the tool */ +}; + +/* Known values for the platform field above. */ +#define PLATFORM_MACOS 1 +#define PLATFORM_IOS 2 +#define PLATFORM_TVOS 3 +#define PLATFORM_WATCHOS 4 + +/* Known values for the tool field above. */ +#define TOOL_CLANG 1 +#define TOOL_SWIFT 2 +#define TOOL_LD 3 + +/* + * The dyld_info_command contains the file offsets and sizes of + * the new compressed form of the information dyld needs to + * load the image. This information is used by dyld on Mac OS X + * 10.6 and later. All information pointed to by this command + * is encoded using byte streams, so no endian swapping is needed + * to interpret it. + */ +struct dyld_info_command { + uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */ + uint32_t cmdsize; /* sizeof(struct dyld_info_command) */ + + /* + * Dyld rebases an image whenever dyld loads it at an address different + * from its preferred address. The rebase information is a stream + * of byte sized opcodes whose symbolic names start with REBASE_OPCODE_. + * Conceptually the rebase information is a table of tuples: + * <seg-index, seg-offset, type> + * The opcodes are a compressed way to encode the table by only + * encoding when a column changes. In addition simple patterns + * like "every n'th offset for m times" can be encoded in a few + * bytes. + */ + uint32_t rebase_off; /* file offset to rebase info */ + uint32_t rebase_size; /* size of rebase info */ + + /* + * Dyld binds an image during the loading process, if the image + * requires any pointers to be initialized to symbols in other images. + * The bind information is a stream of byte sized + * opcodes whose symbolic names start with BIND_OPCODE_. + * Conceptually the bind information is a table of tuples: + * <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend> + * The opcodes are a compressed way to encode the table by only + * encoding when a column changes. In addition simple patterns + * like for runs of pointers initialzed to the same value can be + * encoded in a few bytes. + */ + uint32_t bind_off; /* file offset to binding info */ + uint32_t bind_size; /* size of binding info */ + + /* + * Some C++ programs require dyld to unique symbols so that all + * images in the process use the same copy of some code/data. + * This step is done after binding. The content of the weak_bind + * info is an opcode stream like the bind_info. But it is sorted + * alphabetically by symbol name. This enable dyld to walk + * all images with weak binding information in order and look + * for collisions. If there are no collisions, dyld does + * no updating. That means that some fixups are also encoded + * in the bind_info. For instance, all calls to "operator new" + * are first bound to libstdc++.dylib using the information + * in bind_info. Then if some image overrides operator new + * that is detected when the weak_bind information is processed + * and the call to operator new is then rebound. + */ + uint32_t weak_bind_off; /* file offset to weak binding info */ + uint32_t weak_bind_size; /* size of weak binding info */ + + /* + * Some uses of external symbols do not need to be bound immediately. + * Instead they can be lazily bound on first use. The lazy_bind + * are contains a stream of BIND opcodes to bind all lazy symbols. + * Normal use is that dyld ignores the lazy_bind section when + * loading an image. Instead the static linker arranged for the + * lazy pointer to initially point to a helper function which + * pushes the offset into the lazy_bind area for the symbol + * needing to be bound, then jumps to dyld which simply adds + * the offset to lazy_bind_off to get the information on what + * to bind. + */ + uint32_t lazy_bind_off; /* file offset to lazy binding info */ + uint32_t lazy_bind_size; /* size of lazy binding infs */ + + /* + * The symbols exported by a dylib are encoded in a trie. This + * is a compact representation that factors out common prefixes. + * It also reduces LINKEDIT pages in RAM because it encodes all + * information (name, address, flags) in one small, contiguous range. + * The export area is a stream of nodes. The first node sequentially + * is the start node for the trie. + * + * Nodes for a symbol start with a uleb128 that is the length of + * the exported symbol information for the string so far. + * If there is no exported symbol, the node starts with a zero byte. + * If there is exported info, it follows the length. + * + * First is a uleb128 containing flags. Normally, it is followed by + * a uleb128 encoded offset which is location of the content named + * by the symbol from the mach_header for the image. If the flags + * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is + * a uleb128 encoded library ordinal, then a zero terminated + * UTF8 string. If the string is zero length, then the symbol + * is re-export from the specified dylib with the same name. + * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following + * the flags is two uleb128s: the stub offset and the resolver offset. + * The stub is used by non-lazy pointers. The resolver is used + * by lazy pointers and must be called to get the actual address to use. + * + * After the optional exported symbol information is a byte of + * how many edges (0-255) that this node has leaving it, + * followed by each edge. + * Each edge is a zero terminated UTF8 of the addition chars + * in the symbol, followed by a uleb128 offset for the node that + * edge points to. + * + */ + uint32_t export_off; /* file offset to lazy binding info */ + uint32_t export_size; /* size of lazy binding infs */ +}; + +/* + * The following are used to encode rebasing information + */ +#define REBASE_TYPE_POINTER 1 +#define REBASE_TYPE_TEXT_ABSOLUTE32 2 +#define REBASE_TYPE_TEXT_PCREL32 3 + +#define REBASE_OPCODE_MASK 0xF0 +#define REBASE_IMMEDIATE_MASK 0x0F +#define REBASE_OPCODE_DONE 0x00 +#define REBASE_OPCODE_SET_TYPE_IMM 0x10 +#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20 +#define REBASE_OPCODE_ADD_ADDR_ULEB 0x30 +#define REBASE_OPCODE_ADD_ADDR_IMM_SCALED 0x40 +#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50 +#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES 0x60 +#define REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB 0x70 +#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB 0x80 + + +/* + * The following are used to encode binding information + */ +#define BIND_TYPE_POINTER 1 +#define BIND_TYPE_TEXT_ABSOLUTE32 2 +#define BIND_TYPE_TEXT_PCREL32 3 + +#define BIND_SPECIAL_DYLIB_SELF 0 +#define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1 +#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 + +#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 +#define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8 + +#define BIND_OPCODE_MASK 0xF0 +#define BIND_IMMEDIATE_MASK 0x0F +#define BIND_OPCODE_DONE 0x00 +#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10 +#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20 +#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 +#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 +#define BIND_OPCODE_SET_TYPE_IMM 0x50 +#define BIND_OPCODE_SET_ADDEND_SLEB 0x60 +#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 +#define BIND_OPCODE_ADD_ADDR_ULEB 0x80 +#define BIND_OPCODE_DO_BIND 0x90 +#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0 +#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0 +#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0 + + +/* + * The following are used on the flags byte of a terminal node + * in the export information. + */ +#define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03 +#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 +#define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01 +#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 +#define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 +#define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 + +/* + * The linker_option_command contains linker options embedded in object files. + */ +struct linker_option_command { + uint32_t cmd; /* LC_LINKER_OPTION only used in MH_OBJECT filetypes */ + uint32_t cmdsize; + uint32_t count; /* number of strings */ + /* concatenation of zero terminated UTF8 strings. + Zero filled at end to align */ +}; + +/* + * The symseg_command contains the offset and size of the GNU style + * symbol table information as described in the header file <symseg.h>. + * The symbol roots of the symbol segments must also be aligned properly + * in the file. So the requirement of keeping the offsets aligned to a + * multiple of a 4 bytes translates to the length field of the symbol + * roots also being a multiple of a long. Also the padding must again be + * zeroed. (THIS IS OBSOLETE and no longer supported). + */ +struct symseg_command { + uint32_t cmd; /* LC_SYMSEG */ + uint32_t cmdsize; /* sizeof(struct symseg_command) */ + uint32_t offset; /* symbol segment offset */ + uint32_t size; /* symbol segment size in bytes */ +}; + +/* + * The ident_command contains a free format string table following the + * ident_command structure. The strings are null terminated and the size of + * the command is padded out with zero bytes to a multiple of 4 bytes/ + * (THIS IS OBSOLETE and no longer supported). + */ +struct ident_command { + uint32_t cmd; /* LC_IDENT */ + uint32_t cmdsize; /* strings that follow this command */ +}; + +/* + * The fvmfile_command contains a reference to a file to be loaded at the + * specified virtual address. (Presently, this command is reserved for + * internal use. The kernel ignores this command when loading a program into + * memory). + */ +struct fvmfile_command { + uint32_t cmd; /* LC_FVMFILE */ + uint32_t cmdsize; /* includes pathname string */ + union lc_str name; /* files pathname */ + uint32_t header_addr; /* files virtual address */ +}; + + +/* + * The entry_point_command is a replacement for thread_command. + * It is used for main executables to specify the location (file offset) + * of main(). If -stack_size was used at link time, the stacksize + * field will contain the stack size need for the main thread. + */ +struct entry_point_command { + uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ + uint32_t cmdsize; /* 24 */ + uint64_t entryoff; /* file (__TEXT) offset of main() */ + uint64_t stacksize;/* if not zero, initial stack size */ +}; + + +/* + * The source_version_command is an optional load command containing + * the version of the sources used to build the binary. + */ +struct source_version_command { + uint32_t cmd; /* LC_SOURCE_VERSION */ + uint32_t cmdsize; /* 16 */ + uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ +}; + + +/* + * The LC_DATA_IN_CODE load commands uses a linkedit_data_command + * to point to an array of data_in_code_entry entries. Each entry + * describes a range of data in a code section. + */ +struct data_in_code_entry { + uint32_t offset; /* from mach_header to start of data range*/ + uint16_t length; /* number of bytes in data range */ + uint16_t kind; /* a DICE_KIND_* value */ +}; +#define DICE_KIND_DATA 0x0001 +#define DICE_KIND_JUMP_TABLE8 0x0002 +#define DICE_KIND_JUMP_TABLE16 0x0003 +#define DICE_KIND_JUMP_TABLE32 0x0004 +#define DICE_KIND_ABS_JUMP_TABLE32 0x0005 + + + +/* + * Sections of type S_THREAD_LOCAL_VARIABLES contain an array + * of tlv_descriptor structures. + */ +struct tlv_descriptor +{ + void* (*thunk)(struct tlv_descriptor*); + unsigned long key; + unsigned long offset; +}; + +/* + * LC_NOTE commands describe a region of arbitrary data included in a Mach-O + * file. Its initial use is to record extra data in MH_CORE files. + */ +struct note_command { + uint32_t cmd; /* LC_NOTE */ + uint32_t cmdsize; /* sizeof(struct note_command) */ + char data_owner[16]; /* owner name for this LC_NOTE */ + uint64_t offset; /* file offset of this data */ + uint64_t size; /* length of data region */ +}; + +#endif /* _MACHO_LOADER_H_ */
diff --git a/third_party/crashpad/crashpad/third_party/xnu/README.crashpad b/third_party/crashpad/crashpad/third_party/xnu/README.crashpad new file mode 100644 index 0000000..274faf1 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/xnu/README.crashpad
@@ -0,0 +1,19 @@ +Name: XNU +Short Name: xnu +URL: https://opensource.apple.com/source/xnu/ +URL: https://opensource.apple.com/tarballs/xnu/ +Version: 4903.221.2 (from macOS 10.14.1) +License: APSL 2.0 +License File: APPLE_LICENSE +Security Critical: no + +Description: +XNU is the operating system kernel used on macOS and other Apple systems. + +Local Modifications: + - Only EXTERNAL_HEADERS/mach-o/loader.h is included. Its #includes of + <mach/machine/thread_status.h> and <architecture/byte_order.h> have been + removed as unnecessary. Note that its #includes of <mach/machine.h> and + <mach/vm_prot.h> have been retained but these headers have not been provided. + External headers must be made available to provide the cpu_type_t, + cpu_subtype_t, and vm_prot_t types.
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index b5e1561a..41a74d63 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -441,7 +441,10 @@ "Foundation.framework", "IOKit.framework", ] - deps += [ ":mig" ] + deps += [ + ":mig", + "../third_party/apple_cf:apple_cf", + ] include_dirs += [ "$root_build_dir/gen" ] }
diff --git a/third_party/crashpad/crashpad/util/fuchsia/koid_utilities.cc b/third_party/crashpad/crashpad/util/fuchsia/koid_utilities.cc index bb40a1c..288f04b 100644 --- a/third_party/crashpad/crashpad/util/fuchsia/koid_utilities.cc +++ b/third_party/crashpad/crashpad/util/fuchsia/koid_utilities.cc
@@ -15,7 +15,7 @@ #include "util/fuchsia/koid_utilities.h" #include <fuchsia/sysinfo/c/fidl.h> -#include <lib/fdio/util.h> +#include <lib/fdio/fdio.h> #include <lib/zx/channel.h> #include <lib/zx/job.h> #include <lib/zx/process.h>
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc b/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc index 0965fd67..fbf47fae 100644 --- a/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc +++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc
@@ -33,6 +33,11 @@ return true; } +size_t RoundPage(size_t size) { + const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1; + return (size + kPageMask) & ~kPageMask; +} + } // namespace namespace crashpad { @@ -41,7 +46,7 @@ ScopedMmap::~ScopedMmap() { if (is_valid()) { - Munmap(reinterpret_cast<uintptr_t>(addr_), len_); + Munmap(reinterpret_cast<uintptr_t>(addr_), RoundPage(len_)); } } @@ -51,29 +56,28 @@ bool ScopedMmap::ResetAddrLen(void* addr, size_t len) { const uintptr_t new_addr = reinterpret_cast<uintptr_t>(addr); + const size_t new_len_round = RoundPage(len); if (addr == MAP_FAILED) { DCHECK_EQ(len, 0u); } else { - // Round |len| up to the next page. - const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1; - len = (len + kPageMask) & ~kPageMask; - DCHECK_NE(len, 0u); DCHECK_EQ(new_addr % getpagesize(), 0u); - DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (len - 1)).IsValid()); + DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (new_len_round - 1)) + .IsValid()); } bool result = true; if (is_valid()) { const uintptr_t old_addr = reinterpret_cast<uintptr_t>(addr_); + const size_t old_len_round = RoundPage(len_); if (old_addr < new_addr) { - result &= Munmap(old_addr, std::min(len_, new_addr - old_addr)); + result &= Munmap(old_addr, std::min(old_len_round, new_addr - old_addr)); } - if (old_addr + len_ > new_addr + len) { - uintptr_t unmap_start = std::max(old_addr, new_addr + len); - result &= Munmap(unmap_start, old_addr + len_ - unmap_start); + if (old_addr + old_len_round > new_addr + new_len_round) { + uintptr_t unmap_start = std::max(old_addr, new_addr + new_len_round); + result &= Munmap(unmap_start, old_addr + old_len_round - unmap_start); } } @@ -108,7 +112,7 @@ } bool ScopedMmap::Mprotect(int prot) { - if (mprotect(addr_, len_, prot) < 0) { + if (mprotect(addr_, RoundPage(len_), prot) < 0) { PLOG(ERROR) << "mprotect"; return false; }
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap.h b/third_party/crashpad/crashpad/util/posix/scoped_mmap.h index b0ff3dc..9f22372b 100644 --- a/third_party/crashpad/crashpad/util/posix/scoped_mmap.h +++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap.h
@@ -91,6 +91,11 @@ } //! \brief Returns the size of the memory-mapped region. + //! + //! This is the value originally passed to ResetAddrLen() or ResetMmap(), or + //! after Reset(), `0`. It may not be a round number of pages. Providing the + //! passed-in value is intended to ease tracking the intended lengths of + //! memory-mapped regions backed by files whose sizes are not whole pages. size_t len() const { return len_; } private:
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc index e32fa159..5279fdb 100644 --- a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc +++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc
@@ -309,7 +309,7 @@ ASSERT_TRUE(ScopedMmapResetMmap(&mapping, kHalfPageSize)); EXPECT_TRUE(mapping.is_valid()); EXPECT_NE(mapping.addr(), MAP_FAILED); - EXPECT_EQ(mapping.len(), kPageSize); + EXPECT_EQ(mapping.len(), kHalfPageSize); TestCookie cookie; cookie.SetUp(mapping.addr_as<uint64_t*>()); @@ -319,7 +319,7 @@ ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize)); EXPECT_TRUE(mapping.is_valid()); EXPECT_EQ(mapping.addr(), orig_addr); - EXPECT_EQ(mapping.len(), kPageSize); + EXPECT_EQ(mapping.len(), kHalfPageSize); EXPECT_EQ(cookie.Observed(), cookie.Expected()); @@ -328,14 +328,14 @@ ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, 1)); EXPECT_TRUE(mapping.is_valid()); EXPECT_EQ(mapping.addr(), orig_addr); - EXPECT_EQ(mapping.len(), kPageSize); + EXPECT_EQ(mapping.len(), 1u); EXPECT_EQ(cookie.Observed(), cookie.Expected()); ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize - 1)); EXPECT_TRUE(mapping.is_valid()); EXPECT_EQ(mapping.addr(), orig_addr); - EXPECT_EQ(mapping.len(), kPageSize); + EXPECT_EQ(mapping.len(), kPageSize - 1); EXPECT_EQ(cookie.Observed(), cookie.Expected()); @@ -356,7 +356,7 @@ ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize)); EXPECT_TRUE(mapping.is_valid()); EXPECT_EQ(mapping.addr(), orig_addr); - EXPECT_EQ(mapping.len(), kPageSize); + EXPECT_EQ(mapping.len(), kHalfPageSize); EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected()); EXPECT_DEATH_CRASH(two_cookies[1].Check(), ""); @@ -376,7 +376,7 @@ ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize + kHalfPageSize)); EXPECT_TRUE(mapping.is_valid()); EXPECT_EQ(mapping.addr(), orig_addr); - EXPECT_EQ(mapping.len(), 2 * kPageSize); + EXPECT_EQ(mapping.len(), kPageSize + kHalfPageSize); EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected()); EXPECT_EQ(two_cookies[1].Observed(), two_cookies[1].Expected());
diff --git a/third_party/inspector_protocol/BUILD.gn b/third_party/inspector_protocol/BUILD.gn index 0cf1a98..ddbe626 100644 --- a/third_party/inspector_protocol/BUILD.gn +++ b/third_party/inspector_protocol/BUILD.gn
@@ -2,109 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# All build targets below are experimental and not used within the -# Chromium / V8 / etc. trees yet thus far. Do not depend on anything. - -import("//testing/test.gni") - -static_library("json_parser") { +static_library("encoding") { sources = [ - "encoding/json_parser.cc", - "encoding/json_parser.h", - "encoding/json_parser_handler.h", - "encoding/platform.h", - "encoding/span.h", - "encoding/status.h", - "encoding/str_util.cc", - "encoding/str_util.h", + "encoding/encoding.cc", + "encoding/encoding.h", ] } -static_library("linux_dev_platform") { - sources = [ - "encoding/linux_dev_platform.cc", - "encoding/linux_dev_platform.h", - "encoding/platform.h", - ] -} +# encoding/encoding_test.cc: +# There's no target for this file here, instead it is included +# in //content/test:content_unittest +# via //content/browser/devtools:inspector_protocol_encoding_test. -test("json_parser_test") { - sources = [ - "encoding/json_parser_test.cc", - ] - deps = [ - ":json_parser", - ":linux_dev_platform", - "//base", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest", - "//third_party/googletest:gtest_main", - ] -} - -static_library("cbor") { - sources = [ - "encoding/cbor.cc", - "encoding/cbor.h", - "encoding/json_parser_handler.h", - "encoding/span.h", - "encoding/status.h", - ] - deps = [ - ":json_parser", - ] -} - -test("cbor_test") { - sources = [ - "encoding/cbor_test.cc", - ] - deps = [ - ":cbor", - ":json_parser", - ":json_std_string_writer", - ":linux_dev_platform", - "//base", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest", - "//third_party/googletest:gtest_main", - ] -} - -test("span_test") { - sources = [ - "encoding/span.h", - "encoding/span_test.cc", - ] - deps = [ - "//base", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest", - "//third_party/googletest:gtest_main", - ] -} - -static_library("json_std_string_writer") { - sources = [ - "encoding/json_parser_handler.h", - "encoding/json_std_string_writer.cc", - "encoding/json_std_string_writer.h", - "encoding/platform.h", - "encoding/span.h", - "encoding/status.h", - ] -} - -test("json_std_string_writer_test") { - sources = [ - "encoding/json_std_string_writer_test.cc", - ] - deps = [ - ":json_std_string_writer", - ":linux_dev_platform", - "//base", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest", - "//third_party/googletest:gtest_main", - ] -}
diff --git a/third_party/inspector_protocol/DEPS b/third_party/inspector_protocol/DEPS index 81c9b082..20785c0 100644 --- a/third_party/inspector_protocol/DEPS +++ b/third_party/inspector_protocol/DEPS
@@ -6,7 +6,7 @@ specific_include_rules = { '^.*_test\.cc$': [ '+base', - '+gmock', - '+gtest', + '+testing/gtest/include', + '+testing/gmock/include', ], }
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium index 89f754b6..d8349fb4 100644 --- a/third_party/inspector_protocol/README.chromium +++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@ Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: be5f927f77f7d4670a02f16ed026db0a3768980a +Revision: 1e65f2e3a9759b799ca3a87a41dcc9f58fdd720f License: BSD License File: LICENSE Security Critical: no
diff --git a/third_party/inspector_protocol/code_generator.py b/third_party/inspector_protocol/code_generator.py index fb9959d..18777d0f 100755 --- a/third_party/inspector_protocol/code_generator.py +++ b/third_party/inspector_protocol/code_generator.py
@@ -632,7 +632,7 @@ "Array_h.template", "DispatcherBase_h.template", "Parser_h.template", - "CBOR_h.template", + "encoding_h.template", ] protocol_cpp_templates = [ @@ -642,7 +642,7 @@ "Object_cpp.template", "DispatcherBase_cpp.template", "Parser_cpp.template", - "CBOR_cpp.template", + "encoding_cpp.template", ] forward_h_templates = [
diff --git a/third_party/inspector_protocol/encoding/cbor.cc b/third_party/inspector_protocol/encoding/cbor.cc deleted file mode 100644 index f771f5b..0000000 --- a/third_party/inspector_protocol/encoding/cbor.cc +++ /dev/null
@@ -1,821 +0,0 @@ -// Copyright 2018 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 "cbor.h" - -#include <cassert> -#include <limits> -#include "json_parser_handler.h" - -namespace inspector_protocol { -using namespace cbor; - -namespace { - -// See RFC 7049 Section 2.3, Table 2. -static constexpr uint8_t kEncodedTrue = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 21); -static constexpr uint8_t kEncodedFalse = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 20); -static constexpr uint8_t kEncodedNull = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 22); -static constexpr uint8_t kInitialByteForDouble = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 27); - -} // namespace - -uint8_t EncodeTrue() { return kEncodedTrue; } -uint8_t EncodeFalse() { return kEncodedFalse; } -uint8_t EncodeNull() { return kEncodedNull; } - -uint8_t EncodeIndefiniteLengthArrayStart() { - return kInitialByteIndefiniteLengthArray; -} - -uint8_t EncodeIndefiniteLengthMapStart() { - return kInitialByteIndefiniteLengthMap; -} - -uint8_t EncodeStop() { return kStopByte; } - -namespace { -// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for -// arbitrary binary data encoded as BYTE_STRING. -static constexpr uint8_t kExpectedConversionToBase64Tag = - EncodeInitialByte(MajorType::TAG, 22); - -// When parsing CBOR, we limit recursion depth for objects and arrays -// to this constant. -static constexpr int kStackLimit = 1000; - -// Writes the bytes for |v| to |out|, starting with the most significant byte. -// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html -template <typename T> -void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) { - for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes) - out->push_back(0xff & (v >> (shift_bytes * 8))); -} -} // namespace - -namespace cbor_internals { -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(MajorType type, uint64_t value, - std::vector<uint8_t>* encoded) { - if (value < 24) { - // Values 0-23 are encoded directly into the additional info of the - // initial byte. - encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value)); - return; - } - if (value <= std::numeric_limits<uint8_t>::max()) { - // Values 24-255 are encoded with one initial byte, followed by the value. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte)); - encoded->push_back(value); - return; - } - if (value <= std::numeric_limits<uint16_t>::max()) { - // Values 256-65535: 1 initial byte + 2 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes)); - WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded); - return; - } - if (value <= std::numeric_limits<uint32_t>::max()) { - // 32 bit uint: 1 initial byte + 4 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes)); - WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value), - encoded); - return; - } - // 64 bit uint: 1 initial byte + 8 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes)); - WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded); -} -} // namespace cbor_internals - -namespace { -// Extracts sizeof(T) bytes from |in| to extract a value of type T -// (e.g. uint64_t, uint32_t, ...), most significant byte first. -// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html -template <typename T> -T ReadBytesMostSignificantByteFirst(span<uint8_t> in) { - assert(static_cast<std::size_t>(in.size()) >= sizeof(T)); - T result = 0; - for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) - result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8); - return result; -} -} // namespace - -namespace cbor_internals { -int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { - if (bytes.empty()) return -1; - uint8_t initial_byte = bytes[0]; - *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); - - uint8_t additional_information = initial_byte & kAdditionalInformationMask; - if (additional_information < 24) { - // Values 0-23 are encoded directly into the additional info of the - // initial byte. - *value = additional_information; - return 1; - } - if (additional_information == kAdditionalInformation1Byte) { - // Values 24-255 are encoded with one initial byte, followed by the value. - if (bytes.size() < 2) return -1; - *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); - return 2; - } - if (additional_information == kAdditionalInformation2Bytes) { - // Values 256-65535: 1 initial byte + 2 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); - return 3; - } - if (additional_information == kAdditionalInformation4Bytes) { - // 32 bit uint: 1 initial byte + 4 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); - return 5; - } - if (additional_information == kAdditionalInformation8Bytes) { - // 64 bit uint: 1 initial byte + 8 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); - return 9; - } - return -1; -} -} // namespace cbor_internals - -using cbor_internals::WriteTokenStart; -using cbor_internals::ReadTokenStart; - -void EncodeInt32(int32_t value, std::vector<uint8_t>* out) { - if (value >= 0) { - WriteTokenStart(MajorType::UNSIGNED, value, out); - } else { - uint64_t representation = static_cast<uint64_t>(-(value + 1)); - WriteTokenStart(MajorType::NEGATIVE, representation, out); - } -} - -void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) { - uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); - WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); - // When emitting UTF16 characters, we always write the least significant byte - // first; this is because it's the native representation for X86. - // TODO(johannes): Implement a more efficient thing here later, e.g. - // casting *iff* the machine has this byte order. - // The wire format for UTF16 chars will probably remain the same - // (least significant byte first) since this way we can have - // golden files, unittests, etc. that port easily and universally. - // See also: - // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html - for (const uint16_t two_bytes : in) { - out->push_back(two_bytes); - out->push_back(two_bytes >> 8); - } -} - -void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) { - WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(in.size_bytes()), - out); - out->insert(out->end(), in.begin(), in.end()); -} - -void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { - for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { - if (latin1[ii] <= 127) - continue; - // If there's at least one non-ASCII char, convert to UTF8. - std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); - for (; ii < latin1.size(); ++ii) { - if (latin1[ii] <= 127) { - utf8.push_back(latin1[ii]); - } else { - // 0xC0 means it's a UTF8 sequence with 2 bytes. - utf8.push_back((latin1[ii] >> 6) | 0xc0); - utf8.push_back((latin1[ii] | 0x80) & 0xbf); - } - } - EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out); - return; - } - EncodeString8(latin1, out); -} - -void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { - // If there's at least one non-ASCII char, encode as STRING16 (UTF16). - for (uint16_t ch : utf16) { - if (ch <= 127) - continue; - EncodeString16(utf16, out); - return; - } - // It's all US-ASCII, strip out every second byte and encode as UTF8. - WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out); - out->insert(out->end(), utf16.begin(), utf16.end()); -} - -void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { - out->push_back(kExpectedConversionToBase64Tag); - uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); - WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); - out->insert(out->end(), in.begin(), in.end()); -} - -// A double is encoded with a specific initial byte -// (kInitialByteForDouble) plus the 64 bits of payload for its value. -constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t); - -// An envelope is encoded with a specific initial byte -// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32 -// bit wide length, plus a 32 bit length for that string. -constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t); - -void EncodeDouble(double value, std::vector<uint8_t>* out) { - // The additional_info=27 indicates 64 bits for the double follow. - // See RFC 7049 Section 2.3, Table 1. - out->push_back(kInitialByteForDouble); - union { - double from_double; - uint64_t to_uint64; - } reinterpret; - reinterpret.from_double = value; - WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out); -} - -void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { - assert(byte_size_pos_ == 0); - out->push_back(kInitialByteForEnvelope); - out->push_back(kInitialByteFor32BitLengthByteString); - byte_size_pos_ = out->size(); - out->resize(out->size() + sizeof(uint32_t)); -} - -bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { - assert(byte_size_pos_ != 0); - // The byte size is the size of the payload, that is, all the - // bytes that were written past the byte size position itself. - uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t)); - // We store exactly 4 bytes, so at most INT32MAX, with most significant - // byte first. - if (byte_size > std::numeric_limits<uint32_t>::max()) return false; - for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; - --shift_bytes) { - (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8)); - } - return true; -} - -namespace { -class JSONToCBOREncoder : public JSONParserHandler { - public: - JSONToCBOREncoder(std::vector<uint8_t>* out, Status* status) - : out_(out), status_(status) { - *status_ = Status(); - } - - void HandleObjectBegin() override { - envelopes_.emplace_back(); - envelopes_.back().EncodeStart(out_); - out_->push_back(kInitialByteIndefiniteLengthMap); - } - - void HandleObjectEnd() override { - out_->push_back(kStopByte); - assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); - envelopes_.pop_back(); - } - - void HandleArrayBegin() override { - envelopes_.emplace_back(); - envelopes_.back().EncodeStart(out_); - out_->push_back(kInitialByteIndefiniteLengthArray); - } - - void HandleArrayEnd() override { - out_->push_back(kStopByte); - assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); - envelopes_.pop_back(); - } - - void HandleString8(span<uint8_t> chars) override { - EncodeString8(chars, out_); - } - - void HandleString16(span<uint16_t> chars) override { - for (uint16_t ch : chars) { - if (ch >= 0x7f) { - // If there's at least one non-7bit character, we encode as UTF16. - EncodeString16(chars, out_); - return; - } - } - std::vector<uint8_t> sevenbit_chars(chars.begin(), chars.end()); - EncodeString8(span<uint8_t>(sevenbit_chars.data(), sevenbit_chars.size()), - out_); - } - - void HandleBinary(std::vector<uint8_t> bytes) override { - EncodeBinary(span<uint8_t>(bytes.data(), bytes.size()), out_); - } - - void HandleDouble(double value) override { EncodeDouble(value, out_); } - - void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } - - void HandleBool(bool value) override { - // See RFC 7049 Section 2.3, Table 2. - out_->push_back(value ? kEncodedTrue : kEncodedFalse); - } - - void HandleNull() override { - // See RFC 7049 Section 2.3, Table 2. - out_->push_back(kEncodedNull); - } - - void HandleError(Status error) override { - assert(!error.ok()); - *status_ = error; - out_->clear(); - } - - private: - std::vector<uint8_t>* out_; - std::vector<EnvelopeEncoder> envelopes_; - Status* status_; -}; -} // namespace - -std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder( - std::vector<uint8_t>* out, Status* status) { - return std::unique_ptr<JSONParserHandler>(new JSONToCBOREncoder(out, status)); -} - -namespace { -// Below are three parsing routines for CBOR, which cover enough -// to roundtrip JSON messages. -bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); -bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); -bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); - -void ParseUTF16String(CBORTokenizer* tokenizer, JSONParserHandler* out) { - std::vector<uint16_t> value; - span<uint8_t> rep = tokenizer->GetString16WireRep(); - for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) - value.push_back((rep[ii + 1] << 8) | rep[ii]); - out->HandleString16(span<uint16_t>(value.data(), value.size())); - tokenizer->Next(); -} - -bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); - out->HandleString8(tokenizer->GetString8()); - tokenizer->Next(); - return true; -} - -bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - if (stack_depth > kStackLimit) { - out->HandleError( - Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos}); - return false; - } - // Skip past the envelope to get to what's inside. - if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE) - tokenizer->EnterEnvelope(); - switch (tokenizer->TokenTag()) { - case CBORTokenTag::ERROR_VALUE: - out->HandleError(tokenizer->Status()); - return false; - case CBORTokenTag::DONE: - out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, - tokenizer->Status().pos}); - return false; - case CBORTokenTag::TRUE_VALUE: - out->HandleBool(true); - tokenizer->Next(); - return true; - case CBORTokenTag::FALSE_VALUE: - out->HandleBool(false); - tokenizer->Next(); - return true; - case CBORTokenTag::NULL_VALUE: - out->HandleNull(); - tokenizer->Next(); - return true; - case CBORTokenTag::INT32: - out->HandleInt32(tokenizer->GetInt32()); - tokenizer->Next(); - return true; - case CBORTokenTag::DOUBLE: - out->HandleDouble(tokenizer->GetDouble()); - tokenizer->Next(); - return true; - case CBORTokenTag::STRING8: - return ParseUTF8String(tokenizer, out); - case CBORTokenTag::STRING16: - ParseUTF16String(tokenizer, out); - return true; - case CBORTokenTag::BINARY: { - span<uint8_t> binary = tokenizer->GetBinary(); - out->HandleBinary(std::vector<uint8_t>(binary.begin(), binary.end())); - tokenizer->Next(); - return true; - } - case CBORTokenTag::MAP_START: - return ParseMap(stack_depth + 1, tokenizer, out); - case CBORTokenTag::ARRAY_START: - return ParseArray(stack_depth + 1, tokenizer, out); - default: - out->HandleError( - Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos}); - return false; - } -} - -// |bytes| must start with the indefinite length array byte, so basically, -// ParseArray may only be called after an indefinite length array has been -// detected. -bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START); - tokenizer->Next(); - out->HandleArrayBegin(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { - if (tokenizer->TokenTag() == CBORTokenTag::DONE) { - out->HandleError( - Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos}); - return false; - } - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { - out->HandleError(tokenizer->Status()); - return false; - } - // Parse value. - if (!ParseValue(stack_depth, tokenizer, out)) return false; - } - out->HandleArrayEnd(); - tokenizer->Next(); - return true; -} - -// |bytes| must start with the indefinite length array byte, so basically, -// ParseArray may only be called after an indefinite length array has been -// detected. -bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START); - out->HandleObjectBegin(); - tokenizer->Next(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { - if (tokenizer->TokenTag() == CBORTokenTag::DONE) { - out->HandleError( - Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos}); - return false; - } - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { - out->HandleError(tokenizer->Status()); - return false; - } - // Parse key. - if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { - if (!ParseUTF8String(tokenizer, out)) - return false; - } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { - ParseUTF16String(tokenizer, out); - } else { - out->HandleError( - Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos}); - return false; - } - // Parse value. - if (!ParseValue(stack_depth, tokenizer, out)) return false; - } - out->HandleObjectEnd(); - tokenizer->Next(); - return true; -} -} // namespace - -void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out) { - if (bytes.empty()) { - json_out->HandleError(Status{Error::CBOR_NO_INPUT, 0}); - return; - } - if (bytes[0] != kInitialByteForEnvelope) { - json_out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0}); - return; - } - CBORTokenizer tokenizer(bytes); - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { - json_out->HandleError(tokenizer.Status()); - return; - } - // We checked for the envelope start byte above, so the tokenizer - // must agree here, since it's not an error. - assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE); - tokenizer.EnterEnvelope(); - if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) { - json_out->HandleError( - Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos}); - return; - } - if (!ParseMap(/*stack_depth=*/1, &tokenizer, json_out)) return; - if (tokenizer.TokenTag() == CBORTokenTag::DONE) return; - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { - json_out->HandleError(tokenizer.Status()); - return; - } - json_out->HandleError( - Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos}); -} - -CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) { - ReadNextToken(/*enter_envelope=*/false); -} -CBORTokenizer::~CBORTokenizer() {} - -CBORTokenTag CBORTokenizer::TokenTag() const { return token_tag_; } - -void CBORTokenizer::Next() { - if (token_tag_ == CBORTokenTag::ERROR_VALUE || token_tag_ == CBORTokenTag::DONE) - return; - ReadNextToken(/*enter_envelope=*/false); -} - -void CBORTokenizer::EnterEnvelope() { - assert(token_tag_ == CBORTokenTag::ENVELOPE); - ReadNextToken(/*enter_envelope=*/true); -} - -Status CBORTokenizer::Status() const { return status_; } - -int32_t CBORTokenizer::GetInt32() const { - assert(token_tag_ == CBORTokenTag::INT32); - // The range checks happen in ::ReadNextToken(). - return static_cast<uint32_t>( - token_start_type_ == MajorType::UNSIGNED - ? token_start_internal_value_ - : -static_cast<int64_t>(token_start_internal_value_) - 1); -} - -double CBORTokenizer::GetDouble() const { - assert(token_tag_ == CBORTokenTag::DOUBLE); - union { - uint64_t from_uint64; - double to_double; - } reinterpret; - reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>( - bytes_.subspan(status_.pos + 1)); - return reinterpret.to_double; -} - -span<uint8_t> CBORTokenizer::GetString8() const { - assert(token_tag_ == CBORTokenTag::STRING8); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -span<uint8_t> CBORTokenizer::GetString16WireRep() const { - assert(token_tag_ == CBORTokenTag::STRING16); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -span<uint8_t> CBORTokenizer::GetBinary() const { - assert(token_tag_ == CBORTokenTag::BINARY); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -void CBORTokenizer::ReadNextToken(bool enter_envelope) { - if (enter_envelope) { - status_.pos += kEncodedEnvelopeHeaderSize; - } else { - status_.pos = - status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_; - } - status_.error = Error::OK; - if (status_.pos >= bytes_.size()) { - token_tag_ = CBORTokenTag::DONE; - return; - } - switch (bytes_[status_.pos]) { - case kStopByte: - SetToken(CBORTokenTag::STOP, 1); - return; - case kInitialByteIndefiniteLengthMap: - SetToken(CBORTokenTag::MAP_START, 1); - return; - case kInitialByteIndefiniteLengthArray: - SetToken(CBORTokenTag::ARRAY_START, 1); - return; - case kEncodedTrue: - SetToken(CBORTokenTag::TRUE_VALUE, 1); - return; - case kEncodedFalse: - SetToken(CBORTokenTag::FALSE_VALUE, 1); - return; - case kEncodedNull: - SetToken(CBORTokenTag::NULL_VALUE, 1); - return; - case kExpectedConversionToBase64Tag: { // BINARY - int8_t bytes_read = - ReadTokenStart(bytes_.subspan(status_.pos + 1), &token_start_type_, - &token_start_internal_value_); - int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_; - if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING || - status_.pos + token_byte_length > bytes_.size()) { - SetError(Error::CBOR_INVALID_BINARY); - return; - } - SetToken(CBORTokenTag::BINARY, - static_cast<std::ptrdiff_t>(token_byte_length)); - return; - } - case kInitialByteForDouble: { // DOUBLE - if (status_.pos + kEncodedDoubleSize > bytes_.size()) { - SetError(Error::CBOR_INVALID_DOUBLE); - return; - } - SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize); - return; - } - case kInitialByteForEnvelope: { // ENVELOPE - if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - // The envelope must be a byte string with 32 bit length. - if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - // Read the length of the byte string. - token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>( - bytes_.subspan(status_.pos + 2)); - // Make sure the payload is contained within the message. - if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize + - status_.pos > - static_cast<std::size_t>(bytes_.size())) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::ENVELOPE, - kEncodedEnvelopeHeaderSize + length); - return; - } - default: { - span<uint8_t> remainder = - bytes_.subspan(status_.pos, bytes_.size() - status_.pos); - assert(!remainder.empty()); - int8_t token_start_length = ReadTokenStart(remainder, &token_start_type_, - &token_start_internal_value_); - bool success = token_start_length != -1; - switch (token_start_type_) { - case MajorType::UNSIGNED: // INT32. - if (!success || std::numeric_limits<int32_t>::max() < - token_start_internal_value_) { - SetError(Error::CBOR_INVALID_INT32); - return; - } - SetToken(CBORTokenTag::INT32, token_start_length); - return; - case MajorType::NEGATIVE: // INT32. - if (!success || - std::numeric_limits<int32_t>::min() > - -static_cast<int64_t>(token_start_internal_value_) - 1) { - SetError(Error::CBOR_INVALID_INT32); - return; - } - SetToken(CBORTokenTag::INT32, token_start_length); - return; - case MajorType::STRING: { // STRING8. - if (!success || remainder.size() < static_cast<int64_t>( - token_start_internal_value_)) { - SetError(Error::CBOR_INVALID_STRING8); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::STRING8, token_start_length + length); - return; - } - case MajorType::BYTE_STRING: { // STRING16. - if (!success || - remainder.size() < - static_cast<int64_t>(token_start_internal_value_) || - // Must be divisible by 2 since UTF16 is 2 bytes per character. - token_start_internal_value_ & 1) { - SetError(Error::CBOR_INVALID_STRING16); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::STRING16, token_start_length + length); - return; - } - case MajorType::ARRAY: - case MajorType::MAP: - case MajorType::TAG: - case MajorType::SIMPLE_VALUE: - SetError(Error::CBOR_UNSUPPORTED_VALUE); - return; - } - } - } -} - -void CBORTokenizer::SetToken(CBORTokenTag token_tag, - std::ptrdiff_t token_byte_length) { - token_tag_ = token_tag; - token_byte_length_ = token_byte_length; -} - -void CBORTokenizer::SetError(Error error) { - token_tag_ = CBORTokenTag::ERROR_VALUE; - status_.error = error; -} - -#if 0 -void DumpCBOR(span<uint8_t> cbor) { - std::string indent; - CBORTokenizer tokenizer(cbor); - while (true) { - fprintf(stderr, "%s", indent.c_str()); - switch (tokenizer.TokenTag()) { - case CBORTokenTag::ERROR_VALUE: - fprintf(stderr, "ERROR {status.error=%d, status.pos=%ld}\n", - tokenizer.Status().error, tokenizer.Status().pos); - return; - case CBORTokenTag::DONE: - fprintf(stderr, "DONE\n"); - return; - case CBORTokenTag::TRUE_VALUE: - fprintf(stderr, "TRUE_VALUE\n"); - break; - case CBORTokenTag::FALSE_VALUE: - fprintf(stderr, "FALSE_VALUE\n"); - break; - case CBORTokenTag::NULL_VALUE: - fprintf(stderr, "NULL_VALUE\n"); - break; - case CBORTokenTag::INT32: - fprintf(stderr, "INT32 [%d]\n", tokenizer.GetInt32()); - break; - case CBORTokenTag::DOUBLE: - fprintf(stderr, "DOUBLE [%lf]\n", tokenizer.GetDouble()); - break; - case CBORTokenTag::STRING8: { - span<uint8_t> v = tokenizer.GetString8(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "STRING8 [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::STRING16: { - span<uint8_t> v = tokenizer.GetString16WireRep(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "STRING16 [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::BINARY: { - span<uint8_t> v = tokenizer.GetBinary(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "BINARY [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::MAP_START: - fprintf(stderr, "MAP_START\n"); - indent += " "; - break; - case CBORTokenTag::ARRAY_START: - fprintf(stderr, "ARRAY_START\n"); - indent += " "; - break; - case CBORTokenTag::STOP: - fprintf(stderr, "STOP\n"); - indent.erase(0, 2); - break; - case CBORTokenTag::ENVELOPE: - fprintf(stderr, "ENVELOPE\n"); - tokenizer.EnterEnvelope(); - continue; - } - tokenizer.Next(); - } -} -#endif - -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/cbor.h b/third_party/inspector_protocol/encoding/cbor.h deleted file mode 100644 index 2785f633..0000000 --- a/third_party/inspector_protocol/encoding/cbor.h +++ /dev/null
@@ -1,280 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_CBOR_H_ -#define INSPECTOR_PROTOCOL_ENCODING_CBOR_H_ - -#include <cstdint> -#include <memory> -#include <vector> -#include "cbor_internals.h" -#include "json_parser_handler.h" -#include "span.h" -#include "status.h" - -namespace inspector_protocol { - -namespace cbor { - -// The major types from RFC 7049 Section 2.1. -enum class MajorType { - UNSIGNED = 0, - NEGATIVE = 1, - BYTE_STRING = 2, - STRING = 3, - ARRAY = 4, - MAP = 5, - TAG = 6, - SIMPLE_VALUE = 7 -}; - -// Indicates the number of bits the "initial byte" needs to be shifted to the -// right after applying |kMajorTypeMask| to produce the major type in the -// lowermost bits. -static constexpr uint8_t kMajorTypeBitShift = 5u; -// Mask selecting the low-order 5 bits of the "initial byte", which is where -// the additional information is encoded. -static constexpr uint8_t kAdditionalInformationMask = 0x1f; -// Mask selecting the high-order 3 bits of the "initial byte", which indicates -// the major type of the encoded value. -static constexpr uint8_t kMajorTypeMask = 0xe0; -// Indicates the integer is in the following byte. -static constexpr uint8_t kAdditionalInformation1Byte = 24u; -// Indicates the integer is in the next 2 bytes. -static constexpr uint8_t kAdditionalInformation2Bytes = 25u; -// Indicates the integer is in the next 4 bytes. -static constexpr uint8_t kAdditionalInformation4Bytes = 26u; -// Indicates the integer is in the next 8 bytes. -static constexpr uint8_t kAdditionalInformation8Bytes = 27u; - -// Encodes the initial byte, consisting of the |type| in the first 3 bits -// followed by 5 bits of |additional_info|. -constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { - return (static_cast<uint8_t>(type) << kMajorTypeBitShift) | - (additional_info & kAdditionalInformationMask); -} - -// TAG 24 indicates that what follows is a byte string which is -// encoded in CBOR format. We use this as a wrapper for -// maps and arrays, allowing us to skip them, because the -// byte string carries its size (byte length). -// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 -static constexpr uint8_t kInitialByteForEnvelope = - EncodeInitialByte(MajorType::TAG, 24); -// The initial byte for a byte string with at most 2^32 bytes -// of payload. This is used for envelope encoding, even if -// the byte string is shorter. -static constexpr uint8_t kInitialByteFor32BitLengthByteString = - EncodeInitialByte(MajorType::BYTE_STRING, 26); - -// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional -// info = 31. -static constexpr uint8_t kInitialByteIndefiniteLengthArray = - EncodeInitialByte(MajorType::ARRAY, 31); -static constexpr uint8_t kInitialByteIndefiniteLengthMap = - EncodeInitialByte(MajorType::MAP, 31); -// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite -// length maps / arrays. -static constexpr uint8_t kStopByte = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); - -} // namespace cbor - -// The binary encoding for the inspector protocol follows the CBOR specification -// (RFC 7049). Additional constraints: -// - Only indefinite length maps and arrays are supported. -// - Maps and arrays are wrapped with an envelope, that is, a -// CBOR tag with value 24 followed by a byte string specifying -// the byte length of the enclosed map / array. The byte string -// must use a 32 bit wide length. -// - At the top level, a message must be an indefinite length map -// wrapped by an envelope. -// - Maximal size for messages is 2^32 (4 GB). -// - For scalars, we support only the int32_t range, encoded as -// UNSIGNED/NEGATIVE (major types 0 / 1). -// - UTF16 strings, including with unbalanced surrogate pairs, are encoded -// as CBOR BYTE_STRING (major type 2). For such strings, the number of -// bytes encoded must be even. -// - UTF8 strings (major type 3) are supported. -// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not -// as UTF16 strings. -// - Arbitrary byte arrays, in the inspector protocol called 'binary', -// are encoded as BYTE_STRING (major type 2), prefixed with a byte -// indicating base64 when rendered as JSON. - -// Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE| -// (major type 1) iff < 0. -void EncodeInt32(int32_t value, std::vector<uint8_t>* out); - -// Encodes a UTF16 string as a BYTE_STRING (major type 2). Each utf16 -// character in |in| is emitted with most significant byte first, -// appending to |out|. -void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out); - -// Encodes a UTF8 string |in| as STRING (major type 3). -void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out); - -// Encodes the given |latin1| string as STRING8. -// If any non-ASCII character is present, it will be represented -// as a 2 byte UTF8 sequence. -void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out); - -// Encodes the given |utf16| string as STRING8 if it's entirely US-ASCII. -// Otherwise, encodes as STRING16. -void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out); - -// Encodes arbitrary binary data in |in| as a BYTE_STRING (major type 2) with -// definitive length, prefixed with tag 22 indicating expected conversion to -// base64 (see RFC 7049, Table 3 and Section 2.4.4.2). -void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out); - -// Encodes / decodes a double as Major type 7 (SIMPLE_VALUE), -// with additional info = 27, followed by 8 bytes in big endian. -void EncodeDouble(double value, std::vector<uint8_t>* out); - -// Some constants for CBOR tokens that only take a single byte on the wire. -uint8_t EncodeTrue(); -uint8_t EncodeFalse(); -uint8_t EncodeNull(); -uint8_t EncodeIndefiniteLengthArrayStart(); -uint8_t EncodeIndefiniteLengthMapStart(); -uint8_t EncodeStop(); - -// An envelope indicates the byte length of a wrapped item. -// We use this for maps and array, which allows the decoder -// to skip such (nested) values whole sale. -// It's implemented as a CBOR tag (major type 6) with additional -// info = 24, followed by a byte string with a 32 bit length value; -// so the maximal structure that we can wrap is 2^32 bits long. -// See also: https://tools.ietf.org/html/rfc7049#section-2.4.4.1 -class EnvelopeEncoder { - public: - // Emits the envelope start bytes and records the position for the - // byte size in |byte_size_pos_|. Also emits empty bytes for the - // byte sisze so that encoding can continue. - void EncodeStart(std::vector<uint8_t>* out); - // This records the current size in |out| at position byte_size_pos_. - // Returns true iff successful. - bool EncodeStop(std::vector<uint8_t>* out); - - private: - std::size_t byte_size_pos_ = 0; -}; - -// This can be used to convert from JSON to CBOR, by passing the -// return value to the routines in json_parser.h. The handler will encode into -// |out|, and iff an error occurs it will set |status| to an error and clear -// |out|. Otherwise, |status.ok()| will be |true|. -std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder( - std::vector<uint8_t>* out, Status* status); - -// Parses a CBOR encoded message from |bytes|, sending JSON events to -// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops. -// The client is responsible for discarding the already received information in -// that case. -void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out); - -// Tags for the tokens within a CBOR message that CBORStream understands. -// Note that this is not the same terminology as the CBOR spec (RFC 7049), -// but rather, our adaptation. For instance, we lump unsigned and signed -// major type into INT32 here (and disallow values outside the int32_t range). -enum class CBORTokenTag { - // Encountered an error in the structure of the message. Consult - // status() for details. - ERROR_VALUE, - // Booleans and NULL. - TRUE_VALUE, - FALSE_VALUE, - NULL_VALUE, - // An int32_t (signed 32 bit integer). - INT32, - // A double (64 bit floating point). - DOUBLE, - // A UTF8 string. - STRING8, - // A UTF16 string. - STRING16, - // A binary string. - BINARY, - // Starts an indefinite length map; after the map start we expect - // alternating keys and values, followed by STOP. - MAP_START, - // Starts an indefinite length array; after the array start we - // expect values, followed by STOP. - ARRAY_START, - // Ends a map or an array. - STOP, - // An envelope indicator, wrapping a map or array. - // Internally this carries the byte length of the wrapped - // map or array. While CBORTokenizer::Next() will read / skip the entire - // envelope, CBORTokenizer::EnterEnvelope() reads the tokens - // inside of it. - ENVELOPE, - // We've reached the end there is nothing else to read. - DONE, -}; - -// CBORTokenizer segments a CBOR message, presenting the tokens therein as -// numbers, strings, etc. This is not a complete CBOR parser, but makes it much -// easier to implement one (e.g. ParseCBOR, above). It can also be used to parse -// messages partially. -class CBORTokenizer { - public: - explicit CBORTokenizer(span<uint8_t> bytes); - ~CBORTokenizer(); - - // Identifies the current token that we're looking at, - // or ERROR_VALUE (in which ase ::Status() has details) - // or DONE (if we're past the last token). - CBORTokenTag TokenTag() const; - - // Advances to the next token. - void Next(); - // Can only be called if TokenTag() == CBORTokenTag::ENVELOPE. - // While Next() would skip past the entire envelope / what it's - // wrapping, EnterEnvelope positions the cursor inside of the envelope, - // letting the client explore the nested structure. - void EnterEnvelope(); - - // If TokenTag() is CBORTokenTag::ERROR_VALUE, then Status().error describes - // the error more precisely; otherwise it'll be set to Error::OK. - // In either case, Status().pos is the current position. - struct Status Status() const; - - // The following methods retrieve the token values. They can only - // be called if TokenTag() matches. - - // To be called only if ::TokenTag() == CBORTokenTag::INT32. - int32_t GetInt32() const; - - // To be called only if ::TokenTag() == CBORTokenTag::DOUBLE. - double GetDouble() const; - - // To be called only if ::TokenTag() == CBORTokenTag::STRING8. - span<uint8_t> GetString8() const; - - // Wire representation for STRING16 is low byte first (little endian). - // To be called only if ::TokenTag() == CBORTokenTag::STRING16. - span<uint8_t> GetString16WireRep() const; - - // To be called only if ::TokenTag() == CBORTokenTag::BINARY. - span<uint8_t> GetBinary() const; - - private: - void ReadNextToken(bool enter_envelope); - void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length); - void SetError(Error error); - - span<uint8_t> bytes_; - CBORTokenTag token_tag_; - struct Status status_; - std::ptrdiff_t token_byte_length_; - cbor::MajorType token_start_type_; - uint64_t token_start_internal_value_; -}; - -void DumpCBOR(span<uint8_t> cbor); - -} // namespace inspector_protocol -#endif // INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
diff --git a/third_party/inspector_protocol/encoding/cbor_internals.h b/third_party/inspector_protocol/encoding/cbor_internals.h deleted file mode 100644 index e2621d89..0000000 --- a/third_party/inspector_protocol/encoding/cbor_internals.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_CBOR_INTERNALS_H_ -#define INSPECTOR_PROTOCOL_ENCODING_CBOR_INTERNALS_H_ - -#include <cstdint> -#include <vector> -#include "span.h" -#include "status.h" - -// These internals are exposed for testing and implementing cbor.h. -// Never directly depend on them from other production code. -namespace inspector_protocol { -namespace cbor { -enum class MajorType; -} - -namespace cbor_internals { - -// Reads the start of a token with definitive size from |bytes|. -// |type| is the major type as specified in RFC 7049 Section 2.1. -// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size -// (e.g. for BYTE_STRING). -// If successful, returns the number of bytes read. Otherwise returns -1. -int8_t ReadTokenStart(span<uint8_t> bytes, - cbor::MajorType* type, - uint64_t* value); - -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(cbor::MajorType type, - uint64_t value, - std::vector<uint8_t>* encoded); -} // namespace cbor_internals -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_CBOR_H_
diff --git a/third_party/inspector_protocol/encoding/cbor_test.cc b/third_party/inspector_protocol/encoding/cbor_test.cc deleted file mode 100644 index 9f6201f..0000000 --- a/third_party/inspector_protocol/encoding/cbor_test.cc +++ /dev/null
@@ -1,994 +0,0 @@ -// Copyright 2018 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 "cbor.h" - -#include <array> -#include <cmath> -#include <string> -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "json_parser.h" -#include "json_std_string_writer.h" -#include "linux_dev_platform.h" - -using testing::ElementsAreArray; - -namespace inspector_protocol { - -using cbor::MajorType; - -// -// EncodeInt32 / CBORTokenTag::INT32 -// -TEST(EncodeDecodeInt32Test, Roundtrips23) { - // This roundtrips the int32_t value 23 through the pair of EncodeInt32 / - // CBORTokenizer; this is interesting since 23 is encoded as a single byte. - std::vector<uint8_t> encoded; - EncodeInt32(23, &encoded); - // first three bits: major type = 0; remaining five bits: additional info = - // value 23. - EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}})); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(23, tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeInt32Test, RoundtripsUint8) { - // This roundtrips the int32_t value 42 through the pair of EncodeInt32 / - // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded - // in an extra byte after the initial one. - std::vector<uint8_t> encoded; - EncodeInt32(42, &encoded); - // first three bits: major type = 0; - // remaining five bits: additional info = 24, indicating payload is uint8. - EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}})); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(42, tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeInt32Test, RoundtripsUint16) { - // 500 is encoded as a uint16 after the initial byte. - std::vector<uint8_t> encoded; - EncodeInt32(500, &encoded); - // 1 for initial byte, 2 for uint16. - EXPECT_EQ(static_cast<std::size_t>(3), encoded.size()); - // first three bits: major type = 0; - // remaining five bits: additional info = 25, indicating payload is uint16. - EXPECT_EQ(25, encoded[0]); - EXPECT_EQ(0x01, encoded[1]); - EXPECT_EQ(0xf4, encoded[2]); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(500, tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) { - // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte. - std::vector<uint8_t> encoded; - EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded); - // 1 for initial byte, 4 for the uint32. - // first three bits: major type = 0; - // remaining five bits: additional info = 26, indicating payload is uint32. - EXPECT_THAT( - encoded, - ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}})); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeInt32Test, CantRoundtripUint32) { - // 0xdeadbeef is a value which does not fit below - // std::numerical_limits<int32_t>::max(), so we can't encode - // it with EncodeInt32. However, CBOR does support this, so we - // encode it here manually with the internal routine, just to observe - // that it's considered an invalid int32 by CBORTokenizer. - std::vector<uint8_t> encoded; - cbor_internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded); - // 1 for initial byte, 4 for the uint32. - // first three bits: major type = 0; - // remaining five bits: additional info = 26, indicating payload is uint32. - EXPECT_THAT( - encoded, - ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}})); - - // Now try to decode; we treat this as an invalid INT32. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - // 0xdeadbeef is > std::numerical_limits<int32_t>::max(). - EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); - EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error); -} - -TEST(EncodeDecodeInt32Test, DecodeErrorCases) { - struct TestCase { - std::vector<uint8_t> data; - std::string msg; - }; - std::vector<TestCase> tests{ - {TestCase{ - {24}, - "additional info = 24 would require 1 byte of payload (but it's 0)"}, - TestCase{{27, 0xaa, 0xbb, 0xcc}, - "additional info = 27 would require 8 bytes of payload (but " - "it's 3)"}, - TestCase{{29}, "additional info = 29 isn't recognized"}}}; - - for (const TestCase& test : tests) { - SCOPED_TRACE(test.msg); - span<uint8_t> encoded_bytes(&test.data[0], test.data.size()); - CBORTokenizer tokenizer( - span<uint8_t>(&encoded_bytes[0], encoded_bytes.size())); - EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); - EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error); - } -} - -TEST(EncodeDecodeInt32Test, RoundtripsMinus24) { - // This roundtrips the int32_t value -24 through the pair of EncodeInt32 / - // CBORTokenizer; this is interesting since -24 is encoded as - // a single byte as NEGATIVE, and it tests the specific encoding - // (note how for unsigned the single byte covers values up to 23). - // Additional examples are covered in RoundtripsAdditionalExamples. - std::vector<uint8_t> encoded; - EncodeInt32(-24, &encoded); - // first three bits: major type = 1; remaining five bits: additional info = - // value 23. - EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}})); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(-24, tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) { - std::vector<int32_t> examples = {-1, - -10, - -24, - -25, - -300, - -30000, - -300 * 1000, - -1000 * 1000, - -1000 * 1000 * 1000, - std::numeric_limits<int32_t>::min()}; - for (int32_t example : examples) { - SCOPED_TRACE(base::StringPrintf("example %d", example)); - std::vector<uint8_t> encoded; - EncodeInt32(example, &encoded); - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); - EXPECT_EQ(example, tokenizer.GetInt32()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); - } -} - -// -// EncodeString16 / CBORTokenTag::STRING16 -// -TEST(EncodeDecodeString16Test, RoundtripsEmpty) { - // This roundtrips the empty utf16 string through the pair of EncodeString16 / - // CBORTokenizer. - std::vector<uint8_t> encoded; - EncodeString16(span<uint16_t>(), &encoded); - EXPECT_EQ(static_cast<std::size_t>(1), encoded.size()); - // first three bits: major type = 2; remaining five bits: additional info = - // size 0. - EXPECT_EQ(2 << 5, encoded[0]); - - // Reverse direction: decode with CBORTokenizer. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); - span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep(); - EXPECT_TRUE(decoded_string16_wirerep.empty()); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -// On the wire, we STRING16 is encoded as little endian (least -// significant byte first). The host may or may not be little endian, -// so this routine follows the advice in -// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html. -std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) { - assert((in.size() & 1) == 0); // must be even number of bytes. - std::vector<uint16_t> host_out; - for (std::ptrdiff_t ii = 0; ii < in.size(); ii += 2) - host_out.push_back(in[ii + 1] << 8 | in[ii]); - return host_out; -} - -TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) { - // This roundtrips the hello world message which is given here in utf16 - // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas" - // character, 🌎. - std::array<uint16_t, 10> msg{ - {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}}; - std::vector<uint8_t> encoded; - EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded); - // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in - // the additional info part of the initial byte. Payload is two bytes for each - // UTF16 character. - uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20; - std::array<uint8_t, 21> encoded_expected = { - {initial_byte, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, - ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}; - EXPECT_THAT(encoded, ElementsAreArray(encoded_expected)); - - // Now decode to complete the roundtrip. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); - std::vector<uint16_t> decoded = - String16WireRepToHost(tokenizer.GetString16WireRep()); - EXPECT_THAT(decoded, ElementsAreArray(msg)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); - - // For bonus points, we look at the decoded message in UTF8 as well so we can - // easily see it on the terminal screen. - std::string utf8_decoded = - base::UTF16ToUTF8(base::StringPiece16(decoded.data(), decoded.size())); - EXPECT_EQ("Hello, 🌎.", utf8_decoded); -} - -TEST(EncodeDecodeString16Test, Roundtrips500) { - // We roundtrip a message that has 250 16 bit values. Each of these are just - // set to their index. 250 is interesting because the cbor spec uses a - // BYTE_STRING of length 500 for one of their examples of how to encode the - // start of it (section 2.1) so it's easy for us to look at the first three - // bytes closely. - std::vector<uint16_t> two_fifty; - for (uint16_t ii = 0; ii < 250; ++ii) two_fifty.push_back(ii); - std::vector<uint8_t> encoded; - EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded); - EXPECT_EQ(static_cast<std::size_t>(3 + 250 * 2), encoded.size()); - // Now check the first three bytes: - // Major type: 2 (BYTE_STRING) - // Additional information: 25, indicating size is represented by 2 bytes. - // Bytes 1 and 2 encode 500 (0x01f4). - EXPECT_EQ(2 << 5 | 25, encoded[0]); - EXPECT_EQ(0x01, encoded[1]); - EXPECT_EQ(0xf4, encoded[2]); - - // Now decode to complete the roundtrip. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); - std::vector<uint16_t> decoded = - String16WireRepToHost(tokenizer.GetString16WireRep()); - EXPECT_THAT(decoded, ElementsAreArray(two_fifty)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeString16Test, ErrorCases) { - struct TestCase { - std::vector<uint8_t> data; - std::string msg; - }; - std::vector<TestCase> tests{ - {TestCase{{2 << 5 | 1, 'a'}, - "length must be divisible by 2 (but it's 1)"}, - TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"}}}; - for (const TestCase& test : tests) { - SCOPED_TRACE(test.msg); - CBORTokenizer tokenizer(span<uint8_t>(&test.data[0], test.data.size())); - EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); - EXPECT_EQ(Error::CBOR_INVALID_STRING16, tokenizer.Status().error); - } -} - -// -// EncodeString8 / CBORTokenTag::STRING8 -// -TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) { - // This roundtrips the hello world message which is given here in utf8 - // characters. 🌎 is a four byte utf8 character. - std::string utf8_msg = "Hello, 🌎."; - std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end()); - std::vector<uint8_t> encoded; - EncodeString8(span<uint8_t>(msg.data(), msg.size()), &encoded); - // This will be encoded as STRING of length 12, so the 12 is encoded in - // the additional info part of the initial byte. Payload is one byte per - // utf8 byte. - uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12; - std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l', - 'o', ',', ' ', 0xF0, 0x9f, 0x8c, - 0x8e, '.'}}; - EXPECT_THAT(encoded, ElementsAreArray(encoded_expected)); - - // Now decode to complete the roundtrip. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); - std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), - tokenizer.GetString8().end()); - EXPECT_THAT(decoded, ElementsAreArray(msg)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) { - std::vector<std::pair<std::string, std::string>> examples = { - {"Hello, world.", "Hello, world."}, - {"Above: \xDC" - "ber", - "Above: Über"}, - {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF", - "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}}; - - for (const auto& example : examples) { - const std::string& latin1 = example.first; - const std::string& expected_utf8 = example.second; - std::vector<uint8_t> encoded; - EncodeFromLatin1( - span<uint8_t>(reinterpret_cast<const uint8_t*>(latin1.data()), - latin1.size()), - &encoded); - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); - std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), - tokenizer.GetString8().end()); - std::string decoded_str(decoded.begin(), decoded.end()); - EXPECT_THAT(decoded_str, testing::Eq(expected_utf8)); - } -} - -TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) { - std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'}; - std::vector<uint8_t> encoded; - EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded); - - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); - std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), - tokenizer.GetString8().end()); - std::string decoded_str(decoded.begin(), decoded.end()); - EXPECT_THAT(decoded_str, testing::Eq("easy")); -} - -TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) { - // Since this message contains non-ASCII characters, the routine is - // forced to encode as UTF16. We see this below by checking that the - // token tag is STRING16. - std::vector<uint16_t> msg = {'H', 'e', 'l', 'l', 'o', - ',', ' ', 0xd83c, 0xdf0e, '.'}; - std::vector<uint8_t> encoded; - EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded); - - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); - std::vector<uint16_t> decoded = - String16WireRepToHost(tokenizer.GetString16WireRep()); - std::string utf8_decoded = - base::UTF16ToUTF8(base::StringPiece16(decoded.data(), decoded.size())); - EXPECT_EQ("Hello, 🌎.", utf8_decoded); -} - -// -// EncodeBinary / CBORTokenTag::BINARY -// -TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) { - std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ', - 'w', 'o', 'r', 'l', 'd', '.'}; - std::vector<uint8_t> encoded; - EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded); - // So, on the wire we see that the binary blob travels unmodified. - EXPECT_THAT( - encoded, - ElementsAreArray(std::array<uint8_t, 15>{ - {(6 << 5 | 22), // tag 22 indicating base64 interpretation in JSON - (2 << 5 | 13), // BYTE_STRING (type 2) of length 13 - 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}})); - std::vector<uint8_t> decoded; - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag()); - EXPECT_EQ(0, int(tokenizer.Status().error)); - decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(), - tokenizer.GetBinary().end()); - EXPECT_THAT(decoded, ElementsAreArray(binary)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -// -// EncodeDouble / CBORTokenTag::DOUBLE -// -TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) { - // https://en.wikipedia.org/wiki/Double-precision_floating-point_format - // provides the example of a hex representation 3FD5 5555 5555 5555, which - // approximates 1/3. - - const double kOriginalValue = 1.0 / 3; - std::vector<uint8_t> encoded; - EncodeDouble(kOriginalValue, &encoded); - // first three bits: major type = 7; remaining five bits: additional info = - // value 27. This is followed by 8 bytes of payload (which match Wikipedia). - EXPECT_THAT( - encoded, - ElementsAreArray(std::array<uint8_t, 9>{ - {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}})); - - // Reverse direction: decode and compare with original value. - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag()); - EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); -} - -TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) { - std::vector<double> examples = {0.0, - 1.0, - -1.0, - 3.1415, - std::numeric_limits<double>::min(), - std::numeric_limits<double>::max(), - std::numeric_limits<double>::infinity(), - std::numeric_limits<double>::quiet_NaN()}; - for (double example : examples) { - SCOPED_TRACE(base::StringPrintf("example %lf", example)); - std::vector<uint8_t> encoded; - EncodeDouble(example, &encoded); - span<uint8_t> encoded_bytes(&encoded[0], encoded.size()); - CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); - EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag()); - if (std::isnan(example)) - EXPECT_TRUE(std::isnan(tokenizer.GetDouble())); - else - EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example)); - tokenizer.Next(); - EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); - } -} - -// -// NewJSONToCBOREncoder -// -void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) { - EncodeString8( - span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size()), - out); -} - -TEST(JSONToCBOREncoderTest, SevenBitStrings) { - // When a string can be represented as 7 bit ASCII, the encoder will use the - // STRING (major Type 3) type, so the actual characters end up as bytes on the - // wire. - std::vector<uint8_t> encoded; - Status status; - std::unique_ptr<JSONParserHandler> encoder = - NewJSONToCBOREncoder(&encoded, &status); - std::vector<uint16_t> utf16 = {'f', 'o', 'o'}; - encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size())); - EXPECT_EQ(Error::OK, status.error); - // Here we assert that indeed, seven bit strings are represented as - // bytes on the wire, "foo" is just "foo". - EXPECT_THAT(encoded, - ElementsAreArray(std::array<uint8_t, 4>{ - {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}})); -} - -TEST(JsonCborRoundtrip, EncodingDecoding) { - // Hits all the cases except binary and error in JSONParserHandler, first - // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON. - std::string json = - "{" - "\"string\":\"Hello, \\ud83c\\udf0e.\"," - "\"double\":3.1415," - "\"int\":1," - "\"negative int\":-1," - "\"bool\":true," - "\"null\":null," - "\"array\":[1,2,3]" - "}"; - std::vector<uint8_t> encoded; - Status status; - std::unique_ptr<JSONParserHandler> encoder = - NewJSONToCBOREncoder(&encoded, &status); - span<uint8_t> ascii_in(reinterpret_cast<const uint8_t*>(json.data()), - json.size()); - ParseJSONChars(GetLinuxDevPlatform(), ascii_in, encoder.get()); - std::vector<uint8_t> expected = { - 0xd8, // envelope - 0x5a, // byte string with 32 bit length - 0, 0, 0, 94, // length is 94 bytes - }; - expected.push_back(0xbf); // indef length map start - EncodeUTF8ForTest("string", &expected); - // This is followed by the encoded string for "Hello, 🌎." - // So, it's the same bytes that we tested above in - // EncodeDecodeString16Test.RoundtripsHelloWorld. - expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20); - for (uint8_t ch : std::array<uint8_t, 20>{ - {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, - ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}) - expected.push_back(ch); - EncodeUTF8ForTest("double", &expected); - EncodeDouble(3.1415, &expected); - EncodeUTF8ForTest("int", &expected); - EncodeInt32(1, &expected); - EncodeUTF8ForTest("negative int", &expected); - EncodeInt32(-1, &expected); - EncodeUTF8ForTest("bool", &expected); - expected.push_back(7 << 5 | 21); // RFC 7049 Section 2.3, Table 2: true - EncodeUTF8ForTest("null", &expected); - expected.push_back(7 << 5 | 22); // RFC 7049 Section 2.3, Table 2: null - EncodeUTF8ForTest("array", &expected); - expected.push_back(0xd8); // envelope - expected.push_back(0x5a); // byte string with 32 bit length - // the length is 5 bytes (that's up to end indef length array below). - for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}}) - expected.push_back(ch); - expected.push_back(0x9f); // RFC 7049 Section 2.2.1, indef length array start - expected.push_back(1); // Three UNSIGNED values (easy since Major Type 0) - expected.push_back(2); - expected.push_back(3); - expected.push_back(0xff); // End indef length array - expected.push_back(0xff); // End indef length map - EXPECT_TRUE(status.ok()); - EXPECT_THAT(encoded, ElementsAreArray(expected)); - - // And now we roundtrip, decoding the message we just encoded. - std::string decoded; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status); - ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ(json, decoded); -} - -TEST(JsonCborRoundtrip, MoreRoundtripExamples) { - std::vector<std::string> examples = { - // Tests that after closing a nested objects, additional key/value pairs - // are considered. - "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"}; - for (const std::string& json : examples) { - SCOPED_TRACE(std::string("example: ") + json); - std::vector<uint8_t> encoded; - Status status; - std::unique_ptr<JSONParserHandler> encoder = - NewJSONToCBOREncoder(&encoded, &status); - span<uint8_t> ascii_in(reinterpret_cast<const uint8_t*>(json.data()), - json.size()); - ParseJSONChars(GetLinuxDevPlatform(), ascii_in, encoder.get()); - std::string decoded; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status); - ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ(json, decoded); - } -} - -TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) { - // The JSONParserHandler::HandleBinary is a special case: The JSON parser will - // never call this method, because JSON does not natively support the binary - // type. So, we can't fully roundtrip. However, the other direction works: - // binary will be rendered in JSON, as a base64 string. So, we make calls to - // the encoder directly here, to construct a message, and one of these calls - // is ::HandleBinary, to which we pass a "binary" string containing "Hello, - // world.". - std::vector<uint8_t> encoded; - Status status; - std::unique_ptr<JSONParserHandler> encoder = - NewJSONToCBOREncoder(&encoded, &status); - encoder->HandleObjectBegin(); - // Emit a key. - std::vector<uint16_t> key = {'f', 'o', 'o'}; - encoder->HandleString16(span<uint16_t>(key.data(), key.size())); - // Emit the binary payload, an arbitrary array of bytes that happens to - // be the ascii message "Hello, world.". - encoder->HandleBinary(std::vector<uint8_t>{'H', 'e', 'l', 'l', 'o', ',', ' ', - 'w', 'o', 'r', 'l', 'd', '.'}); - encoder->HandleObjectEnd(); - EXPECT_EQ(Error::OK, status.error); - - // Now drive the json writer via the CBOR decoder. - std::string decoded; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &decoded, &status); - ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ(Status::npos(), status.pos); - // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==". - EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded); -} - -// -// ParseCBOR -// -TEST(ParseCBORTest, ParseEmptyCBORMessage) { - // An envelope starting with 0xd8, 0x5a, with the byte length - // of 2, containing a map that's empty (0xbf for map - // start, and 0xff for map end). - std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff}; - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ("{}", out); -} - -TEST(ParseCBORTest, ParseCBORHelloWorld) { - const uint8_t kPayloadLen = 27; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen}; - bytes.push_back(0xbf); // start indef length map. - EncodeUTF8ForTest("msg", &bytes); // key: msg - // Now write the value, the familiar "Hello, 🌎." where the globe is expressed - // as two utf16 chars. - bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20); - for (uint8_t ch : std::array<uint8_t, 20>{ - {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, - ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}) - bytes.push_back(ch); - bytes.push_back(0xff); // stop byte - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out); -} - -TEST(ParseCBORTest, UTF8IsSupportedInKeys) { - const uint8_t kPayloadLen = 11; - std::vector<uint8_t> bytes = {cbor::kInitialByteForEnvelope, - cbor::kInitialByteFor32BitLengthByteString, - 0, - 0, - 0, - kPayloadLen}; - bytes.push_back(cbor::kInitialByteIndefiniteLengthMap); - EncodeUTF8ForTest("🌎", &bytes); // Two UTF16 chars. - EncodeUTF8ForTest("☾", &bytes); // Can be encoded as a single UTF16 char. - bytes.push_back(cbor::kStopByte); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out); -} - -TEST(ParseCBORTest, NoInputError) { - std::vector<uint8_t> in = {}; - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_NO_INPUT, status.error); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidStartByteError) { - // Here we test that some actual json, which usually starts with {, - // is not considered CBOR. CBOR messages must start with 0x5a, the - // envelope start byte. - std::string json = "{\"msg\": \"Hello, world.\"}"; - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR( - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, UnexpectedEofExpectedValueError) { - constexpr uint8_t kPayloadLen = 5; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); // A key; so value would be next. - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error); - EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, UnexpectedEofInArrayError) { - constexpr uint8_t kPayloadLen = 8; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // The byte for starting a map. - EncodeUTF8ForTest("array", &bytes); // A key; so value would be next. - bytes.push_back(0x9f); // byte for indefinite length array start. - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error); - EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, UnexpectedEofInMapError) { - constexpr uint8_t kPayloadLen = 1; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // The byte for starting a map. - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error); - EXPECT_EQ(7, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidMapKeyError) { - constexpr uint8_t kPayloadLen = 2; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, - 0, 0, kPayloadLen, // envelope - 0xbf, // map start - 7 << 5 | 22}; // null (not a valid map key) - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error); - EXPECT_EQ(7, status.pos); - EXPECT_EQ("", out); -} - -std::vector<uint8_t> MakeNestedCBOR(int depth) { - std::vector<uint8_t> bytes; - std::vector<EnvelopeEncoder> envelopes; - for (int ii = 0; ii < depth; ++ii) { - envelopes.emplace_back(); - envelopes.back().EncodeStart(&bytes); - bytes.push_back(0xbf); // indef length map start - EncodeUTF8ForTest("key", &bytes); - } - EncodeUTF8ForTest("innermost_value", &bytes); - for (int ii = 0; ii < depth; ++ii) { - bytes.push_back(0xff); // stop byte, finishes map. - envelopes.back().EncodeStop(&bytes); - envelopes.pop_back(); - } - return bytes; -} - -TEST(ParseCBORTest, StackLimitExceededError) { - { // Depth 3: no stack limit exceeded error and is easy to inspect. - std::vector<uint8_t> bytes = MakeNestedCBOR(3); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ(Status::npos(), status.pos); - EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out); - } - { // Depth 1000: no stack limit exceeded. - std::vector<uint8_t> bytes = MakeNestedCBOR(1000); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::OK, status.error); - EXPECT_EQ(Status::npos(), status.pos); - } - - // We just want to know the length of one opening map so we can compute - // where the error is encountered. So we look at a small example and find - // the second envelope start. - std::vector<uint8_t> small_example = MakeNestedCBOR(3); - int64_t opening_segment_size = 1; // Start after the first envelope start. - while (opening_segment_size < static_cast<int64_t>(small_example.size()) && - small_example[opening_segment_size] != 0xd8) - opening_segment_size++; - - { // Depth 1001: limit exceeded. - std::vector<uint8_t> bytes = MakeNestedCBOR(1001); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); - EXPECT_EQ(opening_segment_size * 1001, status.pos); - } - { // Depth 1200: still limit exceeded, and at the same pos as for 1001 - std::vector<uint8_t> bytes = MakeNestedCBOR(1200); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); - EXPECT_EQ(opening_segment_size * 1001, status.pos); - } -} - -TEST(ParseCBORTest, UnsupportedValueError) { - constexpr uint8_t kPayloadLen = 6; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - bytes.push_back(6 << 5 | 5); // tags aren't supported yet. - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidString16Error) { - constexpr uint8_t kPayloadLen = 11; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - // a BYTE_STRING of length 5 as value; since we interpret these as string16, - // it's going to be invalid as each character would need two bytes, but - // 5 isn't divisible by 2. - bytes.push_back(2 << 5 | 5); - for (int ii = 0; ii < 5; ++ii) bytes.push_back(' '); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidString8Error) { - constexpr uint8_t kPayloadLen = 6; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - // a STRING of length 5 as value, but we're at the end of the bytes array - // so it can't be decoded successfully. - bytes.push_back(3 << 5 | 5); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidBinaryError) { - constexpr uint8_t kPayloadLen = 9; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - bytes.push_back(6 << 5 | 22); // base64 hint for JSON; indicates binary - bytes.push_back(2 << 5 | 10); // BYTE_STRING (major type 2) of length 10 - // Just two garbage bytes, not enough for the binary. - bytes.push_back(0x31); - bytes.push_back(0x23); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidDoubleError) { - constexpr uint8_t kPayloadLen = 8; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - bytes.push_back(7 << 5 | 27); // initial byte for double - // Just two garbage bytes, not enough to represent an actual double. - bytes.push_back(0x31); - bytes.push_back(0x23); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, InvalidSignedError) { - constexpr uint8_t kPayloadLen = 14; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - int64_t error_pos = bytes.size(); - // uint64_t max is a perfectly fine value to encode as CBOR unsigned, - // but we don't support this since we only cover the int32_t range. - cbor_internals::WriteTokenStart(MajorType::UNSIGNED, - std::numeric_limits<uint64_t>::max(), &bytes); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - -TEST(ParseCBORTest, TrailingJunk) { - constexpr uint8_t kPayloadLen = 35; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeUTF8ForTest("key", &bytes); - EncodeUTF8ForTest("value", &bytes); - bytes.push_back(0xff); // Up to here, it's a perfectly fine msg. - int64_t error_pos = bytes.size(); - EncodeUTF8ForTest("trailing junk", &bytes); - - cbor_internals::WriteTokenStart(MajorType::UNSIGNED, - std::numeric_limits<uint64_t>::max(), &bytes); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/encoding.cc b/third_party/inspector_protocol/encoding/encoding.cc new file mode 100644 index 0000000..c2c6545a4 --- /dev/null +++ b/third_party/inspector_protocol/encoding/encoding.cc
@@ -0,0 +1,1796 @@ +// Copyright 2019 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 "encoding.h" + +#include <cassert> +#include <cstring> +#include <limits> +#include <stack> + +namespace inspector_protocol_encoding { +namespace cbor { +namespace { +// Indicates the number of bits the "initial byte" needs to be shifted to the +// right after applying |kMajorTypeMask| to produce the major type in the +// lowermost bits. +static constexpr uint8_t kMajorTypeBitShift = 5u; +// Mask selecting the low-order 5 bits of the "initial byte", which is where +// the additional information is encoded. +static constexpr uint8_t kAdditionalInformationMask = 0x1f; +// Mask selecting the high-order 3 bits of the "initial byte", which indicates +// the major type of the encoded value. +static constexpr uint8_t kMajorTypeMask = 0xe0; +// Indicates the integer is in the following byte. +static constexpr uint8_t kAdditionalInformation1Byte = 24u; +// Indicates the integer is in the next 2 bytes. +static constexpr uint8_t kAdditionalInformation2Bytes = 25u; +// Indicates the integer is in the next 4 bytes. +static constexpr uint8_t kAdditionalInformation4Bytes = 26u; +// Indicates the integer is in the next 8 bytes. +static constexpr uint8_t kAdditionalInformation8Bytes = 27u; + +// Encodes the initial byte, consisting of the |type| in the first 3 bits +// followed by 5 bits of |additional_info|. +constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { + return (static_cast<uint8_t>(type) << kMajorTypeBitShift) | + (additional_info & kAdditionalInformationMask); +} + +// TAG 24 indicates that what follows is a byte string which is +// encoded in CBOR format. We use this as a wrapper for +// maps and arrays, allowing us to skip them, because the +// byte string carries its size (byte length). +// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 +static constexpr uint8_t kInitialByteForEnvelope = + EncodeInitialByte(MajorType::TAG, 24); +// The initial byte for a byte string with at most 2^32 bytes +// of payload. This is used for envelope encoding, even if +// the byte string is shorter. +static constexpr uint8_t kInitialByteFor32BitLengthByteString = + EncodeInitialByte(MajorType::BYTE_STRING, 26); + +// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional +// info = 31. +static constexpr uint8_t kInitialByteIndefiniteLengthArray = + EncodeInitialByte(MajorType::ARRAY, 31); +static constexpr uint8_t kInitialByteIndefiniteLengthMap = + EncodeInitialByte(MajorType::MAP, 31); +// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite +// length maps / arrays. +static constexpr uint8_t kStopByte = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); + +// See RFC 7049 Section 2.3, Table 2. +static constexpr uint8_t kEncodedTrue = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 21); +static constexpr uint8_t kEncodedFalse = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 20); +static constexpr uint8_t kEncodedNull = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 22); +static constexpr uint8_t kInitialByteForDouble = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 27); + +// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for +// arbitrary binary data encoded as BYTE_STRING. +static constexpr uint8_t kExpectedConversionToBase64Tag = + EncodeInitialByte(MajorType::TAG, 22); + +// Writes the bytes for |v| to |out|, starting with the most significant byte. +// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html +template <typename T> +void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) { + for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes) + out->push_back(0xff & (v >> (shift_bytes * 8))); +} + +// Extracts sizeof(T) bytes from |in| to extract a value of type T +// (e.g. uint64_t, uint32_t, ...), most significant byte first. +// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html +template <typename T> +T ReadBytesMostSignificantByteFirst(span<uint8_t> in) { + assert(static_cast<std::size_t>(in.size()) >= sizeof(T)); + T result = 0; + for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) + result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8); + return result; +} +} // namespace + +namespace internals { +// Reads the start of a token with definitive size from |bytes|. +// |type| is the major type as specified in RFC 7049 Section 2.1. +// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size +// (e.g. for BYTE_STRING). +// If successful, returns the number of bytes read. Otherwise returns -1. +int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { + if (bytes.empty()) + return -1; + uint8_t initial_byte = bytes[0]; + *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); + + uint8_t additional_information = initial_byte & kAdditionalInformationMask; + if (additional_information < 24) { + // Values 0-23 are encoded directly into the additional info of the + // initial byte. + *value = additional_information; + return 1; + } + if (additional_information == kAdditionalInformation1Byte) { + // Values 24-255 are encoded with one initial byte, followed by the value. + if (bytes.size() < 2) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); + return 2; + } + if (additional_information == kAdditionalInformation2Bytes) { + // Values 256-65535: 1 initial byte + 2 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); + return 3; + } + if (additional_information == kAdditionalInformation4Bytes) { + // 32 bit uint: 1 initial byte + 4 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); + return 5; + } + if (additional_information == kAdditionalInformation8Bytes) { + // 64 bit uint: 1 initial byte + 8 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); + return 9; + } + return -1; +} + +// Writes the start of a token with |type|. The |value| may indicate the size, +// or it may be the payload if the value is an unsigned integer. +void WriteTokenStart(MajorType type, + uint64_t value, + std::vector<uint8_t>* encoded) { + if (value < 24) { + // Values 0-23 are encoded directly into the additional info of the + // initial byte. + encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value)); + return; + } + if (value <= std::numeric_limits<uint8_t>::max()) { + // Values 24-255 are encoded with one initial byte, followed by the value. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte)); + encoded->push_back(value); + return; + } + if (value <= std::numeric_limits<uint16_t>::max()) { + // Values 256-65535: 1 initial byte + 2 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes)); + WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded); + return; + } + if (value <= std::numeric_limits<uint32_t>::max()) { + // 32 bit uint: 1 initial byte + 4 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes)); + WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value), + encoded); + return; + } + // 64 bit uint: 1 initial byte + 8 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes)); + WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded); +} +} // namespace internals + +// ============================================================================= +// Detecting CBOR content +// ============================================================================= + +uint8_t InitialByteForEnvelope() { + return kInitialByteForEnvelope; +} +uint8_t InitialByteFor32BitLengthByteString() { + return kInitialByteFor32BitLengthByteString; +} +bool IsCBORMessage(span<uint8_t> msg) { + return msg.size() >= 6 && msg[0] == InitialByteForEnvelope() && + msg[1] == InitialByteFor32BitLengthByteString(); +} + +// ============================================================================= +// Encoding invidiual CBOR items +// ============================================================================= + +uint8_t EncodeTrue() { + return kEncodedTrue; +} +uint8_t EncodeFalse() { + return kEncodedFalse; +} +uint8_t EncodeNull() { + return kEncodedNull; +} + +uint8_t EncodeIndefiniteLengthArrayStart() { + return kInitialByteIndefiniteLengthArray; +} + +uint8_t EncodeIndefiniteLengthMapStart() { + return kInitialByteIndefiniteLengthMap; +} + +uint8_t EncodeStop() { + return kStopByte; +} + +void EncodeInt32(int32_t value, std::vector<uint8_t>* out) { + if (value >= 0) { + internals::WriteTokenStart(MajorType::UNSIGNED, value, out); + } else { + uint64_t representation = static_cast<uint64_t>(-(value + 1)); + internals::WriteTokenStart(MajorType::NEGATIVE, representation, out); + } +} + +void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) { + uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); + internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); + // When emitting UTF16 characters, we always write the least significant byte + // first; this is because it's the native representation for X86. + // TODO(johannes): Implement a more efficient thing here later, e.g. + // casting *iff* the machine has this byte order. + // The wire format for UTF16 chars will probably remain the same + // (least significant byte first) since this way we can have + // golden files, unittests, etc. that port easily and universally. + // See also: + // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html + for (const uint16_t two_bytes : in) { + out->push_back(two_bytes); + out->push_back(two_bytes >> 8); + } +} + +void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) { + internals::WriteTokenStart(MajorType::STRING, + static_cast<uint64_t>(in.size_bytes()), out); + out->insert(out->end(), in.begin(), in.end()); +} + +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { + for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) + continue; + // If there's at least one non-ASCII char, convert to UTF8. + std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); + for (; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) { + utf8.push_back(latin1[ii]); + } else { + // 0xC0 means it's a UTF8 sequence with 2 bytes. + utf8.push_back((latin1[ii] >> 6) | 0xc0); + utf8.push_back((latin1[ii] | 0x80) & 0xbf); + } + } + EncodeString8(SpanFromVector(utf8), out); + return; + } + EncodeString8(latin1, out); +} + +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { + // If there's at least one non-ASCII char, encode as STRING16 (UTF16). + for (uint16_t ch : utf16) { + if (ch <= 127) + continue; + EncodeString16(utf16, out); + return; + } + // It's all US-ASCII, strip out every second byte and encode as UTF8. + internals::WriteTokenStart(MajorType::STRING, + static_cast<uint64_t>(utf16.size()), out); + out->insert(out->end(), utf16.begin(), utf16.end()); +} + +void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { + out->push_back(kExpectedConversionToBase64Tag); + uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); + internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); + out->insert(out->end(), in.begin(), in.end()); +} + +// A double is encoded with a specific initial byte +// (kInitialByteForDouble) plus the 64 bits of payload for its value. +constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t); + +// An envelope is encoded with a specific initial byte +// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32 +// bit wide length, plus a 32 bit length for that string. +constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t); + +void EncodeDouble(double value, std::vector<uint8_t>* out) { + // The additional_info=27 indicates 64 bits for the double follow. + // See RFC 7049 Section 2.3, Table 1. + out->push_back(kInitialByteForDouble); + union { + double from_double; + uint64_t to_uint64; + } reinterpret; + reinterpret.from_double = value; + WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out); +} + +// ============================================================================= +// cbor::EnvelopeEncoder - for wrapping submessages +// ============================================================================= + +void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { + assert(byte_size_pos_ == 0); + out->push_back(kInitialByteForEnvelope); + out->push_back(kInitialByteFor32BitLengthByteString); + byte_size_pos_ = out->size(); + out->resize(out->size() + sizeof(uint32_t)); +} + +bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { + assert(byte_size_pos_ != 0); + // The byte size is the size of the payload, that is, all the + // bytes that were written past the byte size position itself. + uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t)); + // We store exactly 4 bytes, so at most INT32MAX, with most significant + // byte first. + if (byte_size > std::numeric_limits<uint32_t>::max()) + return false; + for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; + --shift_bytes) { + (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8)); + } + return true; +} + +// ============================================================================= +// cbor::NewCBOREncoder - for encoding from a streaming parser +// ============================================================================= + +namespace { +class CBOREncoder : public StreamingParserHandler { + public: + CBOREncoder(std::vector<uint8_t>* out, Status* status) + : out_(out), status_(status) { + *status_ = Status(); + } + + void HandleMapBegin() override { + envelopes_.emplace_back(); + envelopes_.back().EncodeStart(out_); + out_->push_back(kInitialByteIndefiniteLengthMap); + } + + void HandleMapEnd() override { + out_->push_back(kStopByte); + assert(!envelopes_.empty()); + envelopes_.back().EncodeStop(out_); + envelopes_.pop_back(); + } + + void HandleArrayBegin() override { + envelopes_.emplace_back(); + envelopes_.back().EncodeStart(out_); + out_->push_back(kInitialByteIndefiniteLengthArray); + } + + void HandleArrayEnd() override { + out_->push_back(kStopByte); + assert(!envelopes_.empty()); + envelopes_.back().EncodeStop(out_); + envelopes_.pop_back(); + } + + void HandleString8(span<uint8_t> chars) override { + EncodeString8(chars, out_); + } + + void HandleString16(span<uint16_t> chars) override { + EncodeFromUTF16(chars, out_); + } + + void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); } + + void HandleDouble(double value) override { EncodeDouble(value, out_); } + + void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } + + void HandleBool(bool value) override { + // See RFC 7049 Section 2.3, Table 2. + out_->push_back(value ? kEncodedTrue : kEncodedFalse); + } + + void HandleNull() override { + // See RFC 7049 Section 2.3, Table 2. + out_->push_back(kEncodedNull); + } + + void HandleError(Status error) override { + assert(!error.ok()); + *status_ = error; + out_->clear(); + } + + private: + std::vector<uint8_t>* out_; + std::vector<EnvelopeEncoder> envelopes_; + Status* status_; +}; +} // namespace + +std::unique_ptr<StreamingParserHandler> NewCBOREncoder( + std::vector<uint8_t>* out, + Status* status) { + return std::unique_ptr<StreamingParserHandler>(new CBOREncoder(out, status)); +} + +// ============================================================================= +// cbor::CBORTokenizer - for parsing individual CBOR items +// ============================================================================= + +CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) { + ReadNextToken(/*enter_envelope=*/false); +} +CBORTokenizer::~CBORTokenizer() {} + +CBORTokenTag CBORTokenizer::TokenTag() const { + return token_tag_; +} + +void CBORTokenizer::Next() { + if (token_tag_ == CBORTokenTag::ERROR_VALUE || + token_tag_ == CBORTokenTag::DONE) + return; + ReadNextToken(/*enter_envelope=*/false); +} + +void CBORTokenizer::EnterEnvelope() { + assert(token_tag_ == CBORTokenTag::ENVELOPE); + ReadNextToken(/*enter_envelope=*/true); +} + +Status CBORTokenizer::Status() const { + return status_; +} + +int32_t CBORTokenizer::GetInt32() const { + assert(token_tag_ == CBORTokenTag::INT32); + // The range checks happen in ::ReadNextToken(). + return static_cast<uint32_t>( + token_start_type_ == MajorType::UNSIGNED + ? token_start_internal_value_ + : -static_cast<int64_t>(token_start_internal_value_) - 1); +} + +double CBORTokenizer::GetDouble() const { + assert(token_tag_ == CBORTokenTag::DOUBLE); + union { + uint64_t from_uint64; + double to_double; + } reinterpret; + reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>( + bytes_.subspan(status_.pos + 1)); + return reinterpret.to_double; +} + +span<uint8_t> CBORTokenizer::GetString8() const { + assert(token_tag_ == CBORTokenTag::STRING8); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetString16WireRep() const { + assert(token_tag_ == CBORTokenTag::STRING16); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetBinary() const { + assert(token_tag_ == CBORTokenTag::BINARY); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetEnvelopeContents() const { + assert(token_tag_ == CBORTokenTag::ENVELOPE); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length); +} + +void CBORTokenizer::ReadNextToken(bool enter_envelope) { + if (enter_envelope) { + status_.pos += kEncodedEnvelopeHeaderSize; + } else { + status_.pos = + status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_; + } + status_.error = Error::OK; + if (status_.pos >= bytes_.size()) { + token_tag_ = CBORTokenTag::DONE; + return; + } + switch (bytes_[status_.pos]) { + case kStopByte: + SetToken(CBORTokenTag::STOP, 1); + return; + case kInitialByteIndefiniteLengthMap: + SetToken(CBORTokenTag::MAP_START, 1); + return; + case kInitialByteIndefiniteLengthArray: + SetToken(CBORTokenTag::ARRAY_START, 1); + return; + case kEncodedTrue: + SetToken(CBORTokenTag::TRUE_VALUE, 1); + return; + case kEncodedFalse: + SetToken(CBORTokenTag::FALSE_VALUE, 1); + return; + case kEncodedNull: + SetToken(CBORTokenTag::NULL_VALUE, 1); + return; + case kExpectedConversionToBase64Tag: { // BINARY + int8_t bytes_read = internals::ReadTokenStart( + bytes_.subspan(status_.pos + 1), &token_start_type_, + &token_start_internal_value_); + int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_; + if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING || + status_.pos + token_byte_length > bytes_.size()) { + SetError(Error::CBOR_INVALID_BINARY); + return; + } + SetToken(CBORTokenTag::BINARY, + static_cast<std::ptrdiff_t>(token_byte_length)); + return; + } + case kInitialByteForDouble: { // DOUBLE + if (status_.pos + kEncodedDoubleSize > bytes_.size()) { + SetError(Error::CBOR_INVALID_DOUBLE); + return; + } + SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize); + return; + } + case kInitialByteForEnvelope: { // ENVELOPE + if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + // The envelope must be a byte string with 32 bit length. + if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + // Read the length of the byte string. + token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>( + bytes_.subspan(status_.pos + 2)); + // Make sure the payload is contained within the message. + if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize + + status_.pos > + static_cast<std::size_t>(bytes_.size())) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length); + return; + } + default: { + span<uint8_t> remainder = + bytes_.subspan(status_.pos, bytes_.size() - status_.pos); + assert(!remainder.empty()); + int8_t token_start_length = internals::ReadTokenStart( + remainder, &token_start_type_, &token_start_internal_value_); + bool success = token_start_length != -1; + switch (token_start_type_) { + case MajorType::UNSIGNED: // INT32. + if (!success || std::numeric_limits<int32_t>::max() < + token_start_internal_value_) { + SetError(Error::CBOR_INVALID_INT32); + return; + } + SetToken(CBORTokenTag::INT32, token_start_length); + return; + case MajorType::NEGATIVE: // INT32. + if (!success || + std::numeric_limits<int32_t>::min() > + -static_cast<int64_t>(token_start_internal_value_) - 1) { + SetError(Error::CBOR_INVALID_INT32); + return; + } + SetToken(CBORTokenTag::INT32, token_start_length); + return; + case MajorType::STRING: { // STRING8. + if (!success || remainder.size() < static_cast<int64_t>( + token_start_internal_value_)) { + SetError(Error::CBOR_INVALID_STRING8); + return; + } + auto length = + static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::STRING8, token_start_length + length); + return; + } + case MajorType::BYTE_STRING: { // STRING16. + if (!success || + remainder.size() < + static_cast<int64_t>(token_start_internal_value_) || + // Must be divisible by 2 since UTF16 is 2 bytes per character. + token_start_internal_value_ & 1) { + SetError(Error::CBOR_INVALID_STRING16); + return; + } + auto length = + static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::STRING16, token_start_length + length); + return; + } + case MajorType::ARRAY: + case MajorType::MAP: + case MajorType::TAG: + case MajorType::SIMPLE_VALUE: + SetError(Error::CBOR_UNSUPPORTED_VALUE); + return; + } + } + } +} + +void CBORTokenizer::SetToken(CBORTokenTag token_tag, + std::ptrdiff_t token_byte_length) { + token_tag_ = token_tag; + token_byte_length_ = token_byte_length; +} + +void CBORTokenizer::SetError(Error error) { + token_tag_ = CBORTokenTag::ERROR_VALUE; + status_.error = error; +} + +// ============================================================================= +// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages +// ============================================================================= + +namespace { +// When parsing CBOR, we limit recursion depth for objects and arrays +// to this constant. +static constexpr int kStackLimit = 200; + +// Below are three parsing routines for CBOR, which cover enough +// to roundtrip JSON messages. +bool ParseMap(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); +bool ParseArray(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); +bool ParseValue(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); + +void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) { + std::vector<uint16_t> value; + span<uint8_t> rep = tokenizer->GetString16WireRep(); + for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) + value.push_back((rep[ii + 1] << 8) | rep[ii]); + out->HandleString16(span<uint16_t>(value.data(), value.size())); + tokenizer->Next(); +} + +bool ParseUTF8String(CBORTokenizer* tokenizer, StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); + out->HandleString8(tokenizer->GetString8()); + tokenizer->Next(); + return true; +} + +bool ParseValue(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + if (stack_depth > kStackLimit) { + out->HandleError( + Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos}); + return false; + } + // Skip past the envelope to get to what's inside. + if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE) + tokenizer->EnterEnvelope(); + switch (tokenizer->TokenTag()) { + case CBORTokenTag::ERROR_VALUE: + out->HandleError(tokenizer->Status()); + return false; + case CBORTokenTag::DONE: + out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, + tokenizer->Status().pos}); + return false; + case CBORTokenTag::TRUE_VALUE: + out->HandleBool(true); + tokenizer->Next(); + return true; + case CBORTokenTag::FALSE_VALUE: + out->HandleBool(false); + tokenizer->Next(); + return true; + case CBORTokenTag::NULL_VALUE: + out->HandleNull(); + tokenizer->Next(); + return true; + case CBORTokenTag::INT32: + out->HandleInt32(tokenizer->GetInt32()); + tokenizer->Next(); + return true; + case CBORTokenTag::DOUBLE: + out->HandleDouble(tokenizer->GetDouble()); + tokenizer->Next(); + return true; + case CBORTokenTag::STRING8: + return ParseUTF8String(tokenizer, out); + case CBORTokenTag::STRING16: + ParseUTF16String(tokenizer, out); + return true; + case CBORTokenTag::BINARY: { + out->HandleBinary(tokenizer->GetBinary()); + tokenizer->Next(); + return true; + } + case CBORTokenTag::MAP_START: + return ParseMap(stack_depth + 1, tokenizer, out); + case CBORTokenTag::ARRAY_START: + return ParseArray(stack_depth + 1, tokenizer, out); + default: + out->HandleError( + Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos}); + return false; + } +} + +// |bytes| must start with the indefinite length array byte, so basically, +// ParseArray may only be called after an indefinite length array has been +// detected. +bool ParseArray(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START); + tokenizer->Next(); + out->HandleArrayBegin(); + while (tokenizer->TokenTag() != CBORTokenTag::STOP) { + if (tokenizer->TokenTag() == CBORTokenTag::DONE) { + out->HandleError( + Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos}); + return false; + } + if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer->Status()); + return false; + } + // Parse value. + if (!ParseValue(stack_depth, tokenizer, out)) + return false; + } + out->HandleArrayEnd(); + tokenizer->Next(); + return true; +} + +// |bytes| must start with the indefinite length array byte, so basically, +// ParseArray may only be called after an indefinite length array has been +// detected. +bool ParseMap(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START); + out->HandleMapBegin(); + tokenizer->Next(); + while (tokenizer->TokenTag() != CBORTokenTag::STOP) { + if (tokenizer->TokenTag() == CBORTokenTag::DONE) { + out->HandleError( + Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos}); + return false; + } + if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer->Status()); + return false; + } + // Parse key. + if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { + if (!ParseUTF8String(tokenizer, out)) + return false; + } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { + ParseUTF16String(tokenizer, out); + } else { + out->HandleError( + Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos}); + return false; + } + // Parse value. + if (!ParseValue(stack_depth, tokenizer, out)) + return false; + } + out->HandleMapEnd(); + tokenizer->Next(); + return true; +} +} // namespace + +void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out) { + if (bytes.empty()) { + out->HandleError(Status{Error::CBOR_NO_INPUT, 0}); + return; + } + if (bytes[0] != kInitialByteForEnvelope) { + out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0}); + return; + } + CBORTokenizer tokenizer(bytes); + if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer.Status()); + return; + } + // We checked for the envelope start byte above, so the tokenizer + // must agree here, since it's not an error. + assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE); + tokenizer.EnterEnvelope(); + if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) { + out->HandleError( + Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos}); + return; + } + if (!ParseMap(/*stack_depth=*/1, &tokenizer, out)) + return; + if (tokenizer.TokenTag() == CBORTokenTag::DONE) + return; + if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer.Status()); + return; + } + out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos}); +} +} // namespace cbor + +namespace json { + +// ============================================================================= +// json::NewJSONEncoder - for encoding streaming parser events as JSON +// ============================================================================= + +namespace { +// Prints |value| to |out| with 4 hex digits, most significant chunk first. +void PrintHex(uint16_t value, std::string* out) { + for (int ii = 3; ii >= 0; --ii) { + int four_bits = 0xf & (value >> (4 * ii)); + out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10))); + } +} + +// In the writer below, we maintain a stack of State instances. +// It is just enough to emit the appropriate delimiters and brackets +// in JSON. +enum class Container { + // Used for the top-level, initial state. + NONE, + // Inside a JSON object. + MAP, + // Inside a JSON array. + ARRAY +}; +class State { + public: + explicit State(Container container) : container_(container) {} + void StartElement(std::string* out) { + assert(container_ != Container::NONE || size_ == 0); + if (size_ != 0) { + char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':'; + out->append(1, delim); + } + ++size_; + } + Container container() const { return container_; } + + private: + Container container_ = Container::NONE; + int size_ = 0; +}; + +constexpr char kBase64Table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + +void Base64Encode(const span<uint8_t>& in, std::string* out) { + // The following three cases are based on the tables in the example + // section in https://en.wikipedia.org/wiki/Base64. We process three + // input bytes at a time, emitting 4 output bytes at a time. + std::ptrdiff_t ii = 0; + + // While possible, process three input bytes. + for (; ii + 3 <= in.size(); ii += 3) { + uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2]; + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); + out->push_back(kBase64Table[twentyfour_bits & 0x3f]); + } + if (ii + 2 <= in.size()) { // Process two input bytes. + uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8); + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); + out->push_back('='); // Emit padding. + return; + } + if (ii + 1 <= in.size()) { // Process a single input byte. + uint32_t twentyfour_bits = (in[ii] << 16); + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back('='); // Emit padding. + out->push_back('='); // Emit padding. + } +} + +// Implements a handler for JSON parser events to emit a JSON string. +class JSONEncoder : public StreamingParserHandler { + public: + JSONEncoder(const Platform* platform, std::string* out, Status* status) + : platform_(platform), out_(out), status_(status) { + *status_ = Status(); + state_.emplace(Container::NONE); + } + + void HandleMapBegin() override { + if (!status_->ok()) + return; + assert(!state_.empty()); + state_.top().StartElement(out_); + state_.emplace(Container::MAP); + out_->append("{"); + } + + void HandleMapEnd() override { + if (!status_->ok()) + return; + assert(state_.size() >= 2 && state_.top().container() == Container::MAP); + state_.pop(); + out_->append("}"); + } + + void HandleArrayBegin() override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + state_.emplace(Container::ARRAY); + out_->append("["); + } + + void HandleArrayEnd() override { + if (!status_->ok()) + return; + assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY); + state_.pop(); + out_->append("]"); + } + + void HandleString16(span<uint16_t> chars) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + for (const uint16_t ch : chars) { + if (ch == '"') { + out_->append("\\\""); + } else if (ch == '\\') { + out_->append("\\\\"); + } else if (ch == '\b') { + out_->append("\\b"); + } else if (ch == '\f') { + out_->append("\\f"); + } else if (ch == '\n') { + out_->append("\\n"); + } else if (ch == '\r') { + out_->append("\\r"); + } else if (ch == '\t') { + out_->append("\\t"); + } else if (ch >= 32 && ch <= 126) { + out_->append(1, ch); + } else { + out_->append("\\u"); + PrintHex(ch, out_); + } + } + out_->append("\""); + } + + void HandleString8(span<uint8_t> chars) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) { + uint8_t c = chars[ii]; + if (c == '"') { + out_->append("\\\""); + } else if (c == '\\') { + out_->append("\\\\"); + } else if (c == '\b') { + out_->append("\\b"); + } else if (c == '\f') { + out_->append("\\f"); + } else if (c == '\n') { + out_->append("\\n"); + } else if (c == '\r') { + out_->append("\\r"); + } else if (c == '\t') { + out_->append("\\t"); + } else if (c >= 32 && c <= 126) { + out_->append(1, c); + } else if (c < 32) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(c), out_); + } else { + // Inspect the leading byte to figure out how long the utf8 + // byte sequence is; while doing this initialize |codepoint| + // with the first few bits. + // See table in: https://en.wikipedia.org/wiki/UTF-8 + // byte one is 110x xxxx -> 2 byte utf8 sequence + // byte one is 1110 xxxx -> 3 byte utf8 sequence + // byte one is 1111 0xxx -> 4 byte utf8 sequence + uint32_t codepoint; + int num_bytes_left; + if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence + num_bytes_left = 1; + codepoint = c & 0x1f; + } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence + num_bytes_left = 2; + codepoint = c & 0x0f; + } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence + codepoint = c & 0x07; + num_bytes_left = 3; + } else { + continue; // invalid leading byte + } + + // If we have enough bytes in our input, decode the remaining ones + // belonging to this Unicode character into |codepoint|. + if (ii + num_bytes_left > chars.size()) + continue; + while (num_bytes_left > 0) { + c = chars[++ii]; + --num_bytes_left; + // Check the next byte is a continuation byte, that is 10xx xxxx. + if ((c & 0xc0) != 0x80) + continue; + codepoint = (codepoint << 6) | (c & 0x3f); + } + + // Disallow overlong encodings for ascii characters, as these + // would include " and other characters significant to JSON + // string termination / control. + if (codepoint < 0x7f) + continue; + // Invalid in UTF8, and can't be represented in UTF16 anyway. + if (codepoint > 0x10ffff) + continue; + + // So, now we transcode to UTF16, + // using the math described at https://en.wikipedia.org/wiki/UTF-16, + // for either one or two 16 bit characters. + if (codepoint < 0xffff) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(codepoint), out_); + continue; + } + codepoint -= 0x10000; + // high surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_); + // low surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_); + } + } + out_->append("\""); + } + + void HandleBinary(span<uint8_t> bytes) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + Base64Encode(bytes, out_); + out_->append("\""); + } + + void HandleDouble(double value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + std::unique_ptr<char[]> str_value = platform_->DToStr(value); + + // DToStr may fail to emit a 0 before the decimal dot. E.g. this is + // the case in base::NumberToString in Chromium (which is based on + // dmg_fp). So, much like + // https://cs.chromium.org/chromium/src/base/json/json_writer.cc + // we probe for this and emit the leading 0 anyway if necessary. + const char* chars = str_value.get(); + if (chars[0] == '.') { + out_->append("0"); + } else if (chars[0] == '-' && chars[1] == '.') { + out_->append("-0"); + ++chars; + } + out_->append(chars); + } + + void HandleInt32(int32_t value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append(std::to_string(value)); + } + + void HandleBool(bool value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append(value ? "true" : "false"); + } + + void HandleNull() override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("null"); + } + + void HandleError(Status error) override { + assert(!error.ok()); + *status_ = error; + out_->clear(); + } + + private: + const Platform* platform_; + std::string* out_; + Status* status_; + std::stack<State> state_; +}; +} // namespace + +std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform, + std::string* out, + Status* status) { + return std::unique_ptr<StreamingParserHandler>( + new JSONEncoder(platform, out, status)); +} + +// ============================================================================= +// json::ParseJSON - for receiving streaming parser events for JSON. +// ============================================================================= + +namespace { +const int kStackLimit = 200; + +enum Token { + ObjectBegin, + ObjectEnd, + ArrayBegin, + ArrayEnd, + StringLiteral, + Number, + BoolTrue, + BoolFalse, + NullToken, + ListSeparator, + ObjectPairSeparator, + InvalidToken, + NoInput +}; + +const char* const kNullString = "null"; +const char* const kTrueString = "true"; +const char* const kFalseString = "false"; + +template <typename Char> +class JsonParser { + public: + JsonParser(const Platform* platform, StreamingParserHandler* handler) + : platform_(platform), handler_(handler) {} + + void Parse(const Char* start, std::size_t length) { + start_pos_ = start; + const Char* end = start + length; + const Char* tokenEnd; + ParseValue(start, end, &tokenEnd, 0); + if (tokenEnd != end) { + HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd); + } + } + + private: + bool CharsToDouble(const uint16_t* chars, + std::size_t length, + double* result) { + std::string buffer; + buffer.reserve(length + 1); + for (std::size_t ii = 0; ii < length; ++ii) { + bool is_ascii = !(chars[ii] & ~0x7F); + if (!is_ascii) + return false; + buffer.push_back(static_cast<char>(chars[ii])); + } + return platform_->StrToD(buffer.c_str(), result); + } + + bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) { + std::string buffer(reinterpret_cast<const char*>(chars), length); + return platform_->StrToD(buffer.c_str(), result); + } + + static bool ParseConstToken(const Char* start, + const Char* end, + const Char** token_end, + const char* token) { + // |token| is \0 terminated, it's one of the constants at top of the file. + while (start < end && *token != '\0' && *start++ == *token++) { + } + if (*token != '\0') + return false; + *token_end = start; + return true; + } + + static bool ReadInt(const Char* start, + const Char* end, + const Char** token_end, + bool allow_leading_zeros) { + if (start == end) + return false; + bool has_leading_zero = '0' == *start; + int length = 0; + while (start < end && '0' <= *start && *start <= '9') { + ++start; + ++length; + } + if (!length) + return false; + if (!allow_leading_zeros && length > 1 && has_leading_zero) + return false; + *token_end = start; + return true; + } + + static bool ParseNumberToken(const Char* start, + const Char* end, + const Char** token_end) { + // We just grab the number here. We validate the size in DecodeNumber. + // According to RFC4627, a valid number is: [minus] int [frac] [exp] + if (start == end) + return false; + Char c = *start; + if ('-' == c) + ++start; + + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false)) + return false; + if (start == end) { + *token_end = start; + return true; + } + + // Optional fraction part + c = *start; + if ('.' == c) { + ++start; + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) + return false; + if (start == end) { + *token_end = start; + return true; + } + c = *start; + } + + // Optional exponent part + if ('e' == c || 'E' == c) { + ++start; + if (start == end) + return false; + c = *start; + if ('-' == c || '+' == c) { + ++start; + if (start == end) + return false; + } + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) + return false; + } + + *token_end = start; + return true; + } + + static bool ReadHexDigits(const Char* start, + const Char* end, + const Char** token_end, + int digits) { + if (end - start < digits) + return false; + for (int i = 0; i < digits; ++i) { + Char c = *start++; + if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'))) + return false; + } + *token_end = start; + return true; + } + + static bool ParseStringToken(const Char* start, + const Char* end, + const Char** token_end) { + while (start < end) { + Char c = *start++; + if ('\\' == c) { + if (start == end) + return false; + c = *start++; + // Make sure the escaped char is valid. + switch (c) { + case 'x': + if (!ReadHexDigits(start, end, &start, 2)) + return false; + break; + case 'u': + if (!ReadHexDigits(start, end, &start, 4)) + return false; + break; + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '"': + break; + default: + return false; + } + } else if ('"' == c) { + *token_end = start; + return true; + } + } + return false; + } + + static bool SkipComment(const Char* start, + const Char* end, + const Char** comment_end) { + if (start == end) + return false; + + if (*start != '/' || start + 1 >= end) + return false; + ++start; + + if (*start == '/') { + // Single line comment, read to newline. + for (++start; start < end; ++start) { + if (*start == '\n' || *start == '\r') { + *comment_end = start + 1; + return true; + } + } + *comment_end = end; + // Comment reaches end-of-input, which is fine. + return true; + } + + if (*start == '*') { + Char previous = '\0'; + // Block comment, read until end marker. + for (++start; start < end; previous = *start++) { + if (previous == '*' && *start == '/') { + *comment_end = start + 1; + return true; + } + } + // Block comment must close before end-of-input. + return false; + } + + return false; + } + + static bool IsSpaceOrNewLine(Char c) { + // \v = vertial tab; \f = form feed page break. + return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || + c == '\t'; + } + + static void SkipWhitespaceAndComments(const Char* start, + const Char* end, + const Char** whitespace_end) { + while (start < end) { + if (IsSpaceOrNewLine(*start)) { + ++start; + } else if (*start == '/') { + const Char* comment_end; + if (!SkipComment(start, end, &comment_end)) + break; + start = comment_end; + } else { + break; + } + } + *whitespace_end = start; + } + + static Token ParseToken(const Char* start, + const Char* end, + const Char** tokenStart, + const Char** token_end) { + SkipWhitespaceAndComments(start, end, tokenStart); + start = *tokenStart; + + if (start == end) + return NoInput; + + switch (*start) { + case 'n': + if (ParseConstToken(start, end, token_end, kNullString)) + return NullToken; + break; + case 't': + if (ParseConstToken(start, end, token_end, kTrueString)) + return BoolTrue; + break; + case 'f': + if (ParseConstToken(start, end, token_end, kFalseString)) + return BoolFalse; + break; + case '[': + *token_end = start + 1; + return ArrayBegin; + case ']': + *token_end = start + 1; + return ArrayEnd; + case ',': + *token_end = start + 1; + return ListSeparator; + case '{': + *token_end = start + 1; + return ObjectBegin; + case '}': + *token_end = start + 1; + return ObjectEnd; + case ':': + *token_end = start + 1; + return ObjectPairSeparator; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + if (ParseNumberToken(start, end, token_end)) + return Number; + break; + case '"': + if (ParseStringToken(start + 1, end, token_end)) + return StringLiteral; + break; + } + return InvalidToken; + } + + static int HexToInt(Char c) { + if ('0' <= c && c <= '9') + return c - '0'; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + assert(false); // Unreachable. + return 0; + } + + static bool DecodeString(const Char* start, + const Char* end, + std::vector<uint16_t>* output) { + if (start == end) + return true; + if (start > end) + return false; + output->reserve(end - start); + while (start < end) { + uint16_t c = *start++; + // If the |Char| we're dealing with is really a byte, then + // we have utf8 here, and we need to check for multibyte characters + // and transcode them to utf16 (either one or two utf16 chars). + if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) { + // Inspect the leading byte to figure out how long the utf8 + // byte sequence is; while doing this initialize |codepoint| + // with the first few bits. + // See table in: https://en.wikipedia.org/wiki/UTF-8 + // byte one is 110x xxxx -> 2 byte utf8 sequence + // byte one is 1110 xxxx -> 3 byte utf8 sequence + // byte one is 1111 0xxx -> 4 byte utf8 sequence + uint32_t codepoint; + int num_bytes_left; + if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence + num_bytes_left = 1; + codepoint = c & 0x1f; + } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence + num_bytes_left = 2; + codepoint = c & 0x0f; + } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence + codepoint = c & 0x07; + num_bytes_left = 3; + } else { + return false; // invalid leading byte + } + + // If we have enough bytes in our inpput, decode the remaining ones + // belonging to this Unicode character into |codepoint|. + if (start + num_bytes_left > end) + return false; + while (num_bytes_left > 0) { + c = *start++; + --num_bytes_left; + // Check the next byte is a continuation byte, that is 10xx xxxx. + if ((c & 0xc0) != 0x80) + return false; + codepoint = (codepoint << 6) | (c & 0x3f); + } + + // Disallow overlong encodings for ascii characters, as these + // would include " and other characters significant to JSON + // string termination / control. + if (codepoint < 0x7f) + return false; + // Invalid in UTF8, and can't be represented in UTF16 anyway. + if (codepoint > 0x10ffff) + return false; + + // So, now we transcode to UTF16, + // using the math described at https://en.wikipedia.org/wiki/UTF-16, + // for either one or two 16 bit characters. + if (codepoint < 0xffff) { + output->push_back(codepoint); + continue; + } + codepoint -= 0x10000; + output->push_back((codepoint >> 10) + 0xd800); // high surrogate + output->push_back((codepoint & 0x3ff) + 0xdc00); // low surrogate + continue; + } + if ('\\' != c) { + output->push_back(c); + continue; + } + if (start == end) + return false; + c = *start++; + + if (c == 'x') { + // \x is not supported. + return false; + } + + switch (c) { + case '"': + case '/': + case '\\': + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'u': + c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) + + (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3)); + start += 4; + break; + default: + return false; + } + output->push_back(c); + } + return true; + } + + void ParseValue(const Char* start, + const Char* end, + const Char** value_token_end, + int depth) { + if (depth > kStackLimit) { + HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start); + return; + } + const Char* token_start; + const Char* token_end; + Token token = ParseToken(start, end, &token_start, &token_end); + switch (token) { + case NoInput: + HandleError(Error::JSON_PARSER_NO_INPUT, token_start); + return; + case InvalidToken: + HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start); + return; + case NullToken: + handler_->HandleNull(); + break; + case BoolTrue: + handler_->HandleBool(true); + break; + case BoolFalse: + handler_->HandleBool(false); + break; + case Number: { + double value; + if (!CharsToDouble(token_start, token_end - token_start, &value)) { + HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start); + return; + } + if (value >= std::numeric_limits<int32_t>::min() && + value <= std::numeric_limits<int32_t>::max() && + static_cast<int32_t>(value) == value) + handler_->HandleInt32(static_cast<int32_t>(value)); + else + handler_->HandleDouble(value); + break; + } + case StringLiteral: { + std::vector<uint16_t> value; + bool ok = DecodeString(token_start + 1, token_end - 1, &value); + if (!ok) { + HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); + return; + } + handler_->HandleString16(span<uint16_t>(value.data(), value.size())); + break; + } + case ArrayBegin: { + handler_->HandleArrayBegin(); + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + while (token != ArrayEnd) { + ParseValue(start, end, &token_end, depth + 1); + if (error_) + return; + + // After a list value, we expect a comma or the end of the list. + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ListSeparator) { + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ArrayEnd) { + HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start); + return; + } + } else if (token != ArrayEnd) { + // Unexpected value after list value. Bail out. + HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, + token_start); + return; + } + } + handler_->HandleArrayEnd(); + break; + } + case ObjectBegin: { + handler_->HandleMapBegin(); + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + while (token != ObjectEnd) { + if (token != StringLiteral) { + HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, + token_start); + return; + } + std::vector<uint16_t> key; + if (!DecodeString(token_start + 1, token_end - 1, &key)) { + HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); + return; + } + handler_->HandleString16(span<uint16_t>(key.data(), key.size())); + start = token_end; + + token = ParseToken(start, end, &token_start, &token_end); + if (token != ObjectPairSeparator) { + HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start); + return; + } + start = token_end; + + ParseValue(start, end, &token_end, depth + 1); + if (error_) + return; + start = token_end; + + // After a key/value pair, we expect a comma or the end of the + // object. + token = ParseToken(start, end, &token_start, &token_end); + if (token == ListSeparator) { + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ObjectEnd) { + HandleError(Error::JSON_PARSER_UNEXPECTED_MAP_END, token_start); + return; + } + } else if (token != ObjectEnd) { + // Unexpected value after last object value. Bail out. + HandleError(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, + token_start); + return; + } + } + handler_->HandleMapEnd(); + break; + } + + default: + // We got a token that's not a value. + HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start); + return; + } + + SkipWhitespaceAndComments(token_end, end, value_token_end); + } + + void HandleError(Error error, const Char* pos) { + assert(error != Error::OK); + if (!error_) { + handler_->HandleError(Status{error, pos - start_pos_}); + error_ = true; + } + } + + const Char* start_pos_ = nullptr; + bool error_ = false; + const Platform* platform_; + StreamingParserHandler* handler_; +}; +} // namespace + +void ParseJSON(const Platform* platform, + span<uint8_t> chars, + StreamingParserHandler* handler) { + JsonParser<uint8_t> parser(platform, handler); + parser.Parse(chars.data(), chars.size()); +} + +void ParseJSON(const Platform* platform, + span<uint16_t> chars, + StreamingParserHandler* handler) { + JsonParser<uint16_t> parser(platform, handler); + parser.Parse(chars.data(), chars.size()); +} +} // namespace json +} // namespace inspector_protocol_encoding
diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/encoding/encoding.h similarity index 65% rename from third_party/inspector_protocol/lib/CBOR_h.template rename to third_party/inspector_protocol/encoding/encoding.h index 9d28adb..b958ff4 100644 --- a/third_party/inspector_protocol/lib/CBOR_h.template +++ b/third_party/inspector_protocol/encoding/encoding.h
@@ -1,75 +1,21 @@ -{# This template is generated by gen_cbor_templates.py. #} -// Generated by lib/CBOR_h.template. - // Copyright 2019 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 {{"_".join(config.protocol.namespace)}}_CBOR_h -#define {{"_".join(config.protocol.namespace)}}_CBOR_h +#ifndef INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_ +#define INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_ #include <cstddef> #include <cstdint> #include <memory> +#include <string> #include <vector> -{% for namespace in config.protocol.namespace %} -namespace {{namespace}} { -{% endfor %} +namespace inspector_protocol_encoding { -// ===== encoding/status.h ===== - -// Error codes. -enum class Error { - OK = 0, - // JSON parsing errors - json_parser.{h,cc}. - JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01, - JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02, - JSON_PARSER_NO_INPUT = 0x03, - JSON_PARSER_INVALID_TOKEN = 0x04, - JSON_PARSER_INVALID_NUMBER = 0x05, - JSON_PARSER_INVALID_STRING = 0x06, - JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07, - JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08, - JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09, - JSON_PARSER_COLON_EXPECTED = 0x0a, - JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b, - JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c, - JSON_PARSER_VALUE_EXPECTED = 0x0d, - - CBOR_INVALID_INT32 = 0x0e, - CBOR_INVALID_DOUBLE = 0x0f, - CBOR_INVALID_ENVELOPE = 0x10, - CBOR_INVALID_STRING8 = 0x11, - CBOR_INVALID_STRING16 = 0x12, - CBOR_INVALID_BINARY = 0x13, - CBOR_UNSUPPORTED_VALUE = 0x14, - CBOR_NO_INPUT = 0x15, - CBOR_INVALID_START_BYTE = 0x16, - CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17, - CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18, - CBOR_UNEXPECTED_EOF_IN_MAP = 0x19, - CBOR_INVALID_MAP_KEY = 0x1a, - CBOR_STACK_LIMIT_EXCEEDED = 0x1b, - CBOR_STRING8_MUST_BE_7BIT = 0x1c, - CBOR_TRAILING_JUNK = 0x1d, - CBOR_MAP_START_EXPECTED = 0x1e, -}; - -// A status value with position that can be copied. The default status -// is OK. Usually, error status values should come with a valid position. -struct Status { - static constexpr std::ptrdiff_t npos() { return -1; } - - bool ok() const { return error == Error::OK; } - - Error error = Error::OK; - std::ptrdiff_t pos = npos(); - Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {} - Status() = default; -}; - -// ===== encoding/span.h ===== +// ============================================================================= +// span - sequence of bytes +// ============================================================================= // This template is similar to std::span, which will be included in C++20. Like // std::span it uses ptrdiff_t, which is signed (and thus a bit annoying @@ -107,19 +53,78 @@ index_type size_; }; -// ===== encoding/json_parser_handler.h ===== +template <typename T> +span<T> SpanFromVector(const std::vector<T>& v) { + return span<T>(v.data(), v.size()); +} -// Handler interface for JSON parser events. See also json_parser.h. -class JSONParserHandler { +inline span<uint8_t> SpanFromStdString(const std::string& v) { + return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size()); +} + +// Error codes. +enum class Error { + OK = 0, + // JSON parsing errors - json_parser.{h,cc}. + JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01, + JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02, + JSON_PARSER_NO_INPUT = 0x03, + JSON_PARSER_INVALID_TOKEN = 0x04, + JSON_PARSER_INVALID_NUMBER = 0x05, + JSON_PARSER_INVALID_STRING = 0x06, + JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07, + JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08, + JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09, + JSON_PARSER_COLON_EXPECTED = 0x0a, + JSON_PARSER_UNEXPECTED_MAP_END = 0x0b, + JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c, + JSON_PARSER_VALUE_EXPECTED = 0x0d, + + CBOR_INVALID_INT32 = 0x0e, + CBOR_INVALID_DOUBLE = 0x0f, + CBOR_INVALID_ENVELOPE = 0x10, + CBOR_INVALID_STRING8 = 0x11, + CBOR_INVALID_STRING16 = 0x12, + CBOR_INVALID_BINARY = 0x13, + CBOR_UNSUPPORTED_VALUE = 0x14, + CBOR_NO_INPUT = 0x15, + CBOR_INVALID_START_BYTE = 0x16, + CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17, + CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18, + CBOR_UNEXPECTED_EOF_IN_MAP = 0x19, + CBOR_INVALID_MAP_KEY = 0x1a, + CBOR_STACK_LIMIT_EXCEEDED = 0x1b, + CBOR_STRING8_MUST_BE_7BIT = 0x1c, + CBOR_TRAILING_JUNK = 0x1d, + CBOR_MAP_START_EXPECTED = 0x1e, +}; + +// A status value with position that can be copied. The default status +// is OK. Usually, error status values should come with a valid position. +struct Status { + static constexpr std::ptrdiff_t npos() { return -1; } + + bool ok() const { return error == Error::OK; } + + Error error = Error::OK; + std::ptrdiff_t pos = npos(); + Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {} + Status() = default; +}; + +// Handler interface for parser events emitted by a streaming parser. +// See cbor::NewCBOREncoder, cbor::ParseCBOR, json::NewJSONEncoder, +// json::ParseJSON. +class StreamingParserHandler { public: - virtual ~JSONParserHandler() = default; - virtual void HandleObjectBegin() = 0; - virtual void HandleObjectEnd() = 0; + virtual ~StreamingParserHandler() = default; + virtual void HandleMapBegin() = 0; + virtual void HandleMapEnd() = 0; virtual void HandleArrayBegin() = 0; virtual void HandleArrayEnd() = 0; virtual void HandleString8(span<uint8_t> chars) = 0; virtual void HandleString16(span<uint16_t> chars) = 0; - virtual void HandleBinary(std::vector<uint8_t> bytes) = 0; + virtual void HandleBinary(span<uint8_t> bytes) = 0; virtual void HandleDouble(double value) = 0; virtual void HandleInt32(int32_t value) = 0; virtual void HandleBool(bool value) = 0; @@ -132,97 +137,7 @@ virtual void HandleError(Status error) = 0; }; -// ===== encoding/cbor_internals.h ===== - namespace cbor { -enum class MajorType; -} - -namespace cbor_internals { - -// Reads the start of a token with definitive size from |bytes|. -// |type| is the major type as specified in RFC 7049 Section 2.1. -// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size -// (e.g. for BYTE_STRING). -// If successful, returns the number of bytes read. Otherwise returns -1. -int8_t ReadTokenStart(span<uint8_t> bytes, cbor::MajorType* type, - uint64_t* value); - -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(cbor::MajorType type, uint64_t value, - std::vector<uint8_t>* encoded); -} // namespace cbor_internals - -// ===== encoding/cbor.h ===== - - -namespace cbor { - -// The major types from RFC 7049 Section 2.1. -enum class MajorType { - UNSIGNED = 0, - NEGATIVE = 1, - BYTE_STRING = 2, - STRING = 3, - ARRAY = 4, - MAP = 5, - TAG = 6, - SIMPLE_VALUE = 7 -}; - -// Indicates the number of bits the "initial byte" needs to be shifted to the -// right after applying |kMajorTypeMask| to produce the major type in the -// lowermost bits. -static constexpr uint8_t kMajorTypeBitShift = 5u; -// Mask selecting the low-order 5 bits of the "initial byte", which is where -// the additional information is encoded. -static constexpr uint8_t kAdditionalInformationMask = 0x1f; -// Mask selecting the high-order 3 bits of the "initial byte", which indicates -// the major type of the encoded value. -static constexpr uint8_t kMajorTypeMask = 0xe0; -// Indicates the integer is in the following byte. -static constexpr uint8_t kAdditionalInformation1Byte = 24u; -// Indicates the integer is in the next 2 bytes. -static constexpr uint8_t kAdditionalInformation2Bytes = 25u; -// Indicates the integer is in the next 4 bytes. -static constexpr uint8_t kAdditionalInformation4Bytes = 26u; -// Indicates the integer is in the next 8 bytes. -static constexpr uint8_t kAdditionalInformation8Bytes = 27u; - -// Encodes the initial byte, consisting of the |type| in the first 3 bits -// followed by 5 bits of |additional_info|. -constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { - return (static_cast<uint8_t>(type) << kMajorTypeBitShift) | - (additional_info & kAdditionalInformationMask); -} - -// TAG 24 indicates that what follows is a byte string which is -// encoded in CBOR format. We use this as a wrapper for -// maps and arrays, allowing us to skip them, because the -// byte string carries its size (byte length). -// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 -static constexpr uint8_t kInitialByteForEnvelope = - EncodeInitialByte(MajorType::TAG, 24); -// The initial byte for a byte string with at most 2^32 bytes -// of payload. This is used for envelope encoding, even if -// the byte string is shorter. -static constexpr uint8_t kInitialByteFor32BitLengthByteString = - EncodeInitialByte(MajorType::BYTE_STRING, 26); - -// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional -// info = 31. -static constexpr uint8_t kInitialByteIndefiniteLengthArray = - EncodeInitialByte(MajorType::ARRAY, 31); -static constexpr uint8_t kInitialByteIndefiniteLengthMap = - EncodeInitialByte(MajorType::MAP, 31); -// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite -// length maps / arrays. -static constexpr uint8_t kStopByte = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); - -} // namespace cbor - // The binary encoding for the inspector protocol follows the CBOR specification // (RFC 7049). Additional constraints: // - Only indefinite length maps and arrays are supported. @@ -239,12 +154,38 @@ // as CBOR BYTE_STRING (major type 2). For such strings, the number of // bytes encoded must be even. // - UTF8 strings (major type 3) are supported. -// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not +// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, never // as UTF16 strings. // - Arbitrary byte arrays, in the inspector protocol called 'binary', // are encoded as BYTE_STRING (major type 2), prefixed with a byte // indicating base64 when rendered as JSON. +// ============================================================================= +// Detecting CBOR content +// ============================================================================= + +// The first byte for an envelope, which we use for wrapping dictionaries +// and arrays; and the byte that indicates a byte string with 32 bit length. +// These two bytes start an envelope, and thereby also any CBOR message +// produced or consumed by this protocol. See also |EnvelopeEncoder| below. +uint8_t InitialByteForEnvelope(); +uint8_t InitialByteFor32BitLengthByteString(); + +// Checks whether |msg| is a cbor message. +bool IsCBORMessage(span<uint8_t> msg); + +// ============================================================================= +// Encoding individual CBOR items +// ============================================================================= + +// Some constants for CBOR tokens that only take a single byte on the wire. +uint8_t EncodeTrue(); +uint8_t EncodeFalse(); +uint8_t EncodeNull(); +uint8_t EncodeIndefiniteLengthArrayStart(); +uint8_t EncodeIndefiniteLengthMapStart(); +uint8_t EncodeStop(); + // Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE| // (major type 1) iff < 0. void EncodeInt32(int32_t value, std::vector<uint8_t>* out); @@ -275,13 +216,9 @@ // with additional info = 27, followed by 8 bytes in big endian. void EncodeDouble(double value, std::vector<uint8_t>* out); -// Some constants for CBOR tokens that only take a single byte on the wire. -uint8_t EncodeTrue(); -uint8_t EncodeFalse(); -uint8_t EncodeNull(); -uint8_t EncodeIndefiniteLengthArrayStart(); -uint8_t EncodeIndefiniteLengthMapStart(); -uint8_t EncodeStop(); +// ============================================================================= +// cbor::EnvelopeEncoder - for wrapping submessages +// ============================================================================= // An envelope indicates the byte length of a wrapped item. // We use this for maps and array, which allows the decoder @@ -304,20 +241,23 @@ std::size_t byte_size_pos_ = 0; }; -// This can be used to convert from JSON to CBOR, by passing the -// return value to the routines in json_parser.h. The handler will encode into -// |out|, and iff an error occurs it will set |status| to an error and clear -// |out|. Otherwise, |status.ok()| will be |true|. -std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder( - std::vector<uint8_t>* out, Status* status); +// ============================================================================= +// cbor::NewCBOREncoder - for encoding from a streaming parser +// ============================================================================= -// Parses a CBOR encoded message from |bytes|, sending JSON events to -// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops. -// The client is responsible for discarding the already received information in -// that case. -void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out); +// This can be used to convert to CBOR, by passing the return value to a parser +// that drives it. The handler will encode into |out|, and iff an error occurs +// it will set |status| to an error and clear |out|. Otherwise, |status.ok()| +// will be |true|. +std::unique_ptr<StreamingParserHandler> NewCBOREncoder( + std::vector<uint8_t>* out, + Status* status); -// Tags for the tokens within a CBOR message that CBORStream understands. +// ============================================================================= +// cbor::CBORTokenizer - for parsing individual CBOR items +// ============================================================================= + +// Tags for the tokens within a CBOR message that CBORTokenizer understands. // Note that this is not the same terminology as the CBOR spec (RFC 7049), // but rather, our adaptation. For instance, we lump unsigned and signed // major type into INT32 here (and disallow values outside the int32_t range). @@ -357,6 +297,18 @@ DONE, }; +// The major types from RFC 7049 Section 2.1. +enum class MajorType { + UNSIGNED = 0, + NEGATIVE = 1, + BYTE_STRING = 2, + STRING = 3, + ARRAY = 4, + MAP = 5, + TAG = 6, + SIMPLE_VALUE = 7 +}; + // CBORTokenizer segments a CBOR message, presenting the tokens therein as // numbers, strings, etc. This is not a complete CBOR parser, but makes it much // easier to implement one (e.g. ParseCBOR, above). It can also be used to parse @@ -403,6 +355,9 @@ // To be called only if ::TokenTag() == CBORTokenTag::BINARY. span<uint8_t> GetBinary() const; + // To be called only if ::TokenTag() == CBORTokenTag::ENVELOPE. + span<uint8_t> GetEnvelopeContents() const; + private: void ReadNextToken(bool enter_envelope); void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length); @@ -412,14 +367,70 @@ CBORTokenTag token_tag_; struct Status status_; std::ptrdiff_t token_byte_length_; - cbor::MajorType token_start_type_; + MajorType token_start_type_; uint64_t token_start_internal_value_; }; -void DumpCBOR(span<uint8_t> cbor); +// ============================================================================= +// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages +// ============================================================================= +// Parses a CBOR encoded message from |bytes|, sending events to +// |out|. If an error occurs, sends |out->HandleError|, and parsing stops. +// The client is responsible for discarding the already received information in +// that case. +void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out); -{% for namespace in config.protocol.namespace %} -} // namespace {{namespace}} -{% endfor %} -#endif // !defined({{"_".join(config.protocol.namespace)}}_CBOR_h) +namespace internals { // Exposed only for writing tests. +int8_t ReadTokenStart(span<uint8_t> bytes, + cbor::MajorType* type, + uint64_t* value); + +void WriteTokenStart(cbor::MajorType type, + uint64_t value, + std::vector<uint8_t>* encoded); +} // namespace internals +} // namespace cbor + +namespace json { +// Client code must provide an instance. Implementation should delegate +// to whatever is appropriate. +class Platform { + public: + virtual ~Platform() = default; + // Parses |str| into |result|. Returns false iff there are + // leftover characters or parsing errors. + virtual bool StrToD(const char* str, double* result) const = 0; + + // Prints |value| in a format suitable for JSON. + virtual std::unique_ptr<char[]> DToStr(double value) const = 0; +}; + +// ============================================================================= +// json::NewJSONEncoder - for encoding streaming parser events as JSON +// ============================================================================= + +// Returns a handler object which will write ascii characters to |out|. +// |status->ok()| will be false iff the handler routine HandleError() is called. +// In that case, we'll stop emitting output. +// Except for calling the HandleError routine at any time, the client +// code must call the Handle* methods in an order in which they'd occur +// in valid JSON; otherwise we may crash (the code uses assert). +std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform, + std::string* out, + Status* status); + +// ============================================================================= +// json::ParseJSON - for receiving streaming parser events for JSON +// ============================================================================= + +void ParseJSON(const Platform* platform, + span<uint8_t> chars, + StreamingParserHandler* handler); +void ParseJSON(const Platform* platform, + span<uint16_t> chars, + StreamingParserHandler* handler); +} // namespace json +} // namespace inspector_protocol_encoding + +#endif // INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
diff --git a/third_party/inspector_protocol/encoding/encoding_test.cc b/third_party/inspector_protocol/encoding/encoding_test.cc new file mode 100644 index 0000000..a03c7fc --- /dev/null +++ b/third_party/inspector_protocol/encoding/encoding_test.cc
@@ -0,0 +1,1595 @@ +// Copyright 2018 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 "encoding.h" + +#include <array> +#include <clocale> +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <iomanip> +#include <iostream> +#include <sstream> +#include <string> + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::ElementsAreArray; + +namespace inspector_protocol_encoding { + +std::string UTF16ToUTF8(span<uint16_t> in) { + std::string out; + bool success = base::UTF16ToUTF8( + reinterpret_cast<const base::char16*>(in.data()), in.size(), &out); + CHECK(success); + return out; +} + +std::vector<uint16_t> UTF8ToUTF16(span<uint8_t> in) { + base::string16 tmp; + bool success = base::UTF8ToUTF16(reinterpret_cast<const char*>(in.data()), + in.size(), &tmp); + CHECK(success); + return std::vector<uint16_t>(tmp.begin(), tmp.end()); +} + +class TestPlatform : public json::Platform { + bool StrToD(const char* str, double* result) const override { + // This is not thread-safe + // (see https://en.cppreference.com/w/cpp/locale/setlocale) + // but good enough for a unittest. + const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr); + char* end; + *result = std::strtod(str, &end); + std::setlocale(LC_NUMERIC, saved_locale); + if (errno == ERANGE) { + // errno must be reset, e.g. see the example here: + // https://en.cppreference.com/w/cpp/string/byte/strtof + errno = 0; + return false; + } + return end == str + strlen(str); + } + + std::unique_ptr<char[]> DToStr(double value) const override { + std::stringstream ss; + ss.imbue(std::locale("C")); + ss << value; + std::string str = ss.str(); + std::unique_ptr<char[]> result(new char[str.size() + 1]); + memcpy(result.get(), str.c_str(), str.size() + 1); + return result; + } +}; + +json::Platform* GetTestPlatform() { + static TestPlatform* platform = new TestPlatform; + return platform; +} + +// ============================================================================= +// span - sequence of bytes +// ============================================================================= + +template <typename T> +class SpanTest : public ::testing::Test {}; + +using TestTypes = ::testing::Types<uint8_t, uint16_t>; +TYPED_TEST_SUITE(SpanTest, TestTypes); + +TYPED_TEST(SpanTest, Empty) { + span<TypeParam> empty; + EXPECT_TRUE(empty.empty()); + EXPECT_EQ(0, empty.size()); + EXPECT_EQ(0, empty.size_bytes()); + EXPECT_EQ(empty.begin(), empty.end()); +} + +TYPED_TEST(SpanTest, SingleItem) { + TypeParam single_item = 42; + span<TypeParam> singular(&single_item, 1); + EXPECT_FALSE(singular.empty()); + EXPECT_EQ(1, singular.size()); + EXPECT_EQ(sizeof(TypeParam), static_cast<size_t>(singular.size_bytes())); + EXPECT_EQ(singular.begin() + 1, singular.end()); + EXPECT_EQ(42, singular[0]); +} + +TYPED_TEST(SpanTest, FiveItems) { + std::vector<TypeParam> test_input = {31, 32, 33, 34, 35}; + span<TypeParam> five_items(test_input.data(), 5); + EXPECT_FALSE(five_items.empty()); + EXPECT_EQ(5, five_items.size()); + EXPECT_EQ(sizeof(TypeParam) * 5, + static_cast<size_t>(five_items.size_bytes())); + EXPECT_EQ(five_items.begin() + 5, five_items.end()); + EXPECT_EQ(31, five_items[0]); + EXPECT_EQ(32, five_items[1]); + EXPECT_EQ(33, five_items[2]); + EXPECT_EQ(34, five_items[3]); + EXPECT_EQ(35, five_items[4]); + span<TypeParam> three_items = five_items.subspan(2); + EXPECT_EQ(3, three_items.size()); + EXPECT_EQ(33, three_items[0]); + EXPECT_EQ(34, three_items[1]); + EXPECT_EQ(35, three_items[2]); + span<TypeParam> two_items = five_items.subspan(2, 2); + EXPECT_EQ(2, two_items.size()); + EXPECT_EQ(33, two_items[0]); + EXPECT_EQ(34, two_items[1]); +} + +namespace cbor { + +// ============================================================================= +// Detecting CBOR content +// ============================================================================= + +TEST(IsCBORMessage, SomeSmokeTests) { + std::vector<uint8_t> empty; + EXPECT_FALSE(IsCBORMessage(SpanFromVector(empty))); + std::vector<uint8_t> hello = {'H', 'e', 'l', 'o', ' ', 't', + 'h', 'e', 'r', 'e', '!'}; + EXPECT_FALSE(IsCBORMessage(SpanFromVector(hello))); + std::vector<uint8_t> example = {0xd8, 0x5a, 0, 0, 0, 0}; + EXPECT_TRUE(IsCBORMessage(SpanFromVector(example))); + std::vector<uint8_t> one = {0xd8, 0x5a, 0, 0, 0, 1, 1}; + EXPECT_TRUE(IsCBORMessage(SpanFromVector(one))); +} + +// ============================================================================= +// Encoding individual CBOR items +// cbor::CBORTokenizer - for parsing individual CBOR items +// ============================================================================= + +// +// EncodeInt32 / CBORTokenTag::INT32 +// +TEST(EncodeDecodeInt32Test, Roundtrips23) { + // This roundtrips the int32_t value 23 through the pair of EncodeInt32 / + // CBORTokenizer; this is interesting since 23 is encoded as a single byte. + std::vector<uint8_t> encoded; + EncodeInt32(23, &encoded); + // first three bits: major type = 0; remaining five bits: additional info = + // value 23. + EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}})); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(23, tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeInt32Test, RoundtripsUint8) { + // This roundtrips the int32_t value 42 through the pair of EncodeInt32 / + // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded + // in an extra byte after the initial one. + std::vector<uint8_t> encoded; + EncodeInt32(42, &encoded); + // first three bits: major type = 0; + // remaining five bits: additional info = 24, indicating payload is uint8. + EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}})); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(42, tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeInt32Test, RoundtripsUint16) { + // 500 is encoded as a uint16 after the initial byte. + std::vector<uint8_t> encoded; + EncodeInt32(500, &encoded); + // 1 for initial byte, 2 for uint16. + EXPECT_EQ(static_cast<std::size_t>(3), encoded.size()); + // first three bits: major type = 0; + // remaining five bits: additional info = 25, indicating payload is uint16. + EXPECT_EQ(25, encoded[0]); + EXPECT_EQ(0x01, encoded[1]); + EXPECT_EQ(0xf4, encoded[2]); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(500, tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) { + // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte. + std::vector<uint8_t> encoded; + EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded); + // 1 for initial byte, 4 for the uint32. + // first three bits: major type = 0; + // remaining five bits: additional info = 26, indicating payload is uint32. + EXPECT_THAT( + encoded, + ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}})); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeInt32Test, CantRoundtripUint32) { + // 0xdeadbeef is a value which does not fit below + // std::numerical_limits<int32_t>::max(), so we can't encode + // it with EncodeInt32. However, CBOR does support this, so we + // encode it here manually with the internal routine, just to observe + // that it's considered an invalid int32 by CBORTokenizer. + std::vector<uint8_t> encoded; + internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded); + // 1 for initial byte, 4 for the uint32. + // first three bits: major type = 0; + // remaining five bits: additional info = 26, indicating payload is uint32. + EXPECT_THAT( + encoded, + ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}})); + + // Now try to decode; we treat this as an invalid INT32. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + // 0xdeadbeef is > std::numerical_limits<int32_t>::max(). + EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); + EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error); +} + +TEST(EncodeDecodeInt32Test, DecodeErrorCases) { + struct TestCase { + std::vector<uint8_t> data; + std::string msg; + }; + std::vector<TestCase> tests{ + {TestCase{ + {24}, + "additional info = 24 would require 1 byte of payload (but it's 0)"}, + TestCase{{27, 0xaa, 0xbb, 0xcc}, + "additional info = 27 would require 8 bytes of payload (but " + "it's 3)"}, + TestCase{{29}, "additional info = 29 isn't recognized"}}}; + + for (const TestCase& test : tests) { + SCOPED_TRACE(test.msg); + CBORTokenizer tokenizer(SpanFromVector(test.data)); + EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); + EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error); + } +} + +TEST(EncodeDecodeInt32Test, RoundtripsMinus24) { + // This roundtrips the int32_t value -24 through the pair of EncodeInt32 / + // CBORTokenizer; this is interesting since -24 is encoded as + // a single byte as NEGATIVE, and it tests the specific encoding + // (note how for unsigned the single byte covers values up to 23). + // Additional examples are covered in RoundtripsAdditionalExamples. + std::vector<uint8_t> encoded; + EncodeInt32(-24, &encoded); + // first three bits: major type = 1; remaining five bits: additional info = + // value 23. + EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}})); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(-24, tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) { + std::vector<int32_t> examples = {-1, + -10, + -24, + -25, + -300, + -30000, + -300 * 1000, + -1000 * 1000, + -1000 * 1000 * 1000, + std::numeric_limits<int32_t>::min()}; + for (int32_t example : examples) { + SCOPED_TRACE(std::string("example ") + std::to_string(example)); + std::vector<uint8_t> encoded; + EncodeInt32(example, &encoded); + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); + EXPECT_EQ(example, tokenizer.GetInt32()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); + } +} + +// +// EncodeString16 / CBORTokenTag::STRING16 +// +TEST(EncodeDecodeString16Test, RoundtripsEmpty) { + // This roundtrips the empty utf16 string through the pair of EncodeString16 / + // CBORTokenizer. + std::vector<uint8_t> encoded; + EncodeString16(span<uint16_t>(), &encoded); + EXPECT_EQ(static_cast<std::size_t>(1), encoded.size()); + // first three bits: major type = 2; remaining five bits: additional info = + // size 0. + EXPECT_EQ(2 << 5, encoded[0]); + + // Reverse direction: decode with CBORTokenizer. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); + span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep(); + EXPECT_TRUE(decoded_string16_wirerep.empty()); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +// On the wire, we STRING16 is encoded as little endian (least +// significant byte first). The host may or may not be little endian, +// so this routine follows the advice in +// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html. +std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) { + CHECK_EQ(in.size() & 1, 0); // must be even number of bytes. + std::vector<uint16_t> host_out; + for (std::ptrdiff_t ii = 0; ii < in.size(); ii += 2) + host_out.push_back(in[ii + 1] << 8 | in[ii]); + return host_out; +} + +TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) { + // This roundtrips the hello world message which is given here in utf16 + // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas" + // character, 🌎. + std::array<uint16_t, 10> msg{ + {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}}; + std::vector<uint8_t> encoded; + EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded); + // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in + // the additional info part of the initial byte. Payload is two bytes for each + // UTF16 character. + uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20; + std::array<uint8_t, 21> encoded_expected = { + {initial_byte, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, + ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}; + EXPECT_THAT(encoded, ElementsAreArray(encoded_expected)); + + // Now decode to complete the roundtrip. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); + std::vector<uint16_t> decoded = + String16WireRepToHost(tokenizer.GetString16WireRep()); + EXPECT_THAT(decoded, ElementsAreArray(msg)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); + + // For bonus points, we look at the decoded message in UTF8 as well so we can + // easily see it on the terminal screen. + std::string utf8_decoded = UTF16ToUTF8(SpanFromVector(decoded)); + EXPECT_EQ("Hello, 🌎.", utf8_decoded); +} + +TEST(EncodeDecodeString16Test, Roundtrips500) { + // We roundtrip a message that has 250 16 bit values. Each of these are just + // set to their index. 250 is interesting because the cbor spec uses a + // BYTE_STRING of length 500 for one of their examples of how to encode the + // start of it (section 2.1) so it's easy for us to look at the first three + // bytes closely. + std::vector<uint16_t> two_fifty; + for (uint16_t ii = 0; ii < 250; ++ii) + two_fifty.push_back(ii); + std::vector<uint8_t> encoded; + EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded); + EXPECT_EQ(static_cast<std::size_t>(3 + 250 * 2), encoded.size()); + // Now check the first three bytes: + // Major type: 2 (BYTE_STRING) + // Additional information: 25, indicating size is represented by 2 bytes. + // Bytes 1 and 2 encode 500 (0x01f4). + EXPECT_EQ(2 << 5 | 25, encoded[0]); + EXPECT_EQ(0x01, encoded[1]); + EXPECT_EQ(0xf4, encoded[2]); + + // Now decode to complete the roundtrip. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); + std::vector<uint16_t> decoded = + String16WireRepToHost(tokenizer.GetString16WireRep()); + EXPECT_THAT(decoded, ElementsAreArray(two_fifty)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeString16Test, ErrorCases) { + struct TestCase { + std::vector<uint8_t> data; + std::string msg; + }; + std::vector<TestCase> tests{ + {TestCase{{2 << 5 | 1, 'a'}, + "length must be divisible by 2 (but it's 1)"}, + TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"}}}; + for (const TestCase& test : tests) { + SCOPED_TRACE(test.msg); + CBORTokenizer tokenizer(SpanFromVector(test.data)); + EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag()); + EXPECT_EQ(Error::CBOR_INVALID_STRING16, tokenizer.Status().error); + } +} + +// +// EncodeString8 / CBORTokenTag::STRING8 +// +TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) { + // This roundtrips the hello world message which is given here in utf8 + // characters. 🌎 is a four byte utf8 character. + std::string utf8_msg = "Hello, 🌎."; + std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end()); + std::vector<uint8_t> encoded; + EncodeString8(SpanFromStdString(utf8_msg), &encoded); + // This will be encoded as STRING of length 12, so the 12 is encoded in + // the additional info part of the initial byte. Payload is one byte per + // utf8 byte. + uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12; + std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l', + 'o', ',', ' ', 0xF0, 0x9f, 0x8c, + 0x8e, '.'}}; + EXPECT_THAT(encoded, ElementsAreArray(encoded_expected)); + + // Now decode to complete the roundtrip. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); + std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), + tokenizer.GetString8().end()); + EXPECT_THAT(decoded, ElementsAreArray(msg)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) { + std::vector<std::pair<std::string, std::string>> examples = { + {"Hello, world.", "Hello, world."}, + {"Above: \xDC" + "ber", + "Above: Über"}, + {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF", + "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}}; + + for (const auto& example : examples) { + const std::string& latin1 = example.first; + const std::string& expected_utf8 = example.second; + std::vector<uint8_t> encoded; + EncodeFromLatin1(SpanFromStdString(latin1), &encoded); + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); + std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), + tokenizer.GetString8().end()); + std::string decoded_str(decoded.begin(), decoded.end()); + EXPECT_THAT(decoded_str, testing::Eq(expected_utf8)); + } +} + +TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) { + std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'}; + std::vector<uint8_t> encoded; + EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded); + + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); + std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), + tokenizer.GetString8().end()); + std::string decoded_str(decoded.begin(), decoded.end()); + EXPECT_THAT(decoded_str, testing::Eq("easy")); +} + +TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) { + // Since this message contains non-ASCII characters, the routine is + // forced to encode as UTF16. We see this below by checking that the + // token tag is STRING16. + std::vector<uint16_t> msg = {'H', 'e', 'l', 'l', 'o', + ',', ' ', 0xd83c, 0xdf0e, '.'}; + std::vector<uint8_t> encoded; + EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded); + + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); + std::vector<uint16_t> decoded = + String16WireRepToHost(tokenizer.GetString16WireRep()); + std::string utf8_decoded = UTF16ToUTF8(SpanFromVector(decoded)); + EXPECT_EQ("Hello, 🌎.", utf8_decoded); +} + +// +// EncodeBinary / CBORTokenTag::BINARY +// +TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) { + std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ', + 'w', 'o', 'r', 'l', 'd', '.'}; + std::vector<uint8_t> encoded; + EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded); + // So, on the wire we see that the binary blob travels unmodified. + EXPECT_THAT( + encoded, + ElementsAreArray(std::array<uint8_t, 15>{ + {(6 << 5 | 22), // tag 22 indicating base64 interpretation in JSON + (2 << 5 | 13), // BYTE_STRING (type 2) of length 13 + 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}})); + std::vector<uint8_t> decoded; + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag()); + EXPECT_EQ(0, int(tokenizer.Status().error)); + decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(), + tokenizer.GetBinary().end()); + EXPECT_THAT(decoded, ElementsAreArray(binary)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +// +// EncodeDouble / CBORTokenTag::DOUBLE +// +TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) { + // https://en.wikipedia.org/wiki/Double-precision_floating-point_format + // provides the example of a hex representation 3FD5 5555 5555 5555, which + // approximates 1/3. + + const double kOriginalValue = 1.0 / 3; + std::vector<uint8_t> encoded; + EncodeDouble(kOriginalValue, &encoded); + // first three bits: major type = 7; remaining five bits: additional info = + // value 27. This is followed by 8 bytes of payload (which match Wikipedia). + EXPECT_THAT( + encoded, + ElementsAreArray(std::array<uint8_t, 9>{ + {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}})); + + // Reverse direction: decode and compare with original value. + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag()); + EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); +} + +TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) { + std::vector<double> examples = {0.0, + 1.0, + -1.0, + 3.1415, + std::numeric_limits<double>::min(), + std::numeric_limits<double>::max(), + std::numeric_limits<double>::infinity(), + std::numeric_limits<double>::quiet_NaN()}; + for (double example : examples) { + SCOPED_TRACE(std::string("example ") + std::to_string(example)); + std::vector<uint8_t> encoded; + EncodeDouble(example, &encoded); + CBORTokenizer tokenizer(SpanFromVector(encoded)); + EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag()); + if (std::isnan(example)) + EXPECT_TRUE(std::isnan(tokenizer.GetDouble())); + else + EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example)); + tokenizer.Next(); + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); + } +} + +// ============================================================================= +// cbor::NewCBOREncoder - for encoding from a streaming parser +// ============================================================================= + +void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) { + EncodeString8(SpanFromStdString(key), out); +} +TEST(JSONToCBOREncoderTest, SevenBitStrings) { + // When a string can be represented as 7 bit ASCII, the encoder will use the + // STRING (major Type 3) type, so the actual characters end up as bytes on the + // wire. + std::vector<uint8_t> encoded; + Status status; + std::unique_ptr<StreamingParserHandler> encoder = + NewCBOREncoder(&encoded, &status); + std::vector<uint16_t> utf16 = {'f', 'o', 'o'}; + encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size())); + EXPECT_EQ(Error::OK, status.error); + // Here we assert that indeed, seven bit strings are represented as + // bytes on the wire, "foo" is just "foo". + EXPECT_THAT(encoded, + ElementsAreArray(std::array<uint8_t, 4>{ + {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}})); +} + +TEST(JsonCborRoundtrip, EncodingDecoding) { + // Hits all the cases except binary and error in StreamingParserHandler, first + // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON. + std::string json = + "{" + "\"string\":\"Hello, \\ud83c\\udf0e.\"," + "\"double\":3.1415," + "\"int\":1," + "\"negative int\":-1," + "\"bool\":true," + "\"null\":null," + "\"array\":[1,2,3]" + "}"; + std::vector<uint8_t> encoded; + Status status; + std::unique_ptr<StreamingParserHandler> encoder = + NewCBOREncoder(&encoded, &status); + span<uint8_t> ascii_in = SpanFromStdString(json); + json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get()); + std::vector<uint8_t> expected = { + 0xd8, // envelope + 0x5a, // byte string with 32 bit length + 0, 0, 0, 94, // length is 94 bytes + }; + expected.push_back(0xbf); // indef length map start + EncodeString8(SpanFromStdString("string"), &expected); + // This is followed by the encoded string for "Hello, 🌎." + // So, it's the same bytes that we tested above in + // EncodeDecodeString16Test.RoundtripsHelloWorld. + expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20); + for (uint8_t ch : std::array<uint8_t, 20>{ + {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, + ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}) + expected.push_back(ch); + EncodeString8(SpanFromStdString("double"), &expected); + EncodeDouble(3.1415, &expected); + EncodeString8(SpanFromStdString("int"), &expected); + EncodeInt32(1, &expected); + EncodeString8(SpanFromStdString("negative int"), &expected); + EncodeInt32(-1, &expected); + EncodeString8(SpanFromStdString("bool"), &expected); + expected.push_back(7 << 5 | 21); // RFC 7049 Section 2.3, Table 2: true + EncodeString8(SpanFromStdString("null"), &expected); + expected.push_back(7 << 5 | 22); // RFC 7049 Section 2.3, Table 2: null + EncodeString8(SpanFromStdString("array"), &expected); + expected.push_back(0xd8); // envelope + expected.push_back(0x5a); // byte string with 32 bit length + // the length is 5 bytes (that's up to end indef length array below). + for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}}) + expected.push_back(ch); + expected.push_back(0x9f); // RFC 7049 Section 2.2.1, indef length array start + expected.push_back(1); // Three UNSIGNED values (easy since Major Type 0) + expected.push_back(2); + expected.push_back(3); + expected.push_back(0xff); // End indef length array + expected.push_back(0xff); // End indef length map + EXPECT_TRUE(status.ok()); + EXPECT_THAT(encoded, ElementsAreArray(expected)); + + // And now we roundtrip, decoding the message we just encoded. + std::string decoded; + std::unique_ptr<StreamingParserHandler> json_encoder = + NewJSONEncoder(GetTestPlatform(), &decoded, &status); + ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ(json, decoded); +} + +TEST(JsonCborRoundtrip, MoreRoundtripExamples) { + std::vector<std::string> examples = { + // Tests that after closing a nested objects, additional key/value pairs + // are considered. + "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"}; + for (const std::string& json : examples) { + SCOPED_TRACE(std::string("example: ") + json); + std::vector<uint8_t> encoded; + Status status; + std::unique_ptr<StreamingParserHandler> encoder = + NewCBOREncoder(&encoded, &status); + span<uint8_t> ascii_in = SpanFromStdString(json); + ParseJSON(GetTestPlatform(), ascii_in, encoder.get()); + std::string decoded; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &decoded, &status); + ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ(json, decoded); + } +} + +TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) { + // The StreamingParserHandler::HandleBinary is a special case: The JSON parser + // will never call this method, because JSON does not natively support the + // binary type. So, we can't fully roundtrip. However, the other direction + // works: binary will be rendered in JSON, as a base64 string. So, we make + // calls to the encoder directly here, to construct a message, and one of + // these calls is ::HandleBinary, to which we pass a "binary" string + // containing "Hello, world.". + std::vector<uint8_t> encoded; + Status status; + std::unique_ptr<StreamingParserHandler> encoder = + NewCBOREncoder(&encoded, &status); + encoder->HandleMapBegin(); + // Emit a key. + std::vector<uint16_t> key = {'f', 'o', 'o'}; + encoder->HandleString16(SpanFromVector(key)); + // Emit the binary payload, an arbitrary array of bytes that happens to + // be the ascii message "Hello, world.". + encoder->HandleBinary(SpanFromVector(std::vector<uint8_t>{ + 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'})); + encoder->HandleMapEnd(); + EXPECT_EQ(Error::OK, status.error); + + // Now drive the json writer via the CBOR decoder. + std::string decoded; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &decoded, &status); + ParseCBOR(SpanFromVector(encoded), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ(Status::npos(), status.pos); + // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==". + EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded); +} + +// ============================================================================= +// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages +// ============================================================================= + +TEST(ParseCBORTest, ParseEmptyCBORMessage) { + // An envelope starting with 0xd8, 0x5a, with the byte length + // of 2, containing a map that's empty (0xbf for map + // start, and 0xff for map end). + std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff}; + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ("{}", out); +} + +TEST(ParseCBORTest, ParseCBORHelloWorld) { + const uint8_t kPayloadLen = 27; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen}; + bytes.push_back(0xbf); // start indef length map. + EncodeString8(SpanFromStdString("msg"), &bytes); // key: msg + // Now write the value, the familiar "Hello, 🌎." where the globe is expressed + // as two utf16 chars. + bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20); + for (uint8_t ch : std::array<uint8_t, 20>{ + {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, + ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}) + bytes.push_back(ch); + bytes.push_back(0xff); // stop byte + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out); +} + +TEST(ParseCBORTest, UTF8IsSupportedInKeys) { + const uint8_t kPayloadLen = 11; + std::vector<uint8_t> bytes = {cbor::InitialByteForEnvelope(), + cbor::InitialByteFor32BitLengthByteString(), + 0, + 0, + 0, + kPayloadLen}; + bytes.push_back(cbor::EncodeIndefiniteLengthMapStart()); + // Two UTF16 chars. + EncodeString8(SpanFromStdString("🌎"), &bytes); + // Can be encoded as a single UTF16 char. + EncodeString8(SpanFromStdString("☾"), &bytes); + bytes.push_back(cbor::EncodeStop()); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out); +} + +TEST(ParseCBORTest, NoInputError) { + std::vector<uint8_t> in = {}; + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_NO_INPUT, status.error); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidStartByteError) { + // Here we test that some actual json, which usually starts with {, + // is not considered CBOR. CBOR messages must start with 0x5a, the + // envelope start byte. + std::string json = "{\"msg\": \"Hello, world.\"}"; + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(SpanFromStdString(json), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, UnexpectedEofExpectedValueError) { + constexpr uint8_t kPayloadLen = 5; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + // A key; so value would be next. + EncodeString8(SpanFromStdString("key"), &bytes); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error); + EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, UnexpectedEofInArrayError) { + constexpr uint8_t kPayloadLen = 8; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // The byte for starting a map. + // A key; so value would be next. + EncodeString8(SpanFromStdString("array"), &bytes); + bytes.push_back(0x9f); // byte for indefinite length array start. + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error); + EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, UnexpectedEofInMapError) { + constexpr uint8_t kPayloadLen = 1; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // The byte for starting a map. + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error); + EXPECT_EQ(7, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidMapKeyError) { + constexpr uint8_t kPayloadLen = 2; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, + 0, 0, kPayloadLen, // envelope + 0xbf, // map start + 7 << 5 | 22}; // null (not a valid map key) + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error); + EXPECT_EQ(7, status.pos); + EXPECT_EQ("", out); +} + +std::vector<uint8_t> MakeNestedCBOR(int depth) { + std::vector<uint8_t> bytes; + std::vector<EnvelopeEncoder> envelopes; + for (int ii = 0; ii < depth; ++ii) { + envelopes.emplace_back(); + envelopes.back().EncodeStart(&bytes); + bytes.push_back(0xbf); // indef length map start + EncodeString8(SpanFromStdString("key"), &bytes); + } + EncodeString8(SpanFromStdString("innermost_value"), &bytes); + for (int ii = 0; ii < depth; ++ii) { + bytes.push_back(0xff); // stop byte, finishes map. + envelopes.back().EncodeStop(&bytes); + envelopes.pop_back(); + } + return bytes; +} + +TEST(ParseCBORTest, StackLimitExceededError) { + { // Depth 3: no stack limit exceeded error and is easy to inspect. + std::vector<uint8_t> bytes = MakeNestedCBOR(3); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ(Status::npos(), status.pos); + EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out); + } + { // Depth 200: no stack limit exceeded. + std::vector<uint8_t> bytes = MakeNestedCBOR(200); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ(Status::npos(), status.pos); + } + + // We just want to know the length of one opening map so we can compute + // where the error is encountered. So we look at a small example and find + // the second envelope start. + std::vector<uint8_t> small_example = MakeNestedCBOR(3); + int64_t opening_segment_size = 1; // Start after the first envelope start. + while (opening_segment_size < static_cast<int64_t>(small_example.size()) && + small_example[opening_segment_size] != 0xd8) + opening_segment_size++; + + { // Depth 201: limit exceeded. + std::vector<uint8_t> bytes = MakeNestedCBOR(201); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); + EXPECT_EQ(opening_segment_size * 201, status.pos); + } + { // Depth 220: still limit exceeded, and at the same pos as for 1001 + std::vector<uint8_t> bytes = MakeNestedCBOR(220); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); + EXPECT_EQ(opening_segment_size * 201, status.pos); + } +} + +TEST(ParseCBORTest, UnsupportedValueError) { + constexpr uint8_t kPayloadLen = 6; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + bytes.push_back(6 << 5 | 5); // tags aren't supported yet. + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidString16Error) { + constexpr uint8_t kPayloadLen = 11; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + // a BYTE_STRING of length 5 as value; since we interpret these as string16, + // it's going to be invalid as each character would need two bytes, but + // 5 isn't divisible by 2. + bytes.push_back(2 << 5 | 5); + for (int ii = 0; ii < 5; ++ii) + bytes.push_back(' '); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidString8Error) { + constexpr uint8_t kPayloadLen = 6; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + // a STRING of length 5 as value, but we're at the end of the bytes array + // so it can't be decoded successfully. + bytes.push_back(3 << 5 | 5); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidBinaryError) { + constexpr uint8_t kPayloadLen = 9; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + bytes.push_back(6 << 5 | 22); // base64 hint for JSON; indicates binary + bytes.push_back(2 << 5 | 10); // BYTE_STRING (major type 2) of length 10 + // Just two garbage bytes, not enough for the binary. + bytes.push_back(0x31); + bytes.push_back(0x23); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidDoubleError) { + constexpr uint8_t kPayloadLen = 8; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + bytes.push_back(7 << 5 | 27); // initial byte for double + // Just two garbage bytes, not enough to represent an actual double. + bytes.push_back(0x31); + bytes.push_back(0x23); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, InvalidSignedError) { + constexpr uint8_t kPayloadLen = 14; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + int64_t error_pos = bytes.size(); + // uint64_t max is a perfectly fine value to encode as CBOR unsigned, + // but we don't support this since we only cover the int32_t range. + internals::WriteTokenStart(MajorType::UNSIGNED, + std::numeric_limits<uint64_t>::max(), &bytes); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} + +TEST(ParseCBORTest, TrailingJunk) { + constexpr uint8_t kPayloadLen = 35; + std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope + 0xbf}; // map start + EncodeString8(SpanFromStdString("key"), &bytes); + EncodeString8(SpanFromStdString("value"), &bytes); + bytes.push_back(0xff); // Up to here, it's a perfectly fine msg. + int64_t error_pos = bytes.size(); + EncodeString8(SpanFromStdString("trailing junk"), &bytes); + + internals::WriteTokenStart(MajorType::UNSIGNED, + std::numeric_limits<uint64_t>::max(), &bytes); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> json_writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error); + EXPECT_EQ(error_pos, status.pos); + EXPECT_EQ("", out); +} +} // namespace cbor + +namespace json { + +// ============================================================================= +// json::NewJSONEncoder - for encoding streaming parser events as JSON +// ============================================================================= + +void WriteUTF8AsUTF16(StreamingParserHandler* writer, const std::string& utf8) { + writer->HandleString16(SpanFromVector(UTF8ToUTF16(SpanFromStdString(utf8)))); +} + +TEST(JsonStdStringWriterTest, HelloWorld) { + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleMapBegin(); + WriteUTF8AsUTF16(writer.get(), "msg1"); + WriteUTF8AsUTF16(writer.get(), "Hello, 🌎."); + std::string key = "msg1-as-utf8"; + std::string value = "Hello, 🌎."; + writer->HandleString8(SpanFromStdString(key)); + writer->HandleString8(SpanFromStdString(value)); + WriteUTF8AsUTF16(writer.get(), "msg2"); + WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\""); + WriteUTF8AsUTF16(writer.get(), "nested"); + writer->HandleMapBegin(); + WriteUTF8AsUTF16(writer.get(), "double"); + writer->HandleDouble(3.1415); + WriteUTF8AsUTF16(writer.get(), "int"); + writer->HandleInt32(-42); + WriteUTF8AsUTF16(writer.get(), "bool"); + writer->HandleBool(false); + WriteUTF8AsUTF16(writer.get(), "null"); + writer->HandleNull(); + writer->HandleMapEnd(); + WriteUTF8AsUTF16(writer.get(), "array"); + writer->HandleArrayBegin(); + writer->HandleInt32(1); + writer->HandleInt32(2); + writer->HandleInt32(3); + writer->HandleArrayEnd(); + writer->HandleMapEnd(); + EXPECT_TRUE(status.ok()); + EXPECT_EQ( + "{\"msg1\":\"Hello, \\ud83c\\udf0e.\"," + "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\"," + "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\"," + "\"nested\":{\"double\":3.1415,\"int\":-42," + "\"bool\":false,\"null\":null},\"array\":[1,2,3]}", + out); +} + +TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { + // The encoder emits binary submitted to StreamingParserHandler::HandleBinary + // as base64. The following three examples are taken from + // https://en.wikipedia.org/wiki/Base64. + { + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M', 'a', 'n'}))); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("\"TWFu\"", out); + } + { + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M', 'a'}))); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("\"TWE=\"", out); + } + { + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleBinary(SpanFromVector(std::vector<uint8_t>({'M'}))); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("\"TQ==\"", out); + } + { // "Hello, world.", verified with base64decode.org. + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleBinary(SpanFromVector(std::vector<uint8_t>( + {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}))); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("\"SGVsbG8sIHdvcmxkLg==\"", out); + } +} + +TEST(JsonStdStringWriterTest, HandlesErrors) { + // When an error is sent via HandleError, it saves it in the provided + // status and clears the output. + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(GetTestPlatform(), &out, &status); + writer->HandleMapBegin(); + WriteUTF8AsUTF16(writer.get(), "msg1"); + writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42}); + EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error); + EXPECT_EQ(42, status.pos); + EXPECT_EQ("", out); +} + +// We'd use Gmock but unfortunately it only handles copyable return types. +class MockPlatform : public Platform { + public: + // Not implemented. + bool StrToD(const char* str, double* result) const override { return false; } + + // A map with pre-registered responses for DToSTr. + std::map<double, std::string> dtostr_responses; + + std::unique_ptr<char[]> DToStr(double value) const override { + auto it = dtostr_responses.find(value); + CHECK(it != dtostr_responses.end()); + const std::string& str = it->second; + std::unique_ptr<char[]> response(new char[str.size() + 1]); + memcpy(response.get(), str.c_str(), str.size() + 1); + return response; + } +}; + +TEST(JsonStdStringWriterTest, DoubleToString) { + // This "broken" platform responds without the leading 0 before the + // decimal dot, so it'd be invalid JSON. + MockPlatform platform; + platform.dtostr_responses[.1] = ".1"; + platform.dtostr_responses[-.7] = "-.7"; + + std::string out; + Status status; + std::unique_ptr<StreamingParserHandler> writer = + NewJSONEncoder(&platform, &out, &status); + writer->HandleArrayBegin(); + writer->HandleDouble(.1); + writer->HandleDouble(-.7); + writer->HandleArrayEnd(); + EXPECT_EQ("[0.1,-0.7]", out); +} + +// ============================================================================= +// json::ParseJSON - for receiving streaming parser events for JSON +// ============================================================================= + +class Log : public StreamingParserHandler { + public: + void HandleMapBegin() override { log_ << "map begin\n"; } + + void HandleMapEnd() override { log_ << "map end\n"; } + + void HandleArrayBegin() override { log_ << "array begin\n"; } + + void HandleArrayEnd() override { log_ << "array end\n"; } + + void HandleString8(span<uint8_t> chars) override { + log_ << "string8: " << std::string(chars.begin(), chars.end()) << "\n"; + } + + void HandleString16(span<uint16_t> chars) override { + log_ << "string16: " << UTF16ToUTF8(chars) << "\n"; + } + + void HandleBinary(span<uint8_t> bytes) override { + // JSON doesn't have native support for arbitrary bytes, so our parser will + // never call this. + CHECK(false); + } + + void HandleDouble(double value) override { + log_ << "double: " << value << "\n"; + } + + void HandleInt32(int32_t value) override { log_ << "int: " << value << "\n"; } + + void HandleBool(bool value) override { log_ << "bool: " << value << "\n"; } + + void HandleNull() override { log_ << "null\n"; } + + void HandleError(Status status) override { status_ = status; } + + std::string str() const { return status_.ok() ? log_.str() : ""; } + + Status status() const { return status_; } + + private: + std::ostringstream log_; + Status status_; +}; + +class JsonParserTest : public ::testing::Test { + protected: + Log log_; +}; + +TEST_F(JsonParserTest, SimpleDictionary) { + std::string json = "{\"foo\": 42}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: foo\n" + "int: 42\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, Whitespace) { + std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: msg\n" + "string16: Hello, world.\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, NestedDictionary) { + std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: foo\n" + "map begin\n" + "string16: bar\n" + "map begin\n" + "string16: baz\n" + "int: 1\n" + "map end\n" + "string16: bar2\n" + "int: 2\n" + "map end\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, Doubles) { + std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: foo\n" + "double: 3.1415\n" + "string16: bar\n" + "double: 3.1415\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, Unicode) { + // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16. + std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: msg\n" + "string16: Hello, 🌎.\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, Unicode_ParseUtf16) { + // Globe character. utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E. + // Crescent moon character. utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19. + + // We provide the moon with json escape, but the earth as utf16 input. + // Either way they arrive as utf8 (after decoding in log_.str()). + std::vector<uint16_t> json = + UTF8ToUTF16(SpanFromStdString("{\"space\": \"🌎 \\uD83C\\uDF19.\"}")); + ParseJSON(GetTestPlatform(), SpanFromVector(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: space\n" + "string16: 🌎 🌙.\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, Unicode_ParseUtf8) { + // Used below: + // гласность - example for 2 byte utf8, Russian word "glasnost" + // 屋 - example for 3 byte utf8, Chinese word for "house" + // 🌎 - example for 4 byte utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E. + // 🌙 - example for escapes: utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19. + + // We provide the moon with json escape, but the earth as utf8 input. + // Either way they arrive as utf8 (after decoding in log_.str()). + std::string json = + "{" + "\"escapes\": \"\\uD83C\\uDF19\"," + "\"2 byte\":\"гласность\"," + "\"3 byte\":\"屋\"," + "\"4 byte\":\"🌎\"" + "}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: escapes\n" + "string16: 🌙\n" + "string16: 2 byte\n" + "string16: гласность\n" + "string16: 3 byte\n" + "string16: 屋\n" + "string16: 4 byte\n" + "string16: 🌎\n" + "map end\n", + log_.str()); +} + +TEST_F(JsonParserTest, UnprocessedInputRemainsError) { + // Trailing junk after the valid JSON. + std::string json = "{\"foo\": 3.1415} junk"; + int64_t junk_idx = json.find("junk"); + EXPECT_GT(junk_idx, 0); + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error); + EXPECT_EQ(junk_idx, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +std::string MakeNestedJson(int depth) { + std::string json; + for (int ii = 0; ii < depth; ++ii) + json += "{\"foo\":"; + json += "42"; + for (int ii = 0; ii < depth; ++ii) + json += "}"; + return json; +} + +TEST_F(JsonParserTest, StackLimitExceededError) { + // kStackLimit is 1000 (see json_parser.cc). First let's + // try with a small nested example. + std::string json_3 = MakeNestedJson(3); + ParseJSON(GetTestPlatform(), SpanFromStdString(json_3), &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "map begin\n" + "string16: foo\n" + "map begin\n" + "string16: foo\n" + "map begin\n" + "string16: foo\n" + "int: 42\n" + "map end\n" + "map end\n" + "map end\n", + log_.str()); + + // Now with kStackLimit (200). + log_ = Log(); + std::string json_limit = MakeNestedJson(200); + ParseJSON(GetTestPlatform(), + span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()), + json_limit.size()), + &log_); + EXPECT_TRUE(log_.status().ok()); + // Now with kStackLimit + 1 (1001) - it exceeds in the innermost instance. + log_ = Log(); + std::string exceeded = MakeNestedJson(1001); + ParseJSON(GetTestPlatform(), SpanFromStdString(exceeded), &log_); + EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); + EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 201), + log_.status().pos); + // Now way past the limit. Still, the point of exceeding is 201. + log_ = Log(); + std::string far_out = MakeNestedJson(220); + ParseJSON(GetTestPlatform(), SpanFromStdString(far_out), &log_); + EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); + EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 201), + log_.status().pos); +} + +TEST_F(JsonParserTest, NoInputError) { + std::string json = ""; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error); + EXPECT_EQ(0, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, InvalidTokenError) { + std::string json = "|"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error); + EXPECT_EQ(0, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, InvalidNumberError) { + // Mantissa exceeds max (the constant used here is int64_t max). + std::string json = "1E9223372036854775807"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error); + EXPECT_EQ(0, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, InvalidStringError) { + // \x22 is an unsupported escape sequence + std::string json = "\"foo\\x22\""; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error); + EXPECT_EQ(0, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, UnexpectedArrayEndError) { + std::string json = "[1,2,]"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error); + EXPECT_EQ(5, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) { + std::string json = "[1,2 2"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, + log_.status().error); + EXPECT_EQ(5, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, StringLiteralExpectedError) { + // There's an error because the key bar, a string, is not terminated. + std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error); + EXPECT_EQ(16, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, ColonExpectedError) { + std::string json = "{\"foo\", 42}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error); + EXPECT_EQ(6, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, UnexpectedMapEndError) { + std::string json = "{\"foo\": 42, }"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error); + EXPECT_EQ(12, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, CommaOrMapEndExpectedError) { + // The second separator should be a comma. + std::string json = "{\"foo\": 3.1415: \"bar\": 0}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error); + EXPECT_EQ(14, log_.status().pos); + EXPECT_EQ("", log_.str()); +} + +TEST_F(JsonParserTest, ValueExpectedError) { + std::string json = "}"; + ParseJSON(GetTestPlatform(), SpanFromStdString(json), &log_); + EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error); + EXPECT_EQ(0, log_.status().pos); + EXPECT_EQ("", log_.str()); +} +} // namespace json +} // namespace inspector_protocol_encoding
diff --git a/third_party/inspector_protocol/encoding/json_parser.cc b/third_party/inspector_protocol/encoding/json_parser.cc deleted file mode 100644 index 27a1f23..0000000 --- a/third_party/inspector_protocol/encoding/json_parser.cc +++ /dev/null
@@ -1,588 +0,0 @@ -// Copyright 2018 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 "json_parser.h" - -#include <cassert> -#include <limits> -#include <string> -#include "status.h" - -namespace inspector_protocol { -namespace { -const int kStackLimit = 1000; - -enum Token { - ObjectBegin, - ObjectEnd, - ArrayBegin, - ArrayEnd, - StringLiteral, - Number, - BoolTrue, - BoolFalse, - NullToken, - ListSeparator, - ObjectPairSeparator, - InvalidToken, - NoInput -}; - -const char* const kNullString = "null"; -const char* const kTrueString = "true"; -const char* const kFalseString = "false"; - -template <typename Char> -class JsonParser { - public: - JsonParser(const Platform* platform, JSONParserHandler* handler) - : platform_(platform), handler_(handler) {} - - void Parse(const Char* start, std::size_t length) { - start_pos_ = start; - const Char* end = start + length; - const Char* tokenEnd; - ParseValue(start, end, &tokenEnd, 0); - if (tokenEnd != end) { - HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd); - } - } - - private: - bool CharsToDouble(const uint16_t* chars, - std::size_t length, - double* result) { - std::string buffer; - buffer.reserve(length + 1); - for (std::size_t ii = 0; ii < length; ++ii) { - bool is_ascii = !(chars[ii] & ~0x7F); - if (!is_ascii) return false; - buffer.push_back(static_cast<char>(chars[ii])); - } - return platform_->StrToD(buffer.c_str(), result); - } - - bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) { - std::string buffer(reinterpret_cast<const char*>(chars), length); - return platform_->StrToD(buffer.c_str(), result); - } - - static bool ParseConstToken(const Char* start, const Char* end, - const Char** token_end, const char* token) { - // |token| is \0 terminated, it's one of the constants at top of the file. - while (start < end && *token != '\0' && *start++ == *token++) { - } - if (*token != '\0') return false; - *token_end = start; - return true; - } - - static bool ReadInt(const Char* start, const Char* end, - const Char** token_end, bool allow_leading_zeros) { - if (start == end) return false; - bool has_leading_zero = '0' == *start; - int length = 0; - while (start < end && '0' <= *start && *start <= '9') { - ++start; - ++length; - } - if (!length) return false; - if (!allow_leading_zeros && length > 1 && has_leading_zero) return false; - *token_end = start; - return true; - } - - static bool ParseNumberToken(const Char* start, const Char* end, - const Char** token_end) { - // We just grab the number here. We validate the size in DecodeNumber. - // According to RFC4627, a valid number is: [minus] int [frac] [exp] - if (start == end) return false; - Char c = *start; - if ('-' == c) ++start; - - if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false)) - return false; - if (start == end) { - *token_end = start; - return true; - } - - // Optional fraction part - c = *start; - if ('.' == c) { - ++start; - if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) - return false; - if (start == end) { - *token_end = start; - return true; - } - c = *start; - } - - // Optional exponent part - if ('e' == c || 'E' == c) { - ++start; - if (start == end) return false; - c = *start; - if ('-' == c || '+' == c) { - ++start; - if (start == end) return false; - } - if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) - return false; - } - - *token_end = start; - return true; - } - - static bool ReadHexDigits(const Char* start, const Char* end, - const Char** token_end, int digits) { - if (end - start < digits) return false; - for (int i = 0; i < digits; ++i) { - Char c = *start++; - if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || - ('A' <= c && c <= 'F'))) - return false; - } - *token_end = start; - return true; - } - - static bool ParseStringToken(const Char* start, const Char* end, - const Char** token_end) { - while (start < end) { - Char c = *start++; - if ('\\' == c) { - if (start == end) return false; - c = *start++; - // Make sure the escaped char is valid. - switch (c) { - case 'x': - if (!ReadHexDigits(start, end, &start, 2)) return false; - break; - case 'u': - if (!ReadHexDigits(start, end, &start, 4)) return false; - break; - case '\\': - case '/': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - case '"': - break; - default: - return false; - } - } else if ('"' == c) { - *token_end = start; - return true; - } - } - return false; - } - - static bool SkipComment(const Char* start, const Char* end, - const Char** comment_end) { - if (start == end) return false; - - if (*start != '/' || start + 1 >= end) return false; - ++start; - - if (*start == '/') { - // Single line comment, read to newline. - for (++start; start < end; ++start) { - if (*start == '\n' || *start == '\r') { - *comment_end = start + 1; - return true; - } - } - *comment_end = end; - // Comment reaches end-of-input, which is fine. - return true; - } - - if (*start == '*') { - Char previous = '\0'; - // Block comment, read until end marker. - for (++start; start < end; previous = *start++) { - if (previous == '*' && *start == '/') { - *comment_end = start + 1; - return true; - } - } - // Block comment must close before end-of-input. - return false; - } - - return false; - } - - static bool IsSpaceOrNewLine(Char c) { - // \v = vertial tab; \f = form feed page break. - return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || - c == '\t'; - } - - static void SkipWhitespaceAndComments(const Char* start, const Char* end, - const Char** whitespace_end) { - while (start < end) { - if (IsSpaceOrNewLine(*start)) { - ++start; - } else if (*start == '/') { - const Char* comment_end; - if (!SkipComment(start, end, &comment_end)) break; - start = comment_end; - } else { - break; - } - } - *whitespace_end = start; - } - - static Token ParseToken(const Char* start, const Char* end, - const Char** tokenStart, const Char** token_end) { - SkipWhitespaceAndComments(start, end, tokenStart); - start = *tokenStart; - - if (start == end) return NoInput; - - switch (*start) { - case 'n': - if (ParseConstToken(start, end, token_end, kNullString)) - return NullToken; - break; - case 't': - if (ParseConstToken(start, end, token_end, kTrueString)) - return BoolTrue; - break; - case 'f': - if (ParseConstToken(start, end, token_end, kFalseString)) - return BoolFalse; - break; - case '[': - *token_end = start + 1; - return ArrayBegin; - case ']': - *token_end = start + 1; - return ArrayEnd; - case ',': - *token_end = start + 1; - return ListSeparator; - case '{': - *token_end = start + 1; - return ObjectBegin; - case '}': - *token_end = start + 1; - return ObjectEnd; - case ':': - *token_end = start + 1; - return ObjectPairSeparator; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - if (ParseNumberToken(start, end, token_end)) return Number; - break; - case '"': - if (ParseStringToken(start + 1, end, token_end)) return StringLiteral; - break; - } - return InvalidToken; - } - - static int HexToInt(Char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('A' <= c && c <= 'F') return c - 'A' + 10; - if ('a' <= c && c <= 'f') return c - 'a' + 10; - assert(false); // Unreachable. - return 0; - } - - static bool DecodeString(const Char* start, const Char* end, - std::vector<uint16_t>* output) { - if (start == end) return true; - if (start > end) return false; - output->reserve(end - start); - while (start < end) { - uint16_t c = *start++; - // If the |Char| we're dealing with is really a byte, then - // we have utf8 here, and we need to check for multibyte characters - // and transcode them to utf16 (either one or two utf16 chars). - if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) { - // Inspect the leading byte to figure out how long the utf8 - // byte sequence is; while doing this initialize |codepoint| - // with the first few bits. - // See table in: https://en.wikipedia.org/wiki/UTF-8 - // byte one is 110x xxxx -> 2 byte utf8 sequence - // byte one is 1110 xxxx -> 3 byte utf8 sequence - // byte one is 1111 0xxx -> 4 byte utf8 sequence - uint32_t codepoint; - int num_bytes_left; - if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence - num_bytes_left = 1; - codepoint = c & 0x1f; - } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence - num_bytes_left = 2; - codepoint = c & 0x0f; - } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence - codepoint = c & 0x07; - num_bytes_left = 3; - } else { - return false; // invalid leading byte - } - - // If we have enough bytes in our inpput, decode the remaining ones - // belonging to this Unicode character into |codepoint|. - if (start + num_bytes_left > end) return false; - while (num_bytes_left > 0) { - c = *start++; - --num_bytes_left; - // Check the next byte is a continuation byte, that is 10xx xxxx. - if ((c & 0xc0) != 0x80) return false; - codepoint = (codepoint << 6) | (c & 0x3f); - } - - // Disallow overlong encodings for ascii characters, as these - // would include " and other characters significant to JSON - // string termination / control. - if (codepoint < 0x7f) return false; - // Invalid in UTF8, and can't be represented in UTF16 anyway. - if (codepoint > 0x10ffff) return false; - - // So, now we transcode to UTF16, - // using the math described at https://en.wikipedia.org/wiki/UTF-16, - // for either one or two 16 bit characters. - if (codepoint < 0xffff) { - output->push_back(codepoint); - continue; - } - codepoint -= 0x10000; - output->push_back((codepoint >> 10) + 0xd800); // high surrogate - output->push_back((codepoint & 0x3ff) + 0xdc00); // low surrogate - continue; - } - if ('\\' != c) { - output->push_back(c); - continue; - } - if (start == end) return false; - c = *start++; - - if (c == 'x') { - // \x is not supported. - return false; - } - - switch (c) { - case '"': - case '/': - case '\\': - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case 'u': - c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) + - (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3)); - start += 4; - break; - default: - return false; - } - output->push_back(c); - } - return true; - } - - void ParseValue(const Char* start, const Char* end, - const Char** value_token_end, int depth) { - if (depth > kStackLimit) { - HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start); - return; - } - const Char* token_start; - const Char* token_end; - Token token = ParseToken(start, end, &token_start, &token_end); - switch (token) { - case NoInput: - HandleError(Error::JSON_PARSER_NO_INPUT, token_start); - return; - case InvalidToken: - HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start); - return; - case NullToken: - handler_->HandleNull(); - break; - case BoolTrue: - handler_->HandleBool(true); - break; - case BoolFalse: - handler_->HandleBool(false); - break; - case Number: { - double value; - if (!CharsToDouble(token_start, token_end - token_start, &value)) { - HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start); - return; - } - if (value >= std::numeric_limits<int32_t>::min() && - value <= std::numeric_limits<int32_t>::max() && - static_cast<int32_t>(value) == value) - handler_->HandleInt32(static_cast<int32_t>(value)); - else - handler_->HandleDouble(value); - break; - } - case StringLiteral: { - std::vector<uint16_t> value; - bool ok = DecodeString(token_start + 1, token_end - 1, &value); - if (!ok) { - HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); - return; - } - handler_->HandleString16(span<uint16_t>(value.data(), value.size())); - break; - } - case ArrayBegin: { - handler_->HandleArrayBegin(); - start = token_end; - token = ParseToken(start, end, &token_start, &token_end); - while (token != ArrayEnd) { - ParseValue(start, end, &token_end, depth + 1); - if (error_) return; - - // After a list value, we expect a comma or the end of the list. - start = token_end; - token = ParseToken(start, end, &token_start, &token_end); - if (token == ListSeparator) { - start = token_end; - token = ParseToken(start, end, &token_start, &token_end); - if (token == ArrayEnd) { - HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start); - return; - } - } else if (token != ArrayEnd) { - // Unexpected value after list value. Bail out. - HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, - token_start); - return; - } - } - handler_->HandleArrayEnd(); - break; - } - case ObjectBegin: { - handler_->HandleObjectBegin(); - start = token_end; - token = ParseToken(start, end, &token_start, &token_end); - while (token != ObjectEnd) { - if (token != StringLiteral) { - HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, - token_start); - return; - } - std::vector<uint16_t> key; - if (!DecodeString(token_start + 1, token_end - 1, &key)) { - HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); - return; - } - handler_->HandleString16(span<uint16_t>(key.data(), key.size())); - start = token_end; - - token = ParseToken(start, end, &token_start, &token_end); - if (token != ObjectPairSeparator) { - HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start); - return; - } - start = token_end; - - ParseValue(start, end, &token_end, depth + 1); - if (error_) return; - start = token_end; - - // After a key/value pair, we expect a comma or the end of the - // object. - token = ParseToken(start, end, &token_start, &token_end); - if (token == ListSeparator) { - start = token_end; - token = ParseToken(start, end, &token_start, &token_end); - if (token == ObjectEnd) { - HandleError(Error::JSON_PARSER_UNEXPECTED_OBJECT_END, - token_start); - return; - } - } else if (token != ObjectEnd) { - // Unexpected value after last object value. Bail out. - HandleError(Error::JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED, - token_start); - return; - } - } - handler_->HandleObjectEnd(); - break; - } - - default: - // We got a token that's not a value. - HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start); - return; - } - - SkipWhitespaceAndComments(token_end, end, value_token_end); - } - - void HandleError(Error error, const Char* pos) { - assert(error != Error::OK); - if (!error_) { - handler_->HandleError(Status{error, pos - start_pos_}); - error_ = true; - } - } - - const Char* start_pos_ = nullptr; - bool error_ = false; - const Platform* platform_; - JSONParserHandler* handler_; -}; -} // namespace - -void ParseJSONChars(const Platform* platform, span<uint8_t> chars, - JSONParserHandler* handler) { - JsonParser<uint8_t> parser(platform, handler); - parser.Parse(chars.data(), chars.size()); -} - -void ParseJSONChars(const Platform* platform, span<uint16_t> chars, - JSONParserHandler* handler) { - JsonParser<uint16_t> parser(platform, handler); - parser.Parse(chars.data(), chars.size()); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_parser.h b/third_party/inspector_protocol/encoding/json_parser.h deleted file mode 100644 index 55384be..0000000 --- a/third_party/inspector_protocol/encoding/json_parser.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_ -#define INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_ - -#include <cstdint> -#include <vector> -#include "json_parser_handler.h" -#include "platform.h" -#include "span.h" - -namespace inspector_protocol { -// JSON parsing routines. -void ParseJSONChars(const Platform* platform, span<uint8_t> chars, - JSONParserHandler* handler); -void ParseJSONChars(const Platform* platform, span<uint16_t> chars, - JSONParserHandler* handler); -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_H_
diff --git a/third_party/inspector_protocol/encoding/json_parser_handler.h b/third_party/inspector_protocol/encoding/json_parser_handler.h deleted file mode 100644 index d90b65f7..0000000 --- a/third_party/inspector_protocol/encoding/json_parser_handler.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_ -#define INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_ - -#include <cstdint> -#include <vector> -#include "span.h" -#include "status.h" - -namespace inspector_protocol { -// Handler interface for JSON parser events. See also json_parser.h. -class JSONParserHandler { - public: - virtual ~JSONParserHandler() = default; - virtual void HandleObjectBegin() = 0; - virtual void HandleObjectEnd() = 0; - virtual void HandleArrayBegin() = 0; - virtual void HandleArrayEnd() = 0; - virtual void HandleString8(span<uint8_t> chars) = 0; - virtual void HandleString16(span<uint16_t> chars) = 0; - virtual void HandleBinary(std::vector<uint8_t> bytes) = 0; - virtual void HandleDouble(double value) = 0; - virtual void HandleInt32(int32_t value) = 0; - virtual void HandleBool(bool value) = 0; - virtual void HandleNull() = 0; - - // The parser may send one error even after other events have already - // been received. Client code is reponsible to then discard the - // already processed events. - // |error| must be an eror, as in, |error.is_ok()| can't be true. - virtual void HandleError(Status error) = 0; -}; -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_JSON_PARSER_HANDLER_H_
diff --git a/third_party/inspector_protocol/encoding/json_parser_test.cc b/third_party/inspector_protocol/encoding/json_parser_test.cc deleted file mode 100644 index 2e63129..0000000 --- a/third_party/inspector_protocol/encoding/json_parser_test.cc +++ /dev/null
@@ -1,413 +0,0 @@ -// Copyright 2018 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 "json_parser.h" - -#include <iostream> -#include <sstream> -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "gtest/gtest.h" -#include "linux_dev_platform.h" - -namespace inspector_protocol { -class Log : public JSONParserHandler { - public: - void HandleObjectBegin() override { log_ << "object begin\n"; } - - void HandleObjectEnd() override { log_ << "object end\n"; } - - void HandleArrayBegin() override { log_ << "array begin\n"; } - - void HandleArrayEnd() override { log_ << "array end\n"; } - - void HandleString8(span<uint8_t> chars) override { - base::StringPiece foo(reinterpret_cast<const char*>(chars.data()), - chars.size()); - log_ << "string8: " << foo << "\n"; - } - - void HandleString16(span<uint16_t> chars) override { - base::StringPiece16 foo(reinterpret_cast<const base::char16*>(chars.data()), - chars.size()); - log_ << "string16: " << base::UTF16ToUTF8(foo) << "\n"; - } - - void HandleBinary(std::vector<uint8_t> bytes) override { - // JSON doesn't have native support for arbitrary bytes, so our parser will - // never call this. - assert(false); - } - - void HandleDouble(double value) override { - log_ << "double: " << value << "\n"; - } - - void HandleInt32(int32_t value) override { log_ << "int: " << value << "\n"; } - - void HandleBool(bool value) override { log_ << "bool: " << value << "\n"; } - - void HandleNull() override { log_ << "null\n"; } - - void HandleError(Status status) override { status_ = status; } - - std::string str() const { return status_.ok() ? log_.str() : ""; } - - Status status() const { return status_; } - - private: - std::ostringstream log_; - Status status_; -}; - -class JsonParserTest : public ::testing::Test { - protected: - Log log_; -}; - -TEST_F(JsonParserTest, SimpleDictionary) { - std::string json = "{\"foo\": 42}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: foo\n" - "int: 42\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, Whitespace) { - std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: msg\n" - "string16: Hello, world.\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, NestedDictionary) { - std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: foo\n" - "object begin\n" - "string16: bar\n" - "object begin\n" - "string16: baz\n" - "int: 1\n" - "object end\n" - "string16: bar2\n" - "int: 2\n" - "object end\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, Doubles) { - std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: foo\n" - "double: 3.1415\n" - "string16: bar\n" - "double: 3.1415\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, Unicode) { - // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16. - std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: msg\n" - "string16: Hello, 🌎.\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, Unicode_ParseUtf16) { - // Globe character. utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E. - // Crescent moon character. utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19. - - // We provide the moon with json escape, but the earth as utf16 input. - // Either way they arrive as utf8 (after decoding in log_.str()). - base::string16 json = base::UTF8ToUTF16("{\"space\": \"🌎 \\uD83C\\uDF19.\"}"); - ParseJSONChars(GetLinuxDevPlatform(), - span<uint16_t>(reinterpret_cast<const uint16_t*>(json.data()), - json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: space\n" - "string16: 🌎 🌙.\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, Unicode_ParseUtf8) { - // Used below: - // гласность - example for 2 byte utf8, Russian word "glasnost" - // 屋 - example for 3 byte utf8, Chinese word for "house" - // 🌎 - example for 4 byte utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E. - // 🌙 - example for escapes: utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19. - - // We provide the moon with json escape, but the earth as utf8 input. - // Either way they arrive as utf8 (after decoding in log_.str()). - std::string json = - "{" - "\"escapes\": \"\\uD83C\\uDF19\"," - "\"2 byte\":\"гласность\"," - "\"3 byte\":\"屋\"," - "\"4 byte\":\"🌎\"" - "}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: escapes\n" - "string16: 🌙\n" - "string16: 2 byte\n" - "string16: гласность\n" - "string16: 3 byte\n" - "string16: 屋\n" - "string16: 4 byte\n" - "string16: 🌎\n" - "object end\n", - log_.str()); -} - -TEST_F(JsonParserTest, UnprocessedInputRemainsError) { - // Trailing junk after the valid JSON. - std::string json = "{\"foo\": 3.1415} junk"; - int64_t junk_idx = json.find("junk"); - EXPECT_GT(junk_idx, 0); - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error); - EXPECT_EQ(junk_idx, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -std::string MakeNestedJson(int depth) { - std::string json; - for (int ii = 0; ii < depth; ++ii) json += "{\"foo\":"; - json += "42"; - for (int ii = 0; ii < depth; ++ii) json += "}"; - return json; -} - -TEST_F(JsonParserTest, StackLimitExceededError) { - // kStackLimit is 1000 (see json_parser.cc). First let's - // try with a small nested example. - std::string json_3 = MakeNestedJson(3); - ParseJSONChars(GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json_3.data()), - json_3.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - EXPECT_EQ( - "object begin\n" - "string16: foo\n" - "object begin\n" - "string16: foo\n" - "object begin\n" - "string16: foo\n" - "int: 42\n" - "object end\n" - "object end\n" - "object end\n", - log_.str()); - - // Now with kStackLimit (1000). - log_ = Log(); - std::string json_limit = MakeNestedJson(1000); - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()), - json_limit.size()), - &log_); - EXPECT_TRUE(log_.status().ok()); - // Now with kStackLimit + 1 (1001) - it exceeds in the innermost instance. - log_ = Log(); - std::string exceeded = MakeNestedJson(1001); - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(exceeded.data()), - exceeded.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); - EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001), - log_.status().pos); - // Now way past the limit. Still, the point of exceeding is 1001. - log_ = Log(); - std::string far_out = MakeNestedJson(10000); - ParseJSONChars(GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(far_out.data()), - far_out.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); - EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 1001), - log_.status().pos); -} - -TEST_F(JsonParserTest, NoInputError) { - std::string json = ""; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error); - EXPECT_EQ(0, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, InvalidTokenError) { - std::string json = "|"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error); - EXPECT_EQ(0, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, InvalidNumberError) { - // Mantissa exceeds max (the constant used here is int64_t max). - std::string json = "1E9223372036854775807"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error); - EXPECT_EQ(0, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, InvalidStringError) { - // \x22 is an unsupported escape sequence - std::string json = "\"foo\\x22\""; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error); - EXPECT_EQ(0, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, UnexpectedArrayEndError) { - std::string json = "[1,2,]"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error); - EXPECT_EQ(5, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) { - std::string json = "[1,2 2"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, - log_.status().error); - EXPECT_EQ(5, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, StringLiteralExpectedError) { - // There's an error because the key bar, a string, is not terminated. - std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error); - EXPECT_EQ(16, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, ColonExpectedError) { - std::string json = "{\"foo\", 42}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error); - EXPECT_EQ(6, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, UnexpectedObjectEndError) { - std::string json = "{\"foo\": 42, }"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_OBJECT_END, log_.status().error); - EXPECT_EQ(12, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, CommaOrObjectEndExpectedError) { - // The second separator should be a comma. - std::string json = "{\"foo\": 3.1415: \"bar\": 0}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED, - log_.status().error); - EXPECT_EQ(14, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -TEST_F(JsonParserTest, ValueExpectedError) { - std::string json = "}"; - ParseJSONChars( - GetLinuxDevPlatform(), - span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), - &log_); - EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error); - EXPECT_EQ(0, log_.status().pos); - EXPECT_EQ("", log_.str()); -} - -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer.cc b/third_party/inspector_protocol/encoding/json_std_string_writer.cc deleted file mode 100644 index 1c849cc..0000000 --- a/third_party/inspector_protocol/encoding/json_std_string_writer.cc +++ /dev/null
@@ -1,306 +0,0 @@ -// Copyright 2018 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 "json_std_string_writer.h" -#include <cassert> -#include <stack> - -namespace inspector_protocol { -namespace { -// Prints |value| to |out| with 4 hex digits, most significant chunk first. -void PrintHex(uint16_t value, std::string* out) { - for (int ii = 3; ii >= 0; --ii) { - int four_bits = 0xf & (value >> (4 * ii)); - out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10))); - } -} - -// In the writer below, we maintain a stack of State instances. -// It is just enough to emit the appropriate delimiters and brackets -// in JSON. -enum class Container { - // Used for the top-level, initial state. - NONE, - // Inside a JSON object. - OBJECT, - // Inside a JSON array. - ARRAY -}; -class State { - public: - explicit State(Container container) : container_(container) {} - void StartElement(std::string* out) { - assert(container_ != Container::NONE || size_ == 0); - if (size_ != 0) { - char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':'; - out->append(1, delim); - } - ++size_; - } - Container container() const { return container_; } - - private: - Container container_ = Container::NONE; - int size_ = 0; -}; - -constexpr char kBase64Table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; - -void Base64Encode(const std::vector<uint8_t>& in, std::string* out) { - // The following three cases are based on the tables in the example - // section in https://en.wikipedia.org/wiki/Base64. We process three - // input bytes at a time, emitting 4 output bytes at a time. - std::size_t ii = 0; - - // While possible, process three input bytes. - for (; ii + 3 <= in.size(); ii += 3) { - uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2]; - out->push_back(kBase64Table[(twentyfour_bits >> 18)]); - out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); - out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); - out->push_back(kBase64Table[twentyfour_bits & 0x3f]); - } - if (ii + 2 <= in.size()) { // Process two input bytes. - uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8); - out->push_back(kBase64Table[(twentyfour_bits >> 18)]); - out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); - out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); - out->push_back('='); // Emit padding. - return; - } - if (ii + 1 <= in.size()) { // Process a single input byte. - uint32_t twentyfour_bits = (in[ii] << 16); - out->push_back(kBase64Table[(twentyfour_bits >> 18)]); - out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); - out->push_back('='); // Emit padding. - out->push_back('='); // Emit padding. - } -} - -// Implements a handler for JSON parser events to emit a JSON string. -class Writer : public JSONParserHandler { - public: - Writer(Platform* platform, std::string* out, Status* status) - : platform_(platform), out_(out), status_(status) { - *status_ = Status(); - state_.emplace(Container::NONE); - } - - void HandleObjectBegin() override { - if (!status_->ok()) return; - assert(!state_.empty()); - state_.top().StartElement(out_); - state_.emplace(Container::OBJECT); - out_->append("{"); - } - - void HandleObjectEnd() override { - if (!status_->ok()) return; - assert(state_.size() >= 2 && state_.top().container() == Container::OBJECT); - state_.pop(); - out_->append("}"); - } - - void HandleArrayBegin() override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - state_.emplace(Container::ARRAY); - out_->append("["); - } - - void HandleArrayEnd() override { - if (!status_->ok()) return; - assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY); - state_.pop(); - out_->append("]"); - } - - void HandleString16(span<uint16_t> chars) override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - out_->append("\""); - for (const uint16_t ch : chars) { - if (ch == '"') { - out_->append("\\\""); - } else if (ch == '\\') { - out_->append("\\\\"); - } else if (ch == '\b') { - out_->append("\\b"); - } else if (ch == '\f') { - out_->append("\\f"); - } else if (ch == '\n') { - out_->append("\\n"); - } else if (ch == '\r') { - out_->append("\\r"); - } else if (ch == '\t') { - out_->append("\\t"); - } else if (ch >= 32 && ch <= 126) { - out_->append(1, ch); - } else { - out_->append("\\u"); - PrintHex(ch, out_); - } - } - out_->append("\""); - } - - void HandleString8(span<uint8_t> chars) override { - if (!status_->ok()) - return; - state_.top().StartElement(out_); - out_->append("\""); - for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) { - uint8_t c = chars[ii]; - if (c == '"') { - out_->append("\\\""); - } else if (c == '\\') { - out_->append("\\\\"); - } else if (c == '\b') { - out_->append("\\b"); - } else if (c == '\f') { - out_->append("\\f"); - } else if (c == '\n') { - out_->append("\\n"); - } else if (c == '\r') { - out_->append("\\r"); - } else if (c == '\t') { - out_->append("\\t"); - } else if (c >= 32 && c <= 126) { - out_->append(1, c); - } else if (c < 32) { - out_->append("\\u"); - PrintHex(static_cast<uint16_t>(c), out_); - } else { - // Inspect the leading byte to figure out how long the utf8 - // byte sequence is; while doing this initialize |codepoint| - // with the first few bits. - // See table in: https://en.wikipedia.org/wiki/UTF-8 - // byte one is 110x xxxx -> 2 byte utf8 sequence - // byte one is 1110 xxxx -> 3 byte utf8 sequence - // byte one is 1111 0xxx -> 4 byte utf8 sequence - uint32_t codepoint; - int num_bytes_left; - if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence - num_bytes_left = 1; - codepoint = c & 0x1f; - } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence - num_bytes_left = 2; - codepoint = c & 0x0f; - } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence - codepoint = c & 0x07; - num_bytes_left = 3; - } else { - continue; // invalid leading byte - } - - // If we have enough bytes in our input, decode the remaining ones - // belonging to this Unicode character into |codepoint|. - if (ii + num_bytes_left > chars.size()) - continue; - while (num_bytes_left > 0) { - c = chars[++ii]; - --num_bytes_left; - // Check the next byte is a continuation byte, that is 10xx xxxx. - if ((c & 0xc0) != 0x80) - continue; - codepoint = (codepoint << 6) | (c & 0x3f); - } - - // Disallow overlong encodings for ascii characters, as these - // would include " and other characters significant to JSON - // string termination / control. - if (codepoint < 0x7f) - continue; - // Invalid in UTF8, and can't be represented in UTF16 anyway. - if (codepoint > 0x10ffff) - continue; - - // So, now we transcode to UTF16, - // using the math described at https://en.wikipedia.org/wiki/UTF-16, - // for either one or two 16 bit characters. - if (codepoint < 0xffff) { - out_->append("\\u"); - PrintHex(static_cast<uint16_t>(codepoint), out_); - continue; - } - codepoint -= 0x10000; - // high surrogate - out_->append("\\u"); - PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_); - // low surrogate - out_->append("\\u"); - PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_); - } - } - out_->append("\""); - } - - void HandleBinary(std::vector<uint8_t> bytes) override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - out_->append("\""); - Base64Encode(bytes, out_); - out_->append("\""); - } - - void HandleDouble(double value) override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - std::unique_ptr<char[]> str_value = platform_->DToStr(value); - - // DToStr may fail to emit a 0 before the decimal dot. E.g. this is - // the case in base::NumberToString in Chromium (which is based on - // dmg_fp). So, much like - // https://cs.chromium.org/chromium/src/base/json/json_writer.cc - // we probe for this and emit the leading 0 anyway if necessary. - const char* chars = str_value.get(); - if (chars[0] == '.') { - out_->append("0"); - } else if (chars[0] == '-' && chars[1] == '.') { - out_->append("-0"); - ++chars; - } - out_->append(chars); - } - - void HandleInt32(int32_t value) override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - out_->append(std::to_string(value)); - } - - void HandleBool(bool value) override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - out_->append(value ? "true" : "false"); - } - - void HandleNull() override { - if (!status_->ok()) return; - state_.top().StartElement(out_); - out_->append("null"); - } - - void HandleError(Status error) override { - assert(!error.ok()); - *status_ = error; - out_->clear(); - } - - private: - Platform* platform_; - std::string* out_; - Status* status_; - std::stack<State> state_; -}; -} // namespace - -std::unique_ptr<JSONParserHandler> NewJSONWriter(Platform* platform, - std::string* out, - Status* status) { - return std::unique_ptr<Writer>(new Writer(platform, out, status)); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer.h b/third_party/inspector_protocol/encoding/json_std_string_writer.h deleted file mode 100644 index b2c9b634..0000000 --- a/third_party/inspector_protocol/encoding/json_std_string_writer.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_ -#define INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_ - -#include <memory> -#include <string> -#include "json_parser_handler.h" -#include "platform.h" - -namespace inspector_protocol { -// Returns a handler object which will write ascii characters to |out|. -// |status->ok()| will be false iff the handler routine HandleError() is called. -// In that case, we'll stop emitting output. -// Except for calling the HandleError routine at any time, the client -// code must call the Handle* methods in an order in which they'd occur -// in valid JSON; otherwise we may crash (the code uses assert). -std::unique_ptr<JSONParserHandler> NewJSONWriter(Platform* platform, - std::string* out, - Status* status); -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_JSON_STD_STRING_WRITER_H_
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc b/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc deleted file mode 100644 index 553f8b2..0000000 --- a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc +++ /dev/null
@@ -1,162 +0,0 @@ -// Copyright 2018 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 "json_std_string_writer.h" - -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "gtest/gtest.h" -#include "linux_dev_platform.h" - -namespace inspector_protocol { -std::vector<uint16_t> UTF16String(const std::string& utf8) { - base::string16 string16 = base::UTF8ToUTF16(utf8); - return std::vector<uint16_t>(string16.data(), - string16.data() + string16.size()); -} - -void WriteUTF8AsUTF16(JSONParserHandler* writer, const std::string& utf8) { - std::vector<uint16_t> utf16 = UTF16String(utf8); - writer->HandleString16(span<uint16_t>(utf16.data(), utf16.size())); -} - -TEST(JsonStdStringWriterTest, HelloWorld) { - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleObjectBegin(); - WriteUTF8AsUTF16(writer.get(), "msg1"); - WriteUTF8AsUTF16(writer.get(), "Hello, 🌎."); - std::string key = "msg1-as-utf8"; - std::string value = "Hello, 🌎."; - writer->HandleString8( - span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size())); - writer->HandleString8(span<uint8_t>( - reinterpret_cast<const uint8_t*>(value.data()), value.size())); - WriteUTF8AsUTF16(writer.get(), "msg2"); - WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\""); - WriteUTF8AsUTF16(writer.get(), "nested"); - writer->HandleObjectBegin(); - WriteUTF8AsUTF16(writer.get(), "double"); - writer->HandleDouble(3.1415); - WriteUTF8AsUTF16(writer.get(), "int"); - writer->HandleInt32(-42); - WriteUTF8AsUTF16(writer.get(), "bool"); - writer->HandleBool(false); - WriteUTF8AsUTF16(writer.get(), "null"); - writer->HandleNull(); - writer->HandleObjectEnd(); - WriteUTF8AsUTF16(writer.get(), "array"); - writer->HandleArrayBegin(); - writer->HandleInt32(1); - writer->HandleInt32(2); - writer->HandleInt32(3); - writer->HandleArrayEnd(); - writer->HandleObjectEnd(); - EXPECT_TRUE(status.ok()); - EXPECT_EQ( - "{\"msg1\":\"Hello, \\ud83c\\udf0e.\"," - "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\"," - "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\"," - "\"nested\":{\"double\":3.1415,\"int\":-42," - "\"bool\":false,\"null\":null},\"array\":[1,2,3]}", - out); -} - -TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { - // The encoder emits binary submitted to JSONParserHandler::HandleBinary - // as base64. The following three examples are taken from - // https://en.wikipedia.org/wiki/Base64. - { - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleBinary({'M', 'a', 'n'}); - EXPECT_TRUE(status.ok()); - EXPECT_EQ("\"TWFu\"", out); - } - { - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleBinary({'M', 'a'}); - EXPECT_TRUE(status.ok()); - EXPECT_EQ("\"TWE=\"", out); - } - { - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleBinary({'M'}); - EXPECT_TRUE(status.ok()); - EXPECT_EQ("\"TQ==\"", out); - } - { // "Hello, world.", verified with base64decode.org. - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleBinary( - {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}); - EXPECT_TRUE(status.ok()); - EXPECT_EQ("\"SGVsbG8sIHdvcmxkLg==\"", out); - } -} - -TEST(JsonStdStringWriterTest, HandlesErrors) { - // When an error is sent via HandleError, it saves it in the provided - // status and clears the output. - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - writer->HandleObjectBegin(); - WriteUTF8AsUTF16(writer.get(), "msg1"); - writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42}); - EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error); - EXPECT_EQ(42, status.pos); - EXPECT_EQ("", out); -} - -// We'd use Gmock but unfortunately it only handles copyable return types. -class MockPlatform : public Platform { - public: - // Not implemented. - bool StrToD(const char* str, double* result) const override { return false; } - - // A map with pre-registered responses for DToSTr. - std::map<double, std::string> dtostr_responses; - - std::unique_ptr<char[]> DToStr(double value) const override { - auto it = dtostr_responses.find(value); - assert(it != dtostr_responses.end()); - const std::string& str = it->second; - std::unique_ptr<char[]> response(new char[str.size() + 1]); - memcpy(response.get(), str.c_str(), str.size() + 1); - return response; - } -}; - -TEST(JsonStdStringWriterTest, DoubleToString) { - // This "broken" platform responds without the leading 0 before the - // decimal dot, so it'd be invalid JSON. - MockPlatform platform; - platform.dtostr_responses[.1] = ".1"; - platform.dtostr_responses[-.7] = "-.7"; - - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> writer = - NewJSONWriter(&platform, &out, &status); - writer->HandleArrayBegin(); - writer->HandleDouble(.1); - writer->HandleDouble(-.7); - writer->HandleArrayEnd(); - EXPECT_EQ("[0.1,-0.7]", out); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/linux_dev_platform.cc b/third_party/inspector_protocol/encoding/linux_dev_platform.cc deleted file mode 100644 index 142ca086..0000000 --- a/third_party/inspector_protocol/encoding/linux_dev_platform.cc +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2018 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 "linux_dev_platform.h" - -#include <clocale> -#include <cstdlib> -#include <cstring> -#include <iomanip> -#include <sstream> - -namespace inspector_protocol { -namespace { -class LinuxDevPlatform : public Platform { - bool StrToD(const char* str, double* result) const override { - // This is not thread-safe - // (see https://en.cppreference.com/w/cpp/locale/setlocale) - // but good enough for a unittest. - const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr); - char* end; - *result = std::strtod(str, &end); - std::setlocale(LC_NUMERIC, saved_locale); - if (errno == ERANGE) { - // errno must be reset, e.g. see the example here: - // https://en.cppreference.com/w/cpp/string/byte/strtof - errno = 0; - return false; - } - return end == str + strlen(str); - } - - std::unique_ptr<char[]> DToStr(double value) const override { - std::stringstream ss; - ss.imbue(std::locale("C")); - ss << value; - std::string str = ss.str(); - std::unique_ptr<char[]> result(new char[str.size() + 1]); - memcpy(result.get(), str.c_str(), str.size() + 1); - return result; - } -}; -} // namespace - -Platform* GetLinuxDevPlatform() { - static Platform* deps = new LinuxDevPlatform; - return deps; -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/linux_dev_platform.h b/third_party/inspector_protocol/encoding/linux_dev_platform.h deleted file mode 100644 index cf5dfd5b..0000000 --- a/third_party/inspector_protocol/encoding/linux_dev_platform.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_ -#define INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_ - -#include "platform.h" - -namespace inspector_protocol { -// Returns an instance of the platform implementation that we're using for -// development on Linux. This is intended and appropriate for tests for this -// package, for now. -Platform* GetLinuxDevPlatform(); -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_LINUX_DEV_PLATFORM_H_
diff --git a/third_party/inspector_protocol/encoding/platform.h b/third_party/inspector_protocol/encoding/platform.h deleted file mode 100644 index cfd2d5d..0000000 --- a/third_party/inspector_protocol/encoding/platform.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_ -#define INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_ - -#include <memory> - -namespace inspector_protocol { -// Client code must provide an instance. Implementation should delegate -// to whatever is appropriate. -class Platform { - public: - virtual ~Platform() = default; - // Parses |str| into |result|. Returns false iff there are - // leftover characters or parsing errors. - virtual bool StrToD(const char* str, double* result) const = 0; - - // Prints |value| in a format suitable for JSON. - virtual std::unique_ptr<char[]> DToStr(double value) const = 0; -}; -} // namespace inspector_protocol - -#endif // INSPECTOR_PROTOCOL_ENCODING_PLATFORM_H_
diff --git a/third_party/inspector_protocol/encoding/span.h b/third_party/inspector_protocol/encoding/span.h deleted file mode 100644 index 052062cf..0000000 --- a/third_party/inspector_protocol/encoding/span.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_SPAN_H_ -#define INSPECTOR_PROTOCOL_ENCODING_SPAN_H_ - -#include <cstddef> - -namespace inspector_protocol { -// This template is similar to std::span, which will be included in C++20. Like -// std::span it uses ptrdiff_t, which is signed (and thus a bit annoying -// sometimes when comparing with size_t), but other than this it's much simpler. -template <typename T> -class span { - public: - using index_type = std::ptrdiff_t; - - span() : data_(nullptr), size_(0) {} - span(const T* data, index_type size) : data_(data), size_(size) {} - - const T* data() const { return data_; } - - const T* begin() const { return data_; } - const T* end() const { return data_ + size_; } - - const T& operator[](index_type idx) const { return data_[idx]; } - - span<T> subspan(index_type offset, index_type count) const { - return span(data_ + offset, count); - } - - span<T> subspan(index_type offset) const { - return span(data_ + offset, size_ - offset); - } - - bool empty() const { return size_ == 0; } - - index_type size() const { return size_; } - index_type size_bytes() const { return size_ * sizeof(T); } - - private: - const T* data_; - index_type size_; -}; -} // namespace inspector_protocol -#endif // INSPECTOR_PROTOCOL_ENCODING_SPAN_H_
diff --git a/third_party/inspector_protocol/encoding/span_test.cc b/third_party/inspector_protocol/encoding/span_test.cc deleted file mode 100644 index 48ee76d..0000000 --- a/third_party/inspector_protocol/encoding/span_test.cc +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2018 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 "span.h" - -#include "gtest/gtest.h" - -namespace inspector_protocol { -template <typename T> -class SpanTest : public ::testing::Test {}; - -using TestTypes = ::testing::Types<uint8_t, uint16_t>; -TYPED_TEST_SUITE(SpanTest, TestTypes); - -TYPED_TEST(SpanTest, Empty) { - span<TypeParam> empty; - EXPECT_TRUE(empty.empty()); - EXPECT_EQ(0, empty.size()); - EXPECT_EQ(0, empty.size_bytes()); - EXPECT_EQ(empty.begin(), empty.end()); -} - -TYPED_TEST(SpanTest, SingleItem) { - TypeParam single_item = 42; - span<TypeParam> singular(&single_item, 1); - EXPECT_FALSE(singular.empty()); - EXPECT_EQ(1, singular.size()); - EXPECT_EQ(sizeof(TypeParam), static_cast<size_t>(singular.size_bytes())); - EXPECT_EQ(singular.begin() + 1, singular.end()); - EXPECT_EQ(42, singular[0]); -} - -TYPED_TEST(SpanTest, FiveItems) { - std::vector<TypeParam> test_input = {31, 32, 33, 34, 35}; - span<TypeParam> five_items(test_input.data(), 5); - EXPECT_FALSE(five_items.empty()); - EXPECT_EQ(5, five_items.size()); - EXPECT_EQ(sizeof(TypeParam) * 5, - static_cast<size_t>(five_items.size_bytes())); - EXPECT_EQ(five_items.begin() + 5, five_items.end()); - EXPECT_EQ(31, five_items[0]); - EXPECT_EQ(32, five_items[1]); - EXPECT_EQ(33, five_items[2]); - EXPECT_EQ(34, five_items[3]); - EXPECT_EQ(35, five_items[4]); - span<TypeParam> three_items = five_items.subspan(2); - EXPECT_EQ(3, three_items.size()); - EXPECT_EQ(33, three_items[0]); - EXPECT_EQ(34, three_items[1]); - EXPECT_EQ(35, three_items[2]); - span<TypeParam> two_items = five_items.subspan(2, 2); - EXPECT_EQ(2, two_items.size()); - EXPECT_EQ(33, two_items[0]); - EXPECT_EQ(34, two_items[1]); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/status.h b/third_party/inspector_protocol/encoding/status.h deleted file mode 100644 index ea4a3da..0000000 --- a/third_party/inspector_protocol/encoding/status.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_STATUS_H_ -#define INSPECTOR_PROTOCOL_ENCODING_STATUS_H_ - -#include <cstdint> - -namespace inspector_protocol { -// Error codes. -enum class Error { - OK = 0, - // JSON parsing errors - json_parser.{h,cc}. - JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01, - JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02, - JSON_PARSER_NO_INPUT = 0x03, - JSON_PARSER_INVALID_TOKEN = 0x04, - JSON_PARSER_INVALID_NUMBER = 0x05, - JSON_PARSER_INVALID_STRING = 0x06, - JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07, - JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08, - JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09, - JSON_PARSER_COLON_EXPECTED = 0x0a, - JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b, - JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c, - JSON_PARSER_VALUE_EXPECTED = 0x0d, - - CBOR_INVALID_INT32 = 0x0e, - CBOR_INVALID_DOUBLE = 0x0f, - CBOR_INVALID_ENVELOPE = 0x10, - CBOR_INVALID_STRING8 = 0x11, - CBOR_INVALID_STRING16 = 0x12, - CBOR_INVALID_BINARY = 0x13, - CBOR_UNSUPPORTED_VALUE = 0x14, - CBOR_NO_INPUT = 0x15, - CBOR_INVALID_START_BYTE = 0x16, - CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17, - CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18, - CBOR_UNEXPECTED_EOF_IN_MAP = 0x19, - CBOR_INVALID_MAP_KEY = 0x1a, - CBOR_STACK_LIMIT_EXCEEDED = 0x1b, - CBOR_STRING8_MUST_BE_7BIT = 0x1c, - CBOR_TRAILING_JUNK = 0x1d, - CBOR_MAP_START_EXPECTED = 0x1e, -}; - -// A status value with position that can be copied. The default status -// is OK. Usually, error status values should come with a valid position. -struct Status { - static constexpr std::ptrdiff_t npos() { return -1; } - - bool ok() const { return error == Error::OK; } - - Error error = Error::OK; - std::ptrdiff_t pos = npos(); - Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {} - Status() = default; -}; -} // namespace inspector_protocol -#endif // INSPECTOR_PROTOCOL_ENCODING_STATUS_H_
diff --git a/third_party/inspector_protocol/encoding/str_util.cc b/third_party/inspector_protocol/encoding/str_util.cc deleted file mode 100644 index 1f4be7c..0000000 --- a/third_party/inspector_protocol/encoding/str_util.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2018 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 "str_util.h" - -#include <cstring> - -namespace inspector_protocol { -bool StrEq(span<uint8_t> left, span<uint8_t> right) { - return left.size() == right.size() && - 0 == memcmp(left.data(), right.data(), left.size()); -} - -bool StrEq(span<uint8_t> left, const char* null_terminated_right) { - return static_cast<std::size_t>(left.size()) == - strlen(null_terminated_right) && - 0 == memcmp(left.data(), null_terminated_right, left.size()); -} -} // namespace inspector_protocol
diff --git a/third_party/inspector_protocol/encoding/str_util.h b/third_party/inspector_protocol/encoding/str_util.h deleted file mode 100644 index f377541..0000000 --- a/third_party/inspector_protocol/encoding/str_util.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2018 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 INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_ -#define INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_ - -#include <cstdint> - -#include "span.h" - -namespace inspector_protocol { -// Returns true iff |left| and right have the same contents, byte for byte. -bool StrEq(span<uint8_t> left, span<uint8_t> right); -bool StrEq(span<uint8_t> left, const char* null_terminated_right); -} // namespace inspector_protocol -#endif // INSPECTOR_PROTOCOL_ENCODING_STR_UTIL_H_
diff --git a/third_party/inspector_protocol/inspector_protocol.gni b/third_party/inspector_protocol/inspector_protocol.gni index ecee942..d612fb6a 100644 --- a/third_party/inspector_protocol/inspector_protocol.gni +++ b/third_party/inspector_protocol/inspector_protocol.gni
@@ -33,10 +33,10 @@ invoker.config_file, "$inspector_protocol_dir/lib/base_string_adapter_cc.template", "$inspector_protocol_dir/lib/base_string_adapter_h.template", + "$inspector_protocol_dir/lib/encoding_h.template", + "$inspector_protocol_dir/lib/encoding_cpp.template", "$inspector_protocol_dir/lib/Allocator_h.template", "$inspector_protocol_dir/lib/Array_h.template", - "$inspector_protocol_dir/lib/CBOR_h.template", - "$inspector_protocol_dir/lib/CBOR_cpp.template", "$inspector_protocol_dir/lib/DispatcherBase_cpp.template", "$inspector_protocol_dir/lib/DispatcherBase_h.template", "$inspector_protocol_dir/lib/ErrorSupport_cpp.template",
diff --git a/third_party/inspector_protocol/inspector_protocol.gypi b/third_party/inspector_protocol/inspector_protocol.gypi index 3d0a60e..d614474 100644 --- a/third_party/inspector_protocol/inspector_protocol.gypi +++ b/third_party/inspector_protocol/inspector_protocol.gypi
@@ -5,10 +5,10 @@ { 'variables': { 'inspector_protocol_files': [ + 'lib/encoding_h.template', + 'lib/encoding_cpp.template', 'lib/Allocator_h.template', 'lib/Array_h.template', - 'lib/CBOR_h.template', - 'lib/CBOR_cpp.template', 'lib/DispatcherBase_cpp.template', 'lib/DispatcherBase_h.template', 'lib/ErrorSupport_cpp.template',
diff --git a/third_party/inspector_protocol/lib/CBOR_cpp.template b/third_party/inspector_protocol/lib/CBOR_cpp.template deleted file mode 100644 index d2375b6c..0000000 --- a/third_party/inspector_protocol/lib/CBOR_cpp.template +++ /dev/null
@@ -1,828 +0,0 @@ -{# This template is generated by gen_cbor_templates.py. #} -// Generated by lib/CBOR_cpp.template. - -// Copyright 2019 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 <cassert> -#include <limits> - -{% for namespace in config.protocol.namespace %} -namespace {{namespace}} { -{% endfor %} - -// ===== encoding/cbor.cc ===== - -using namespace cbor; - -namespace { - -// See RFC 7049 Section 2.3, Table 2. -static constexpr uint8_t kEncodedTrue = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 21); -static constexpr uint8_t kEncodedFalse = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 20); -static constexpr uint8_t kEncodedNull = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 22); -static constexpr uint8_t kInitialByteForDouble = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 27); - -} // namespace - -uint8_t EncodeTrue() { return kEncodedTrue; } -uint8_t EncodeFalse() { return kEncodedFalse; } -uint8_t EncodeNull() { return kEncodedNull; } - -uint8_t EncodeIndefiniteLengthArrayStart() { - return kInitialByteIndefiniteLengthArray; -} - -uint8_t EncodeIndefiniteLengthMapStart() { - return kInitialByteIndefiniteLengthMap; -} - -uint8_t EncodeStop() { return kStopByte; } - -namespace { -// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for -// arbitrary binary data encoded as BYTE_STRING. -static constexpr uint8_t kExpectedConversionToBase64Tag = - EncodeInitialByte(MajorType::TAG, 22); - -// When parsing CBOR, we limit recursion depth for objects and arrays -// to this constant. -static constexpr int kStackLimit = 1000; - -// Writes the bytes for |v| to |out|, starting with the most significant byte. -// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html -template <typename T> -void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) { - for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes) - out->push_back(0xff & (v >> (shift_bytes * 8))); -} -} // namespace - -namespace cbor_internals { -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(MajorType type, uint64_t value, - std::vector<uint8_t>* encoded) { - if (value < 24) { - // Values 0-23 are encoded directly into the additional info of the - // initial byte. - encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value)); - return; - } - if (value <= std::numeric_limits<uint8_t>::max()) { - // Values 24-255 are encoded with one initial byte, followed by the value. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte)); - encoded->push_back(value); - return; - } - if (value <= std::numeric_limits<uint16_t>::max()) { - // Values 256-65535: 1 initial byte + 2 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes)); - WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded); - return; - } - if (value <= std::numeric_limits<uint32_t>::max()) { - // 32 bit uint: 1 initial byte + 4 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes)); - WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value), - encoded); - return; - } - // 64 bit uint: 1 initial byte + 8 bytes payload. - encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes)); - WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded); -} -} // namespace cbor_internals - -namespace { -// Extracts sizeof(T) bytes from |in| to extract a value of type T -// (e.g. uint64_t, uint32_t, ...), most significant byte first. -// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html -template <typename T> -T ReadBytesMostSignificantByteFirst(span<uint8_t> in) { - assert(static_cast<std::size_t>(in.size()) >= sizeof(T)); - T result = 0; - for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) - result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8); - return result; -} -} // namespace - -namespace cbor_internals { -int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { - if (bytes.empty()) return -1; - uint8_t initial_byte = bytes[0]; - *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); - - uint8_t additional_information = initial_byte & kAdditionalInformationMask; - if (additional_information < 24) { - // Values 0-23 are encoded directly into the additional info of the - // initial byte. - *value = additional_information; - return 1; - } - if (additional_information == kAdditionalInformation1Byte) { - // Values 24-255 are encoded with one initial byte, followed by the value. - if (bytes.size() < 2) return -1; - *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); - return 2; - } - if (additional_information == kAdditionalInformation2Bytes) { - // Values 256-65535: 1 initial byte + 2 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); - return 3; - } - if (additional_information == kAdditionalInformation4Bytes) { - // 32 bit uint: 1 initial byte + 4 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); - return 5; - } - if (additional_information == kAdditionalInformation8Bytes) { - // 64 bit uint: 1 initial byte + 8 bytes payload. - if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t)) - return -1; - *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); - return 9; - } - return -1; -} -} // namespace cbor_internals - -using cbor_internals::WriteTokenStart; -using cbor_internals::ReadTokenStart; - -void EncodeInt32(int32_t value, std::vector<uint8_t>* out) { - if (value >= 0) { - WriteTokenStart(MajorType::UNSIGNED, value, out); - } else { - uint64_t representation = static_cast<uint64_t>(-(value + 1)); - WriteTokenStart(MajorType::NEGATIVE, representation, out); - } -} - -void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) { - uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); - WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); - // When emitting UTF16 characters, we always write the least significant byte - // first; this is because it's the native representation for X86. - // TODO(johannes): Implement a more efficient thing here later, e.g. - // casting *iff* the machine has this byte order. - // The wire format for UTF16 chars will probably remain the same - // (least significant byte first) since this way we can have - // golden files, unittests, etc. that port easily and universally. - // See also: - // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html - for (const uint16_t two_bytes : in) { - out->push_back(two_bytes); - out->push_back(two_bytes >> 8); - } -} - -void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) { - WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(in.size_bytes()), - out); - out->insert(out->end(), in.begin(), in.end()); -} - -void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { - for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { - if (latin1[ii] <= 127) continue; - // If there's at least one non-ASCII char, convert to UTF8. - std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); - for (; ii < latin1.size(); ++ii) { - if (latin1[ii] <= 127) { - utf8.push_back(latin1[ii]); - } else { - // 0xC0 means it's a UTF8 sequence with 2 bytes. - utf8.push_back((latin1[ii] >> 6) | 0xc0); - utf8.push_back((latin1[ii] | 0x80) & 0xbf); - } - } - EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out); - return; - } - EncodeString8(latin1, out); -} - -void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { - // If there's at least one non-ASCII char, encode as STRING16 (UTF16). - for (uint16_t ch : utf16) { - if (ch <= 127) continue; - EncodeString16(utf16, out); - return; - } - // It's all US-ASCII, strip out every second byte and encode as UTF8. - WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out); - out->insert(out->end(), utf16.begin(), utf16.end()); -} - -void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { - out->push_back(kExpectedConversionToBase64Tag); - uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); - WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); - out->insert(out->end(), in.begin(), in.end()); -} - -// A double is encoded with a specific initial byte -// (kInitialByteForDouble) plus the 64 bits of payload for its value. -constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t); - -// An envelope is encoded with a specific initial byte -// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32 -// bit wide length, plus a 32 bit length for that string. -constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t); - -void EncodeDouble(double value, std::vector<uint8_t>* out) { - // The additional_info=27 indicates 64 bits for the double follow. - // See RFC 7049 Section 2.3, Table 1. - out->push_back(kInitialByteForDouble); - union { - double from_double; - uint64_t to_uint64; - } reinterpret; - reinterpret.from_double = value; - WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out); -} - -void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { - assert(byte_size_pos_ == 0); - out->push_back(kInitialByteForEnvelope); - out->push_back(kInitialByteFor32BitLengthByteString); - byte_size_pos_ = out->size(); - out->resize(out->size() + sizeof(uint32_t)); -} - -bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { - assert(byte_size_pos_ != 0); - // The byte size is the size of the payload, that is, all the - // bytes that were written past the byte size position itself. - uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t)); - // We store exactly 4 bytes, so at most INT32MAX, with most significant - // byte first. - if (byte_size > std::numeric_limits<uint32_t>::max()) return false; - for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; - --shift_bytes) { - (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8)); - } - return true; -} - -namespace { -class JSONToCBOREncoder : public JSONParserHandler { - public: - JSONToCBOREncoder(std::vector<uint8_t>* out, Status* status) - : out_(out), status_(status) { - *status_ = Status(); - } - - void HandleObjectBegin() override { - envelopes_.emplace_back(); - envelopes_.back().EncodeStart(out_); - out_->push_back(kInitialByteIndefiniteLengthMap); - } - - void HandleObjectEnd() override { - out_->push_back(kStopByte); - assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); - envelopes_.pop_back(); - } - - void HandleArrayBegin() override { - envelopes_.emplace_back(); - envelopes_.back().EncodeStart(out_); - out_->push_back(kInitialByteIndefiniteLengthArray); - } - - void HandleArrayEnd() override { - out_->push_back(kStopByte); - assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); - envelopes_.pop_back(); - } - - void HandleString8(span<uint8_t> chars) override { - EncodeString8(chars, out_); - } - - void HandleString16(span<uint16_t> chars) override { - for (uint16_t ch : chars) { - if (ch >= 0x7f) { - // If there's at least one non-7bit character, we encode as UTF16. - EncodeString16(chars, out_); - return; - } - } - std::vector<uint8_t> sevenbit_chars(chars.begin(), chars.end()); - EncodeString8(span<uint8_t>(sevenbit_chars.data(), sevenbit_chars.size()), - out_); - } - - void HandleBinary(std::vector<uint8_t> bytes) override { - EncodeBinary(span<uint8_t>(bytes.data(), bytes.size()), out_); - } - - void HandleDouble(double value) override { EncodeDouble(value, out_); } - - void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } - - void HandleBool(bool value) override { - // See RFC 7049 Section 2.3, Table 2. - out_->push_back(value ? kEncodedTrue : kEncodedFalse); - } - - void HandleNull() override { - // See RFC 7049 Section 2.3, Table 2. - out_->push_back(kEncodedNull); - } - - void HandleError(Status error) override { - assert(!error.ok()); - *status_ = error; - out_->clear(); - } - - private: - std::vector<uint8_t>* out_; - std::vector<EnvelopeEncoder> envelopes_; - Status* status_; -}; -} // namespace - -std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder( - std::vector<uint8_t>* out, Status* status) { - return std::unique_ptr<JSONParserHandler>(new JSONToCBOREncoder(out, status)); -} - -namespace { -// Below are three parsing routines for CBOR, which cover enough -// to roundtrip JSON messages. -bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); -bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); -bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out); - -void ParseUTF16String(CBORTokenizer* tokenizer, JSONParserHandler* out) { - std::vector<uint16_t> value; - span<uint8_t> rep = tokenizer->GetString16WireRep(); - for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) - value.push_back((rep[ii + 1] << 8) | rep[ii]); - out->HandleString16(span<uint16_t>(value.data(), value.size())); - tokenizer->Next(); -} - -bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); - out->HandleString8(tokenizer->GetString8()); - tokenizer->Next(); - return true; -} - -bool ParseValue(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - if (stack_depth > kStackLimit) { - out->HandleError( - Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos}); - return false; - } - // Skip past the envelope to get to what's inside. - if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE) - tokenizer->EnterEnvelope(); - switch (tokenizer->TokenTag()) { - case CBORTokenTag::ERROR_VALUE: - out->HandleError(tokenizer->Status()); - return false; - case CBORTokenTag::DONE: - out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, - tokenizer->Status().pos}); - return false; - case CBORTokenTag::TRUE_VALUE: - out->HandleBool(true); - tokenizer->Next(); - return true; - case CBORTokenTag::FALSE_VALUE: - out->HandleBool(false); - tokenizer->Next(); - return true; - case CBORTokenTag::NULL_VALUE: - out->HandleNull(); - tokenizer->Next(); - return true; - case CBORTokenTag::INT32: - out->HandleInt32(tokenizer->GetInt32()); - tokenizer->Next(); - return true; - case CBORTokenTag::DOUBLE: - out->HandleDouble(tokenizer->GetDouble()); - tokenizer->Next(); - return true; - case CBORTokenTag::STRING8: - return ParseUTF8String(tokenizer, out); - case CBORTokenTag::STRING16: - ParseUTF16String(tokenizer, out); - return true; - case CBORTokenTag::BINARY: { - span<uint8_t> binary = tokenizer->GetBinary(); - out->HandleBinary(std::vector<uint8_t>(binary.begin(), binary.end())); - tokenizer->Next(); - return true; - } - case CBORTokenTag::MAP_START: - return ParseMap(stack_depth + 1, tokenizer, out); - case CBORTokenTag::ARRAY_START: - return ParseArray(stack_depth + 1, tokenizer, out); - default: - out->HandleError( - Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos}); - return false; - } -} - -// |bytes| must start with the indefinite length array byte, so basically, -// ParseArray may only be called after an indefinite length array has been -// detected. -bool ParseArray(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START); - tokenizer->Next(); - out->HandleArrayBegin(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { - if (tokenizer->TokenTag() == CBORTokenTag::DONE) { - out->HandleError( - Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos}); - return false; - } - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { - out->HandleError(tokenizer->Status()); - return false; - } - // Parse value. - if (!ParseValue(stack_depth, tokenizer, out)) return false; - } - out->HandleArrayEnd(); - tokenizer->Next(); - return true; -} - -// |bytes| must start with the indefinite length array byte, so basically, -// ParseArray may only be called after an indefinite length array has been -// detected. -bool ParseMap(int32_t stack_depth, CBORTokenizer* tokenizer, - JSONParserHandler* out) { - assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START); - out->HandleObjectBegin(); - tokenizer->Next(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { - if (tokenizer->TokenTag() == CBORTokenTag::DONE) { - out->HandleError( - Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos}); - return false; - } - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { - out->HandleError(tokenizer->Status()); - return false; - } - // Parse key. - if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { - if (!ParseUTF8String(tokenizer, out)) return false; - } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { - ParseUTF16String(tokenizer, out); - } else { - out->HandleError( - Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos}); - return false; - } - // Parse value. - if (!ParseValue(stack_depth, tokenizer, out)) return false; - } - out->HandleObjectEnd(); - tokenizer->Next(); - return true; -} -} // namespace - -void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out) { - if (bytes.empty()) { - json_out->HandleError(Status{Error::CBOR_NO_INPUT, 0}); - return; - } - if (bytes[0] != kInitialByteForEnvelope) { - json_out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0}); - return; - } - CBORTokenizer tokenizer(bytes); - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { - json_out->HandleError(tokenizer.Status()); - return; - } - // We checked for the envelope start byte above, so the tokenizer - // must agree here, since it's not an error. - assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE); - tokenizer.EnterEnvelope(); - if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) { - json_out->HandleError( - Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos}); - return; - } - if (!ParseMap(/*stack_depth=*/1, &tokenizer, json_out)) return; - if (tokenizer.TokenTag() == CBORTokenTag::DONE) return; - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { - json_out->HandleError(tokenizer.Status()); - return; - } - json_out->HandleError( - Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos}); -} - -CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) { - ReadNextToken(/*enter_envelope=*/false); -} -CBORTokenizer::~CBORTokenizer() {} - -CBORTokenTag CBORTokenizer::TokenTag() const { return token_tag_; } - -void CBORTokenizer::Next() { - if (token_tag_ == CBORTokenTag::ERROR_VALUE || token_tag_ == CBORTokenTag::DONE) - return; - ReadNextToken(/*enter_envelope=*/false); -} - -void CBORTokenizer::EnterEnvelope() { - assert(token_tag_ == CBORTokenTag::ENVELOPE); - ReadNextToken(/*enter_envelope=*/true); -} - -Status CBORTokenizer::Status() const { return status_; } - -int32_t CBORTokenizer::GetInt32() const { - assert(token_tag_ == CBORTokenTag::INT32); - // The range checks happen in ::ReadNextToken(). - return static_cast<uint32_t>( - token_start_type_ == MajorType::UNSIGNED - ? token_start_internal_value_ - : -static_cast<int64_t>(token_start_internal_value_) - 1); -} - -double CBORTokenizer::GetDouble() const { - assert(token_tag_ == CBORTokenTag::DOUBLE); - union { - uint64_t from_uint64; - double to_double; - } reinterpret; - reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>( - bytes_.subspan(status_.pos + 1)); - return reinterpret.to_double; -} - -span<uint8_t> CBORTokenizer::GetString8() const { - assert(token_tag_ == CBORTokenTag::STRING8); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -span<uint8_t> CBORTokenizer::GetString16WireRep() const { - assert(token_tag_ == CBORTokenTag::STRING16); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -span<uint8_t> CBORTokenizer::GetBinary() const { - assert(token_tag_ == CBORTokenTag::BINARY); - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); -} - -void CBORTokenizer::ReadNextToken(bool enter_envelope) { - if (enter_envelope) { - status_.pos += kEncodedEnvelopeHeaderSize; - } else { - status_.pos = - status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_; - } - status_.error = Error::OK; - if (status_.pos >= bytes_.size()) { - token_tag_ = CBORTokenTag::DONE; - return; - } - switch (bytes_[status_.pos]) { - case kStopByte: - SetToken(CBORTokenTag::STOP, 1); - return; - case kInitialByteIndefiniteLengthMap: - SetToken(CBORTokenTag::MAP_START, 1); - return; - case kInitialByteIndefiniteLengthArray: - SetToken(CBORTokenTag::ARRAY_START, 1); - return; - case kEncodedTrue: - SetToken(CBORTokenTag::TRUE_VALUE, 1); - return; - case kEncodedFalse: - SetToken(CBORTokenTag::FALSE_VALUE, 1); - return; - case kEncodedNull: - SetToken(CBORTokenTag::NULL_VALUE, 1); - return; - case kExpectedConversionToBase64Tag: { // BINARY - int8_t bytes_read = - ReadTokenStart(bytes_.subspan(status_.pos + 1), &token_start_type_, - &token_start_internal_value_); - int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_; - if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING || - status_.pos + token_byte_length > bytes_.size()) { - SetError(Error::CBOR_INVALID_BINARY); - return; - } - SetToken(CBORTokenTag::BINARY, - static_cast<std::ptrdiff_t>(token_byte_length)); - return; - } - case kInitialByteForDouble: { // DOUBLE - if (status_.pos + kEncodedDoubleSize > bytes_.size()) { - SetError(Error::CBOR_INVALID_DOUBLE); - return; - } - SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize); - return; - } - case kInitialByteForEnvelope: { // ENVELOPE - if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - // The envelope must be a byte string with 32 bit length. - if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - // Read the length of the byte string. - token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>( - bytes_.subspan(status_.pos + 2)); - // Make sure the payload is contained within the message. - if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize + - status_.pos > - static_cast<std::size_t>(bytes_.size())) { - SetError(Error::CBOR_INVALID_ENVELOPE); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::ENVELOPE, - kEncodedEnvelopeHeaderSize + length); - return; - } - default: { - span<uint8_t> remainder = - bytes_.subspan(status_.pos, bytes_.size() - status_.pos); - assert(!remainder.empty()); - int8_t token_start_length = ReadTokenStart(remainder, &token_start_type_, - &token_start_internal_value_); - bool success = token_start_length != -1; - switch (token_start_type_) { - case MajorType::UNSIGNED: // INT32. - if (!success || std::numeric_limits<int32_t>::max() < - token_start_internal_value_) { - SetError(Error::CBOR_INVALID_INT32); - return; - } - SetToken(CBORTokenTag::INT32, token_start_length); - return; - case MajorType::NEGATIVE: // INT32. - if (!success || - std::numeric_limits<int32_t>::min() > - -static_cast<int64_t>(token_start_internal_value_) - 1) { - SetError(Error::CBOR_INVALID_INT32); - return; - } - SetToken(CBORTokenTag::INT32, token_start_length); - return; - case MajorType::STRING: { // STRING8. - if (!success || remainder.size() < static_cast<int64_t>( - token_start_internal_value_)) { - SetError(Error::CBOR_INVALID_STRING8); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::STRING8, token_start_length + length); - return; - } - case MajorType::BYTE_STRING: { // STRING16. - if (!success || - remainder.size() < - static_cast<int64_t>(token_start_internal_value_) || - // Must be divisible by 2 since UTF16 is 2 bytes per character. - token_start_internal_value_ & 1) { - SetError(Error::CBOR_INVALID_STRING16); - return; - } - auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); - SetToken(CBORTokenTag::STRING16, token_start_length + length); - return; - } - case MajorType::ARRAY: - case MajorType::MAP: - case MajorType::TAG: - case MajorType::SIMPLE_VALUE: - SetError(Error::CBOR_UNSUPPORTED_VALUE); - return; - } - } - } -} - -void CBORTokenizer::SetToken(CBORTokenTag token_tag, - std::ptrdiff_t token_byte_length) { - token_tag_ = token_tag; - token_byte_length_ = token_byte_length; -} - -void CBORTokenizer::SetError(Error error) { - token_tag_ = CBORTokenTag::ERROR_VALUE; - status_.error = error; -} - -#if 0 -void DumpCBOR(span<uint8_t> cbor) { - std::string indent; - CBORTokenizer tokenizer(cbor); - while (true) { - fprintf(stderr, "%s", indent.c_str()); - switch (tokenizer.TokenTag()) { - case CBORTokenTag::ERROR_VALUE: - fprintf(stderr, "ERROR {status.error=%d, status.pos=%ld}\n", - tokenizer.Status().error, tokenizer.Status().pos); - return; - case CBORTokenTag::DONE: - fprintf(stderr, "DONE\n"); - return; - case CBORTokenTag::TRUE_VALUE: - fprintf(stderr, "TRUE_VALUE\n"); - break; - case CBORTokenTag::FALSE_VALUE: - fprintf(stderr, "FALSE_VALUE\n"); - break; - case CBORTokenTag::NULL_VALUE: - fprintf(stderr, "NULL_VALUE\n"); - break; - case CBORTokenTag::INT32: - fprintf(stderr, "INT32 [%d]\n", tokenizer.GetInt32()); - break; - case CBORTokenTag::DOUBLE: - fprintf(stderr, "DOUBLE [%lf]\n", tokenizer.GetDouble()); - break; - case CBORTokenTag::STRING8: { - span<uint8_t> v = tokenizer.GetString8(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "STRING8 [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::STRING16: { - span<uint8_t> v = tokenizer.GetString16WireRep(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "STRING16 [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::BINARY: { - span<uint8_t> v = tokenizer.GetBinary(); - std::string t(v.begin(), v.end()); - fprintf(stderr, "BINARY [%s]\n", t.c_str()); - break; - } - case CBORTokenTag::MAP_START: - fprintf(stderr, "MAP_START\n"); - indent += " "; - break; - case CBORTokenTag::ARRAY_START: - fprintf(stderr, "ARRAY_START\n"); - indent += " "; - break; - case CBORTokenTag::STOP: - fprintf(stderr, "STOP\n"); - indent.erase(0, 2); - break; - case CBORTokenTag::ENVELOPE: - fprintf(stderr, "ENVELOPE\n"); - tokenizer.EnterEnvelope(); - continue; - } - tokenizer.Next(); - } -} -#endif - - -{% for namespace in config.protocol.namespace %} -} // namespace {{namespace}} -{% endfor %} -
diff --git a/third_party/inspector_protocol/lib/Values_cpp.template b/third_party/inspector_protocol/lib/Values_cpp.template index 20899a3..2d4463e2 100644 --- a/third_party/inspector_protocol/lib/Values_cpp.template +++ b/third_party/inspector_protocol/lib/Values_cpp.template
@@ -66,21 +66,21 @@ // Below are three parsing routines for CBOR, which cover enough // to roundtrip JSON messages. -std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, CBORTokenizer* tokenizer); -std::unique_ptr<ListValue> parseArray(int32_t stack_depth, CBORTokenizer* tokenizer); -std::unique_ptr<Value> parseValue(int32_t stack_depth, CBORTokenizer* tokenizer); +std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); +std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); +std::unique_ptr<Value> parseValue(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); // |bytes| must start with the indefinite length array byte, so basically, // ParseArray may only be called after an indefinite length array has been // detected. -std::unique_ptr<ListValue> parseArray(int32_t stack_depth, CBORTokenizer* tokenizer) { - DCHECK(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START); +std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { + DCHECK(tokenizer->TokenTag() == cbor::CBORTokenTag::ARRAY_START); tokenizer->Next(); auto list = ListValue::create(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { + while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) { // Error::CBOR_UNEXPECTED_EOF_IN_ARRAY - if (tokenizer->TokenTag() == CBORTokenTag::DONE) return nullptr; - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr; + if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) return nullptr; + if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; // Parse value. auto value = parseValue(stack_depth, tokenizer); if (!value) return nullptr; @@ -91,51 +91,51 @@ } std::unique_ptr<Value> parseValue( - int32_t stack_depth, CBORTokenizer* tokenizer) { + int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { // Error::CBOR_STACK_LIMIT_EXCEEDED if (stack_depth > kStackLimitValues) return nullptr; // Skip past the envelope to get to what's inside. - if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE) + if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE) tokenizer->EnterEnvelope(); switch (tokenizer->TokenTag()) { - case CBORTokenTag::ERROR_VALUE: + case cbor::CBORTokenTag::ERROR_VALUE: return nullptr; - case CBORTokenTag::DONE: + case cbor::CBORTokenTag::DONE: // Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE return nullptr; - case CBORTokenTag::TRUE_VALUE: { + case cbor::CBORTokenTag::TRUE_VALUE: { std::unique_ptr<Value> value = FundamentalValue::create(true); tokenizer->Next(); return value; } - case CBORTokenTag::FALSE_VALUE: { + case cbor::CBORTokenTag::FALSE_VALUE: { std::unique_ptr<Value> value = FundamentalValue::create(false); tokenizer->Next(); return value; } - case CBORTokenTag::NULL_VALUE: { + case cbor::CBORTokenTag::NULL_VALUE: { std::unique_ptr<Value> value = FundamentalValue::null(); tokenizer->Next(); return value; } - case CBORTokenTag::INT32: { + case cbor::CBORTokenTag::INT32: { std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetInt32()); tokenizer->Next(); return value; } - case CBORTokenTag::DOUBLE: { + case cbor::CBORTokenTag::DOUBLE: { std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetDouble()); tokenizer->Next(); return value; } - case CBORTokenTag::STRING8: { + case cbor::CBORTokenTag::STRING8: { span<uint8_t> str = tokenizer->GetString8(); std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF8(str.data(), str.size())); tokenizer->Next(); return value; } - case CBORTokenTag::STRING16: { + case cbor::CBORTokenTag::STRING16: { span<uint8_t> wire = tokenizer->GetString16WireRep(); DCHECK_EQ(wire.size() & 1, 0); std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16( @@ -143,14 +143,14 @@ tokenizer->Next(); return value; } - case CBORTokenTag::BINARY: { + case cbor::CBORTokenTag::BINARY: { span<uint8_t> payload = tokenizer->GetBinary(); tokenizer->Next(); return BinaryValue::create(Binary::fromSpan(payload.data(), payload.size())); } - case CBORTokenTag::MAP_START: + case cbor::CBORTokenTag::MAP_START: return parseMap(stack_depth + 1, tokenizer); - case CBORTokenTag::ARRAY_START: + case cbor::CBORTokenTag::ARRAY_START: return parseArray(stack_depth + 1, tokenizer); default: // Error::CBOR_UNSUPPORTED_VALUE @@ -162,22 +162,22 @@ // ParseArray may only be called after an indefinite length array has been // detected. std::unique_ptr<DictionaryValue> parseMap( - int32_t stack_depth, CBORTokenizer* tokenizer) { + int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { auto dict = DictionaryValue::create(); tokenizer->Next(); - while (tokenizer->TokenTag() != CBORTokenTag::STOP) { - if (tokenizer->TokenTag() == CBORTokenTag::DONE) { + while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) { + if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) { // Error::CBOR_UNEXPECTED_EOF_IN_MAP return nullptr; } - if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr; + if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; // Parse key. String key; - if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { + if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { span<uint8_t> key_span = tokenizer->GetString8(); key = StringUtil::fromUTF8(key_span.data(), key_span.size()); tokenizer->Next(); - } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { + } else if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) { return nullptr; // STRING16 not supported yet. } else { // Error::CBOR_INVALID_MAP_KEY @@ -202,22 +202,21 @@ if (bytes.empty()) return nullptr; // Error::CBOR_INVALID_START_BYTE - // TODO(johannes): EncodeInitialByteForEnvelope() method. - if (bytes[0] != 0xd8) return nullptr; + if (bytes[0] != cbor::InitialByteForEnvelope()) return nullptr; - CBORTokenizer tokenizer(bytes); - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr; + cbor::CBORTokenizer tokenizer(bytes); + if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; // We checked for the envelope start byte above, so the tokenizer // must agree here, since it's not an error. - DCHECK(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE); + DCHECK(tokenizer.TokenTag() == cbor::CBORTokenTag::ENVELOPE); tokenizer.EnterEnvelope(); // Error::MAP_START_EXPECTED - if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) return nullptr; + if (tokenizer.TokenTag() != cbor::CBORTokenTag::MAP_START) return nullptr; std::unique_ptr<Value> result = parseMap(/*stack_depth=*/1, &tokenizer); if (!result) return nullptr; - if (tokenizer.TokenTag() == CBORTokenTag::DONE) return result; - if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) return nullptr; + if (tokenizer.TokenTag() == cbor::CBORTokenTag::DONE) return result; + if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; // Error::CBOR_TRAILING_JUNK return nullptr; } @@ -255,7 +254,7 @@ void Value::writeBinary(std::vector<uint8_t>* bytes) const { DCHECK(m_type == TypeNull); - bytes->push_back(EncodeNull()); + bytes->push_back(cbor::EncodeNull()); } std::unique_ptr<Value> Value::clone() const @@ -332,13 +331,13 @@ void FundamentalValue::writeBinary(std::vector<uint8_t>* bytes) const { switch (type()) { case TypeDouble: - EncodeDouble(m_doubleValue, bytes); + cbor::EncodeDouble(m_doubleValue, bytes); return; case TypeInteger: - EncodeInt32(m_integerValue, bytes); + cbor::EncodeInt32(m_integerValue, bytes); return; case TypeBoolean: - bytes->push_back(m_boolValue ? EncodeTrue() : EncodeFalse()); + bytes->push_back(m_boolValue ? cbor::EncodeTrue() : cbor::EncodeFalse()); return; default: DCHECK(false); @@ -381,19 +380,19 @@ // transcodes to UTF8 if needed. void EncodeString(const String& s, std::vector<uint8_t>* out) { if (StringUtil::CharacterCount(s) == 0) { - EncodeString8(span<uint8_t>(nullptr, 0), out); // Empty string. + cbor::EncodeString8(span<uint8_t>(nullptr, 0), out); // Empty string. } else if (StringUtil::CharactersLatin1(s)) { - EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s), - StringUtil::CharacterCount(s)), - out); + cbor::EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s), + StringUtil::CharacterCount(s)), + out); } else if (StringUtil::CharactersUTF16(s)) { - EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s), - StringUtil::CharacterCount(s)), - out); + cbor::EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s), + StringUtil::CharacterCount(s)), + out); } else if (StringUtil::CharactersUTF8(s)) { - EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s), - StringUtil::CharacterCount(s)), - out); + cbor::EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s), + StringUtil::CharacterCount(s)), + out); } } } // namespace @@ -420,7 +419,8 @@ } void BinaryValue::writeBinary(std::vector<uint8_t>* bytes) const { - EncodeBinary(span<uint8_t>(m_binaryValue.data(), m_binaryValue.size()), bytes); + cbor::EncodeBinary(span<uint8_t>(m_binaryValue.data(), + m_binaryValue.size()), bytes); } std::unique_ptr<Value> BinaryValue::clone() const @@ -583,9 +583,9 @@ } void DictionaryValue::writeBinary(std::vector<uint8_t>* bytes) const { - EnvelopeEncoder encoder; + cbor::EnvelopeEncoder encoder; encoder.EncodeStart(bytes); - bytes->push_back(EncodeIndefiniteLengthMapStart()); + bytes->push_back(cbor::EncodeIndefiniteLengthMapStart()); for (size_t i = 0; i < m_order.size(); ++i) { const String& key = m_order[i]; Dictionary::const_iterator value = m_data.find(key); @@ -593,7 +593,7 @@ EncodeString(key, bytes); value->second->writeBinary(bytes); } - bytes->push_back(EncodeStop()); + bytes->push_back(cbor::EncodeStop()); encoder.EncodeStop(bytes); } @@ -632,13 +632,13 @@ } void ListValue::writeBinary(std::vector<uint8_t>* bytes) const { - EnvelopeEncoder encoder; + cbor::EnvelopeEncoder encoder; encoder.EncodeStart(bytes); - bytes->push_back(EncodeIndefiniteLengthArrayStart()); + bytes->push_back(cbor::EncodeIndefiniteLengthArrayStart()); for (size_t i = 0; i < m_data.size(); ++i) { m_data[i]->writeBinary(bytes); } - bytes->push_back(EncodeStop()); + bytes->push_back(cbor::EncodeStop()); encoder.EncodeStop(bytes); }
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template index 24855d4..94bcd88 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -256,34 +256,34 @@ if (in.size() < 1 + 1 + 4 + 1 + 1) return false; const uint8_t* envelope = reinterpret_cast<const uint8_t*>(in.data()); - if (cbor::kInitialByteForEnvelope != envelope[0]) + if (cbor::InitialByteForEnvelope() != envelope[0]) return false; - if (cbor::kInitialByteFor32BitLengthByteString != envelope[1]) + if (cbor::InitialByteFor32BitLengthByteString() != envelope[1]) return false; - if (cbor::kInitialByteIndefiniteLengthMap != envelope[6]) + if (cbor::EncodeIndefiniteLengthMapStart() != envelope[6]) return false; uint32_t envelope_size = ReadEnvelopeSize(envelope + 2); if (envelope_size + 2 + 4 != in.size()) return false; - if (cbor::kStopByte != static_cast<uint8_t>(*in.rbegin())) + if (cbor::EncodeStop() != static_cast<uint8_t>(*in.rbegin())) return false; std::vector<uint8_t> encoded_entry; encoded_entry.reserve(1 + 4 + key.size() + 1 + 4 + value.size()); span<uint8_t> key_span( reinterpret_cast<const uint8_t*>(key.data()), key.size()); - EncodeString8(key_span, &encoded_entry); + cbor::EncodeString8(key_span, &encoded_entry); span<uint8_t> value_span( reinterpret_cast<const uint8_t*>(value.data()), value.size()); - EncodeString8(value_span, &encoded_entry); + cbor::EncodeString8(value_span, &encoded_entry); out->clear(); out->reserve(in.size() + encoded_entry.size()); out->append(in.begin(), in.end() - 1); out->append(reinterpret_cast<const char*>(encoded_entry.data()), encoded_entry.size()); - out->append(1, static_cast<char>(cbor::kStopByte)); + out->append(1, static_cast<char>(cbor::EncodeStop())); std::size_t new_size = envelope_size + out->size() - in.size(); if (new_size > static_cast<std::size_t>( std::numeric_limits<uint32_t>::max())) {
diff --git a/third_party/inspector_protocol/lib/encoding_cpp.template b/third_party/inspector_protocol/lib/encoding_cpp.template new file mode 100644 index 0000000..84251d9 --- /dev/null +++ b/third_party/inspector_protocol/lib/encoding_cpp.template
@@ -0,0 +1,1807 @@ +{# This template is generated by gen_cbor_templates.py. #} +// Generated by lib/encoding_cpp.template. + +// Copyright 2019 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 <cassert> +#include <cstring> +#include <limits> +#include <stack> + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +// ===== encoding/encoding.cc ===== + +namespace cbor { +namespace { +// Indicates the number of bits the "initial byte" needs to be shifted to the +// right after applying |kMajorTypeMask| to produce the major type in the +// lowermost bits. +static constexpr uint8_t kMajorTypeBitShift = 5u; +// Mask selecting the low-order 5 bits of the "initial byte", which is where +// the additional information is encoded. +static constexpr uint8_t kAdditionalInformationMask = 0x1f; +// Mask selecting the high-order 3 bits of the "initial byte", which indicates +// the major type of the encoded value. +static constexpr uint8_t kMajorTypeMask = 0xe0; +// Indicates the integer is in the following byte. +static constexpr uint8_t kAdditionalInformation1Byte = 24u; +// Indicates the integer is in the next 2 bytes. +static constexpr uint8_t kAdditionalInformation2Bytes = 25u; +// Indicates the integer is in the next 4 bytes. +static constexpr uint8_t kAdditionalInformation4Bytes = 26u; +// Indicates the integer is in the next 8 bytes. +static constexpr uint8_t kAdditionalInformation8Bytes = 27u; + +// Encodes the initial byte, consisting of the |type| in the first 3 bits +// followed by 5 bits of |additional_info|. +constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { + return (static_cast<uint8_t>(type) << kMajorTypeBitShift) | + (additional_info & kAdditionalInformationMask); +} + +// TAG 24 indicates that what follows is a byte string which is +// encoded in CBOR format. We use this as a wrapper for +// maps and arrays, allowing us to skip them, because the +// byte string carries its size (byte length). +// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 +static constexpr uint8_t kInitialByteForEnvelope = + EncodeInitialByte(MajorType::TAG, 24); +// The initial byte for a byte string with at most 2^32 bytes +// of payload. This is used for envelope encoding, even if +// the byte string is shorter. +static constexpr uint8_t kInitialByteFor32BitLengthByteString = + EncodeInitialByte(MajorType::BYTE_STRING, 26); + +// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional +// info = 31. +static constexpr uint8_t kInitialByteIndefiniteLengthArray = + EncodeInitialByte(MajorType::ARRAY, 31); +static constexpr uint8_t kInitialByteIndefiniteLengthMap = + EncodeInitialByte(MajorType::MAP, 31); +// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite +// length maps / arrays. +static constexpr uint8_t kStopByte = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); + +// See RFC 7049 Section 2.3, Table 2. +static constexpr uint8_t kEncodedTrue = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 21); +static constexpr uint8_t kEncodedFalse = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 20); +static constexpr uint8_t kEncodedNull = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 22); +static constexpr uint8_t kInitialByteForDouble = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 27); + +// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for +// arbitrary binary data encoded as BYTE_STRING. +static constexpr uint8_t kExpectedConversionToBase64Tag = + EncodeInitialByte(MajorType::TAG, 22); + +// Writes the bytes for |v| to |out|, starting with the most significant byte. +// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html +template <typename T> +void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) { + for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes) + out->push_back(0xff & (v >> (shift_bytes * 8))); +} + +// Extracts sizeof(T) bytes from |in| to extract a value of type T +// (e.g. uint64_t, uint32_t, ...), most significant byte first. +// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html +template <typename T> +T ReadBytesMostSignificantByteFirst(span<uint8_t> in) { + assert(static_cast<std::size_t>(in.size()) >= sizeof(T)); + T result = 0; + for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) + result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8); + return result; +} +} // namespace + +namespace internals { +// Reads the start of a token with definitive size from |bytes|. +// |type| is the major type as specified in RFC 7049 Section 2.1. +// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size +// (e.g. for BYTE_STRING). +// If successful, returns the number of bytes read. Otherwise returns -1. +int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { + if (bytes.empty()) + return -1; + uint8_t initial_byte = bytes[0]; + *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); + + uint8_t additional_information = initial_byte & kAdditionalInformationMask; + if (additional_information < 24) { + // Values 0-23 are encoded directly into the additional info of the + // initial byte. + *value = additional_information; + return 1; + } + if (additional_information == kAdditionalInformation1Byte) { + // Values 24-255 are encoded with one initial byte, followed by the value. + if (bytes.size() < 2) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); + return 2; + } + if (additional_information == kAdditionalInformation2Bytes) { + // Values 256-65535: 1 initial byte + 2 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); + return 3; + } + if (additional_information == kAdditionalInformation4Bytes) { + // 32 bit uint: 1 initial byte + 4 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); + return 5; + } + if (additional_information == kAdditionalInformation8Bytes) { + // 64 bit uint: 1 initial byte + 8 bytes payload. + if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t)) + return -1; + *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); + return 9; + } + return -1; +} + +// Writes the start of a token with |type|. The |value| may indicate the size, +// or it may be the payload if the value is an unsigned integer. +void WriteTokenStart(MajorType type, + uint64_t value, + std::vector<uint8_t>* encoded) { + if (value < 24) { + // Values 0-23 are encoded directly into the additional info of the + // initial byte. + encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value)); + return; + } + if (value <= std::numeric_limits<uint8_t>::max()) { + // Values 24-255 are encoded with one initial byte, followed by the value. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte)); + encoded->push_back(value); + return; + } + if (value <= std::numeric_limits<uint16_t>::max()) { + // Values 256-65535: 1 initial byte + 2 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes)); + WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded); + return; + } + if (value <= std::numeric_limits<uint32_t>::max()) { + // 32 bit uint: 1 initial byte + 4 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes)); + WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value), + encoded); + return; + } + // 64 bit uint: 1 initial byte + 8 bytes payload. + encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes)); + WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded); +} +} // namespace internals + +// ============================================================================= +// Detecting CBOR content +// ============================================================================= + +uint8_t InitialByteForEnvelope() { + return kInitialByteForEnvelope; +} +uint8_t InitialByteFor32BitLengthByteString() { + return kInitialByteFor32BitLengthByteString; +} +bool IsCBORMessage(span<uint8_t> msg) { + return msg.size() >= 6 && msg[0] == InitialByteForEnvelope() && + msg[1] == InitialByteFor32BitLengthByteString(); +} + +// ============================================================================= +// Encoding invidiual CBOR items +// ============================================================================= + +uint8_t EncodeTrue() { + return kEncodedTrue; +} +uint8_t EncodeFalse() { + return kEncodedFalse; +} +uint8_t EncodeNull() { + return kEncodedNull; +} + +uint8_t EncodeIndefiniteLengthArrayStart() { + return kInitialByteIndefiniteLengthArray; +} + +uint8_t EncodeIndefiniteLengthMapStart() { + return kInitialByteIndefiniteLengthMap; +} + +uint8_t EncodeStop() { + return kStopByte; +} + +void EncodeInt32(int32_t value, std::vector<uint8_t>* out) { + if (value >= 0) { + internals::WriteTokenStart(MajorType::UNSIGNED, value, out); + } else { + uint64_t representation = static_cast<uint64_t>(-(value + 1)); + internals::WriteTokenStart(MajorType::NEGATIVE, representation, out); + } +} + +void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) { + uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); + internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); + // When emitting UTF16 characters, we always write the least significant byte + // first; this is because it's the native representation for X86. + // TODO(johannes): Implement a more efficient thing here later, e.g. + // casting *iff* the machine has this byte order. + // The wire format for UTF16 chars will probably remain the same + // (least significant byte first) since this way we can have + // golden files, unittests, etc. that port easily and universally. + // See also: + // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html + for (const uint16_t two_bytes : in) { + out->push_back(two_bytes); + out->push_back(two_bytes >> 8); + } +} + +void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) { + internals::WriteTokenStart(MajorType::STRING, + static_cast<uint64_t>(in.size_bytes()), out); + out->insert(out->end(), in.begin(), in.end()); +} + +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { + for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) + continue; + // If there's at least one non-ASCII char, convert to UTF8. + std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); + for (; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) { + utf8.push_back(latin1[ii]); + } else { + // 0xC0 means it's a UTF8 sequence with 2 bytes. + utf8.push_back((latin1[ii] >> 6) | 0xc0); + utf8.push_back((latin1[ii] | 0x80) & 0xbf); + } + } + EncodeString8(SpanFromVector(utf8), out); + return; + } + EncodeString8(latin1, out); +} + +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { + // If there's at least one non-ASCII char, encode as STRING16 (UTF16). + for (uint16_t ch : utf16) { + if (ch <= 127) + continue; + EncodeString16(utf16, out); + return; + } + // It's all US-ASCII, strip out every second byte and encode as UTF8. + internals::WriteTokenStart(MajorType::STRING, + static_cast<uint64_t>(utf16.size()), out); + out->insert(out->end(), utf16.begin(), utf16.end()); +} + +void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { + out->push_back(kExpectedConversionToBase64Tag); + uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); + internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out); + out->insert(out->end(), in.begin(), in.end()); +} + +// A double is encoded with a specific initial byte +// (kInitialByteForDouble) plus the 64 bits of payload for its value. +constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t); + +// An envelope is encoded with a specific initial byte +// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32 +// bit wide length, plus a 32 bit length for that string. +constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t); + +void EncodeDouble(double value, std::vector<uint8_t>* out) { + // The additional_info=27 indicates 64 bits for the double follow. + // See RFC 7049 Section 2.3, Table 1. + out->push_back(kInitialByteForDouble); + union { + double from_double; + uint64_t to_uint64; + } reinterpret; + reinterpret.from_double = value; + WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out); +} + +// ============================================================================= +// cbor::EnvelopeEncoder - for wrapping submessages +// ============================================================================= + +void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { + assert(byte_size_pos_ == 0); + out->push_back(kInitialByteForEnvelope); + out->push_back(kInitialByteFor32BitLengthByteString); + byte_size_pos_ = out->size(); + out->resize(out->size() + sizeof(uint32_t)); +} + +bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { + assert(byte_size_pos_ != 0); + // The byte size is the size of the payload, that is, all the + // bytes that were written past the byte size position itself. + uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t)); + // We store exactly 4 bytes, so at most INT32MAX, with most significant + // byte first. + if (byte_size > std::numeric_limits<uint32_t>::max()) + return false; + for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; + --shift_bytes) { + (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8)); + } + return true; +} + +// ============================================================================= +// cbor::NewCBOREncoder - for encoding from a streaming parser +// ============================================================================= + +namespace { +class CBOREncoder : public StreamingParserHandler { + public: + CBOREncoder(std::vector<uint8_t>* out, Status* status) + : out_(out), status_(status) { + *status_ = Status(); + } + + void HandleMapBegin() override { + envelopes_.emplace_back(); + envelopes_.back().EncodeStart(out_); + out_->push_back(kInitialByteIndefiniteLengthMap); + } + + void HandleMapEnd() override { + out_->push_back(kStopByte); + assert(!envelopes_.empty()); + envelopes_.back().EncodeStop(out_); + envelopes_.pop_back(); + } + + void HandleArrayBegin() override { + envelopes_.emplace_back(); + envelopes_.back().EncodeStart(out_); + out_->push_back(kInitialByteIndefiniteLengthArray); + } + + void HandleArrayEnd() override { + out_->push_back(kStopByte); + assert(!envelopes_.empty()); + envelopes_.back().EncodeStop(out_); + envelopes_.pop_back(); + } + + void HandleString8(span<uint8_t> chars) override { + EncodeString8(chars, out_); + } + + void HandleString16(span<uint16_t> chars) override { + EncodeFromUTF16(chars, out_); + } + + void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); } + + void HandleDouble(double value) override { EncodeDouble(value, out_); } + + void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } + + void HandleBool(bool value) override { + // See RFC 7049 Section 2.3, Table 2. + out_->push_back(value ? kEncodedTrue : kEncodedFalse); + } + + void HandleNull() override { + // See RFC 7049 Section 2.3, Table 2. + out_->push_back(kEncodedNull); + } + + void HandleError(Status error) override { + assert(!error.ok()); + *status_ = error; + out_->clear(); + } + + private: + std::vector<uint8_t>* out_; + std::vector<EnvelopeEncoder> envelopes_; + Status* status_; +}; +} // namespace + +std::unique_ptr<StreamingParserHandler> NewCBOREncoder( + std::vector<uint8_t>* out, + Status* status) { + return std::unique_ptr<StreamingParserHandler>(new CBOREncoder(out, status)); +} + +// ============================================================================= +// cbor::CBORTokenizer - for parsing individual CBOR items +// ============================================================================= + +CBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) { + ReadNextToken(/*enter_envelope=*/false); +} +CBORTokenizer::~CBORTokenizer() {} + +CBORTokenTag CBORTokenizer::TokenTag() const { + return token_tag_; +} + +void CBORTokenizer::Next() { + if (token_tag_ == CBORTokenTag::ERROR_VALUE || + token_tag_ == CBORTokenTag::DONE) + return; + ReadNextToken(/*enter_envelope=*/false); +} + +void CBORTokenizer::EnterEnvelope() { + assert(token_tag_ == CBORTokenTag::ENVELOPE); + ReadNextToken(/*enter_envelope=*/true); +} + +Status CBORTokenizer::Status() const { + return status_; +} + +int32_t CBORTokenizer::GetInt32() const { + assert(token_tag_ == CBORTokenTag::INT32); + // The range checks happen in ::ReadNextToken(). + return static_cast<uint32_t>( + token_start_type_ == MajorType::UNSIGNED + ? token_start_internal_value_ + : -static_cast<int64_t>(token_start_internal_value_) - 1); +} + +double CBORTokenizer::GetDouble() const { + assert(token_tag_ == CBORTokenTag::DOUBLE); + union { + uint64_t from_uint64; + double to_double; + } reinterpret; + reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>( + bytes_.subspan(status_.pos + 1)); + return reinterpret.to_double; +} + +span<uint8_t> CBORTokenizer::GetString8() const { + assert(token_tag_ == CBORTokenTag::STRING8); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetString16WireRep() const { + assert(token_tag_ == CBORTokenTag::STRING16); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetBinary() const { + assert(token_tag_ == CBORTokenTag::BINARY); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + (token_byte_length_ - length), length); +} + +span<uint8_t> CBORTokenizer::GetEnvelopeContents() const { + assert(token_tag_ == CBORTokenTag::ENVELOPE); + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length); +} + +void CBORTokenizer::ReadNextToken(bool enter_envelope) { + if (enter_envelope) { + status_.pos += kEncodedEnvelopeHeaderSize; + } else { + status_.pos = + status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_; + } + status_.error = Error::OK; + if (status_.pos >= bytes_.size()) { + token_tag_ = CBORTokenTag::DONE; + return; + } + switch (bytes_[status_.pos]) { + case kStopByte: + SetToken(CBORTokenTag::STOP, 1); + return; + case kInitialByteIndefiniteLengthMap: + SetToken(CBORTokenTag::MAP_START, 1); + return; + case kInitialByteIndefiniteLengthArray: + SetToken(CBORTokenTag::ARRAY_START, 1); + return; + case kEncodedTrue: + SetToken(CBORTokenTag::TRUE_VALUE, 1); + return; + case kEncodedFalse: + SetToken(CBORTokenTag::FALSE_VALUE, 1); + return; + case kEncodedNull: + SetToken(CBORTokenTag::NULL_VALUE, 1); + return; + case kExpectedConversionToBase64Tag: { // BINARY + int8_t bytes_read = internals::ReadTokenStart( + bytes_.subspan(status_.pos + 1), &token_start_type_, + &token_start_internal_value_); + int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_; + if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING || + status_.pos + token_byte_length > bytes_.size()) { + SetError(Error::CBOR_INVALID_BINARY); + return; + } + SetToken(CBORTokenTag::BINARY, + static_cast<std::ptrdiff_t>(token_byte_length)); + return; + } + case kInitialByteForDouble: { // DOUBLE + if (status_.pos + kEncodedDoubleSize > bytes_.size()) { + SetError(Error::CBOR_INVALID_DOUBLE); + return; + } + SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize); + return; + } + case kInitialByteForEnvelope: { // ENVELOPE + if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + // The envelope must be a byte string with 32 bit length. + if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + // Read the length of the byte string. + token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>( + bytes_.subspan(status_.pos + 2)); + // Make sure the payload is contained within the message. + if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize + + status_.pos > + static_cast<std::size_t>(bytes_.size())) { + SetError(Error::CBOR_INVALID_ENVELOPE); + return; + } + auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length); + return; + } + default: { + span<uint8_t> remainder = + bytes_.subspan(status_.pos, bytes_.size() - status_.pos); + assert(!remainder.empty()); + int8_t token_start_length = internals::ReadTokenStart( + remainder, &token_start_type_, &token_start_internal_value_); + bool success = token_start_length != -1; + switch (token_start_type_) { + case MajorType::UNSIGNED: // INT32. + if (!success || std::numeric_limits<int32_t>::max() < + token_start_internal_value_) { + SetError(Error::CBOR_INVALID_INT32); + return; + } + SetToken(CBORTokenTag::INT32, token_start_length); + return; + case MajorType::NEGATIVE: // INT32. + if (!success || + std::numeric_limits<int32_t>::min() > + -static_cast<int64_t>(token_start_internal_value_) - 1) { + SetError(Error::CBOR_INVALID_INT32); + return; + } + SetToken(CBORTokenTag::INT32, token_start_length); + return; + case MajorType::STRING: { // STRING8. + if (!success || remainder.size() < static_cast<int64_t>( + token_start_internal_value_)) { + SetError(Error::CBOR_INVALID_STRING8); + return; + } + auto length = + static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::STRING8, token_start_length + length); + return; + } + case MajorType::BYTE_STRING: { // STRING16. + if (!success || + remainder.size() < + static_cast<int64_t>(token_start_internal_value_) || + // Must be divisible by 2 since UTF16 is 2 bytes per character. + token_start_internal_value_ & 1) { + SetError(Error::CBOR_INVALID_STRING16); + return; + } + auto length = + static_cast<std::ptrdiff_t>(token_start_internal_value_); + SetToken(CBORTokenTag::STRING16, token_start_length + length); + return; + } + case MajorType::ARRAY: + case MajorType::MAP: + case MajorType::TAG: + case MajorType::SIMPLE_VALUE: + SetError(Error::CBOR_UNSUPPORTED_VALUE); + return; + } + } + } +} + +void CBORTokenizer::SetToken(CBORTokenTag token_tag, + std::ptrdiff_t token_byte_length) { + token_tag_ = token_tag; + token_byte_length_ = token_byte_length; +} + +void CBORTokenizer::SetError(Error error) { + token_tag_ = CBORTokenTag::ERROR_VALUE; + status_.error = error; +} + +// ============================================================================= +// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages +// ============================================================================= + +namespace { +// When parsing CBOR, we limit recursion depth for objects and arrays +// to this constant. +static constexpr int kStackLimit = 1000; + +// Below are three parsing routines for CBOR, which cover enough +// to roundtrip JSON messages. +bool ParseMap(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); +bool ParseArray(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); +bool ParseValue(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out); + +void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) { + std::vector<uint16_t> value; + span<uint8_t> rep = tokenizer->GetString16WireRep(); + for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) + value.push_back((rep[ii + 1] << 8) | rep[ii]); + out->HandleString16(span<uint16_t>(value.data(), value.size())); + tokenizer->Next(); +} + +bool ParseUTF8String(CBORTokenizer* tokenizer, StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); + out->HandleString8(tokenizer->GetString8()); + tokenizer->Next(); + return true; +} + +bool ParseValue(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + if (stack_depth > kStackLimit) { + out->HandleError( + Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos}); + return false; + } + // Skip past the envelope to get to what's inside. + if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE) + tokenizer->EnterEnvelope(); + switch (tokenizer->TokenTag()) { + case CBORTokenTag::ERROR_VALUE: + out->HandleError(tokenizer->Status()); + return false; + case CBORTokenTag::DONE: + out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, + tokenizer->Status().pos}); + return false; + case CBORTokenTag::TRUE_VALUE: + out->HandleBool(true); + tokenizer->Next(); + return true; + case CBORTokenTag::FALSE_VALUE: + out->HandleBool(false); + tokenizer->Next(); + return true; + case CBORTokenTag::NULL_VALUE: + out->HandleNull(); + tokenizer->Next(); + return true; + case CBORTokenTag::INT32: + out->HandleInt32(tokenizer->GetInt32()); + tokenizer->Next(); + return true; + case CBORTokenTag::DOUBLE: + out->HandleDouble(tokenizer->GetDouble()); + tokenizer->Next(); + return true; + case CBORTokenTag::STRING8: + return ParseUTF8String(tokenizer, out); + case CBORTokenTag::STRING16: + ParseUTF16String(tokenizer, out); + return true; + case CBORTokenTag::BINARY: { + out->HandleBinary(tokenizer->GetBinary()); + tokenizer->Next(); + return true; + } + case CBORTokenTag::MAP_START: + return ParseMap(stack_depth + 1, tokenizer, out); + case CBORTokenTag::ARRAY_START: + return ParseArray(stack_depth + 1, tokenizer, out); + default: + out->HandleError( + Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos}); + return false; + } +} + +// |bytes| must start with the indefinite length array byte, so basically, +// ParseArray may only be called after an indefinite length array has been +// detected. +bool ParseArray(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START); + tokenizer->Next(); + out->HandleArrayBegin(); + while (tokenizer->TokenTag() != CBORTokenTag::STOP) { + if (tokenizer->TokenTag() == CBORTokenTag::DONE) { + out->HandleError( + Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos}); + return false; + } + if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer->Status()); + return false; + } + // Parse value. + if (!ParseValue(stack_depth, tokenizer, out)) + return false; + } + out->HandleArrayEnd(); + tokenizer->Next(); + return true; +} + +// |bytes| must start with the indefinite length array byte, so basically, +// ParseArray may only be called after an indefinite length array has been +// detected. +bool ParseMap(int32_t stack_depth, + CBORTokenizer* tokenizer, + StreamingParserHandler* out) { + assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START); + out->HandleMapBegin(); + tokenizer->Next(); + while (tokenizer->TokenTag() != CBORTokenTag::STOP) { + if (tokenizer->TokenTag() == CBORTokenTag::DONE) { + out->HandleError( + Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos}); + return false; + } + if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer->Status()); + return false; + } + // Parse key. + if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { + if (!ParseUTF8String(tokenizer, out)) + return false; + } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { + ParseUTF16String(tokenizer, out); + } else { + out->HandleError( + Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos}); + return false; + } + // Parse value. + if (!ParseValue(stack_depth, tokenizer, out)) + return false; + } + out->HandleMapEnd(); + tokenizer->Next(); + return true; +} +} // namespace + +void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out) { + if (bytes.empty()) { + out->HandleError(Status{Error::CBOR_NO_INPUT, 0}); + return; + } + if (bytes[0] != kInitialByteForEnvelope) { + out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0}); + return; + } + CBORTokenizer tokenizer(bytes); + if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer.Status()); + return; + } + // We checked for the envelope start byte above, so the tokenizer + // must agree here, since it's not an error. + assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE); + tokenizer.EnterEnvelope(); + if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) { + out->HandleError( + Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos}); + return; + } + if (!ParseMap(/*stack_depth=*/1, &tokenizer, out)) + return; + if (tokenizer.TokenTag() == CBORTokenTag::DONE) + return; + if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) { + out->HandleError(tokenizer.Status()); + return; + } + out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos}); +} +} // namespace cbor + +namespace json { + +// ============================================================================= +// json::NewJSONEncoder - for encoding streaming parser events as JSON +// ============================================================================= + +namespace { +// Prints |value| to |out| with 4 hex digits, most significant chunk first. +void PrintHex(uint16_t value, std::string* out) { + for (int ii = 3; ii >= 0; --ii) { + int four_bits = 0xf & (value >> (4 * ii)); + out->append(1, four_bits + ((four_bits <= 9) ? '0' : ('a' - 10))); + } +} + +// In the writer below, we maintain a stack of State instances. +// It is just enough to emit the appropriate delimiters and brackets +// in JSON. +enum class Container { + // Used for the top-level, initial state. + NONE, + // Inside a JSON object. + MAP, + // Inside a JSON array. + ARRAY +}; +class State { + public: + explicit State(Container container) : container_(container) {} + void StartElement(std::string* out) { + assert(container_ != Container::NONE || size_ == 0); + if (size_ != 0) { + char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':'; + out->append(1, delim); + } + ++size_; + } + Container container() const { return container_; } + + private: + Container container_ = Container::NONE; + int size_ = 0; +}; + +constexpr char kBase64Table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + +void Base64Encode(const span<uint8_t>& in, std::string* out) { + // The following three cases are based on the tables in the example + // section in https://en.wikipedia.org/wiki/Base64. We process three + // input bytes at a time, emitting 4 output bytes at a time. + std::ptrdiff_t ii = 0; + + // While possible, process three input bytes. + for (; ii + 3 <= in.size(); ii += 3) { + uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2]; + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); + out->push_back(kBase64Table[twentyfour_bits & 0x3f]); + } + if (ii + 2 <= in.size()) { // Process two input bytes. + uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8); + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]); + out->push_back('='); // Emit padding. + return; + } + if (ii + 1 <= in.size()) { // Process a single input byte. + uint32_t twentyfour_bits = (in[ii] << 16); + out->push_back(kBase64Table[(twentyfour_bits >> 18)]); + out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]); + out->push_back('='); // Emit padding. + out->push_back('='); // Emit padding. + } +} + +// Implements a handler for JSON parser events to emit a JSON string. +class JSONEncoder : public StreamingParserHandler { + public: + JSONEncoder(const Platform* platform, std::string* out, Status* status) + : platform_(platform), out_(out), status_(status) { + *status_ = Status(); + state_.emplace(Container::NONE); + } + + void HandleMapBegin() override { + if (!status_->ok()) + return; + assert(!state_.empty()); + state_.top().StartElement(out_); + state_.emplace(Container::MAP); + out_->append("{"); + } + + void HandleMapEnd() override { + if (!status_->ok()) + return; + assert(state_.size() >= 2 && state_.top().container() == Container::MAP); + state_.pop(); + out_->append("}"); + } + + void HandleArrayBegin() override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + state_.emplace(Container::ARRAY); + out_->append("["); + } + + void HandleArrayEnd() override { + if (!status_->ok()) + return; + assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY); + state_.pop(); + out_->append("]"); + } + + void HandleString16(span<uint16_t> chars) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + for (const uint16_t ch : chars) { + if (ch == '"') { + out_->append("\\\""); + } else if (ch == '\\') { + out_->append("\\\\"); + } else if (ch == '\b') { + out_->append("\\b"); + } else if (ch == '\f') { + out_->append("\\f"); + } else if (ch == '\n') { + out_->append("\\n"); + } else if (ch == '\r') { + out_->append("\\r"); + } else if (ch == '\t') { + out_->append("\\t"); + } else if (ch >= 32 && ch <= 126) { + out_->append(1, ch); + } else { + out_->append("\\u"); + PrintHex(ch, out_); + } + } + out_->append("\""); + } + + void HandleString8(span<uint8_t> chars) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) { + uint8_t c = chars[ii]; + if (c == '"') { + out_->append("\\\""); + } else if (c == '\\') { + out_->append("\\\\"); + } else if (c == '\b') { + out_->append("\\b"); + } else if (c == '\f') { + out_->append("\\f"); + } else if (c == '\n') { + out_->append("\\n"); + } else if (c == '\r') { + out_->append("\\r"); + } else if (c == '\t') { + out_->append("\\t"); + } else if (c >= 32 && c <= 126) { + out_->append(1, c); + } else if (c < 32) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(c), out_); + } else { + // Inspect the leading byte to figure out how long the utf8 + // byte sequence is; while doing this initialize |codepoint| + // with the first few bits. + // See table in: https://en.wikipedia.org/wiki/UTF-8 + // byte one is 110x xxxx -> 2 byte utf8 sequence + // byte one is 1110 xxxx -> 3 byte utf8 sequence + // byte one is 1111 0xxx -> 4 byte utf8 sequence + uint32_t codepoint; + int num_bytes_left; + if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence + num_bytes_left = 1; + codepoint = c & 0x1f; + } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence + num_bytes_left = 2; + codepoint = c & 0x0f; + } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence + codepoint = c & 0x07; + num_bytes_left = 3; + } else { + continue; // invalid leading byte + } + + // If we have enough bytes in our input, decode the remaining ones + // belonging to this Unicode character into |codepoint|. + if (ii + num_bytes_left > chars.size()) + continue; + while (num_bytes_left > 0) { + c = chars[++ii]; + --num_bytes_left; + // Check the next byte is a continuation byte, that is 10xx xxxx. + if ((c & 0xc0) != 0x80) + continue; + codepoint = (codepoint << 6) | (c & 0x3f); + } + + // Disallow overlong encodings for ascii characters, as these + // would include " and other characters significant to JSON + // string termination / control. + if (codepoint < 0x7f) + continue; + // Invalid in UTF8, and can't be represented in UTF16 anyway. + if (codepoint > 0x10ffff) + continue; + + // So, now we transcode to UTF16, + // using the math described at https://en.wikipedia.org/wiki/UTF-16, + // for either one or two 16 bit characters. + if (codepoint < 0xffff) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(codepoint), out_); + continue; + } + codepoint -= 0x10000; + // high surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_); + // low surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_); + } + } + out_->append("\""); + } + + void HandleBinary(span<uint8_t> bytes) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + Base64Encode(bytes, out_); + out_->append("\""); + } + + void HandleDouble(double value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + std::unique_ptr<char[]> str_value = platform_->DToStr(value); + + // DToStr may fail to emit a 0 before the decimal dot. E.g. this is + // the case in base::NumberToString in Chromium (which is based on + // dmg_fp). So, much like + // https://cs.chromium.org/chromium/src/base/json/json_writer.cc + // we probe for this and emit the leading 0 anyway if necessary. + const char* chars = str_value.get(); + if (chars[0] == '.') { + out_->append("0"); + } else if (chars[0] == '-' && chars[1] == '.') { + out_->append("-0"); + ++chars; + } + out_->append(chars); + } + + void HandleInt32(int32_t value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append(std::to_string(value)); + } + + void HandleBool(bool value) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append(value ? "true" : "false"); + } + + void HandleNull() override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("null"); + } + + void HandleError(Status error) override { + assert(!error.ok()); + *status_ = error; + out_->clear(); + } + + private: + const Platform* platform_; + std::string* out_; + Status* status_; + std::stack<State> state_; +}; +} // namespace + +std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform, + std::string* out, + Status* status) { + return std::unique_ptr<StreamingParserHandler>( + new JSONEncoder(platform, out, status)); +} + +// ============================================================================= +// json::ParseJSON - for receiving streaming parser events for JSON. +// ============================================================================= + +namespace { +const int kStackLimit = 1000; + +enum Token { + ObjectBegin, + ObjectEnd, + ArrayBegin, + ArrayEnd, + StringLiteral, + Number, + BoolTrue, + BoolFalse, + NullToken, + ListSeparator, + ObjectPairSeparator, + InvalidToken, + NoInput +}; + +const char* const kNullString = "null"; +const char* const kTrueString = "true"; +const char* const kFalseString = "false"; + +template <typename Char> +class JsonParser { + public: + JsonParser(const Platform* platform, StreamingParserHandler* handler) + : platform_(platform), handler_(handler) {} + + void Parse(const Char* start, std::size_t length) { + start_pos_ = start; + const Char* end = start + length; + const Char* tokenEnd; + ParseValue(start, end, &tokenEnd, 0); + if (tokenEnd != end) { + HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd); + } + } + + private: + bool CharsToDouble(const uint16_t* chars, + std::size_t length, + double* result) { + std::string buffer; + buffer.reserve(length + 1); + for (std::size_t ii = 0; ii < length; ++ii) { + bool is_ascii = !(chars[ii] & ~0x7F); + if (!is_ascii) + return false; + buffer.push_back(static_cast<char>(chars[ii])); + } + return platform_->StrToD(buffer.c_str(), result); + } + + bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) { + std::string buffer(reinterpret_cast<const char*>(chars), length); + return platform_->StrToD(buffer.c_str(), result); + } + + static bool ParseConstToken(const Char* start, + const Char* end, + const Char** token_end, + const char* token) { + // |token| is \0 terminated, it's one of the constants at top of the file. + while (start < end && *token != '\0' && *start++ == *token++) { + } + if (*token != '\0') + return false; + *token_end = start; + return true; + } + + static bool ReadInt(const Char* start, + const Char* end, + const Char** token_end, + bool allow_leading_zeros) { + if (start == end) + return false; + bool has_leading_zero = '0' == *start; + int length = 0; + while (start < end && '0' <= *start && *start <= '9') { + ++start; + ++length; + } + if (!length) + return false; + if (!allow_leading_zeros && length > 1 && has_leading_zero) + return false; + *token_end = start; + return true; + } + + static bool ParseNumberToken(const Char* start, + const Char* end, + const Char** token_end) { + // We just grab the number here. We validate the size in DecodeNumber. + // According to RFC4627, a valid number is: [minus] int [frac] [exp] + if (start == end) + return false; + Char c = *start; + if ('-' == c) + ++start; + + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false)) + return false; + if (start == end) { + *token_end = start; + return true; + } + + // Optional fraction part + c = *start; + if ('.' == c) { + ++start; + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) + return false; + if (start == end) { + *token_end = start; + return true; + } + c = *start; + } + + // Optional exponent part + if ('e' == c || 'E' == c) { + ++start; + if (start == end) + return false; + c = *start; + if ('-' == c || '+' == c) { + ++start; + if (start == end) + return false; + } + if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true)) + return false; + } + + *token_end = start; + return true; + } + + static bool ReadHexDigits(const Char* start, + const Char* end, + const Char** token_end, + int digits) { + if (end - start < digits) + return false; + for (int i = 0; i < digits; ++i) { + Char c = *start++; + if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'))) + return false; + } + *token_end = start; + return true; + } + + static bool ParseStringToken(const Char* start, + const Char* end, + const Char** token_end) { + while (start < end) { + Char c = *start++; + if ('\\' == c) { + if (start == end) + return false; + c = *start++; + // Make sure the escaped char is valid. + switch (c) { + case 'x': + if (!ReadHexDigits(start, end, &start, 2)) + return false; + break; + case 'u': + if (!ReadHexDigits(start, end, &start, 4)) + return false; + break; + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '"': + break; + default: + return false; + } + } else if ('"' == c) { + *token_end = start; + return true; + } + } + return false; + } + + static bool SkipComment(const Char* start, + const Char* end, + const Char** comment_end) { + if (start == end) + return false; + + if (*start != '/' || start + 1 >= end) + return false; + ++start; + + if (*start == '/') { + // Single line comment, read to newline. + for (++start; start < end; ++start) { + if (*start == '\n' || *start == '\r') { + *comment_end = start + 1; + return true; + } + } + *comment_end = end; + // Comment reaches end-of-input, which is fine. + return true; + } + + if (*start == '*') { + Char previous = '\0'; + // Block comment, read until end marker. + for (++start; start < end; previous = *start++) { + if (previous == '*' && *start == '/') { + *comment_end = start + 1; + return true; + } + } + // Block comment must close before end-of-input. + return false; + } + + return false; + } + + static bool IsSpaceOrNewLine(Char c) { + // \v = vertial tab; \f = form feed page break. + return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || + c == '\t'; + } + + static void SkipWhitespaceAndComments(const Char* start, + const Char* end, + const Char** whitespace_end) { + while (start < end) { + if (IsSpaceOrNewLine(*start)) { + ++start; + } else if (*start == '/') { + const Char* comment_end; + if (!SkipComment(start, end, &comment_end)) + break; + start = comment_end; + } else { + break; + } + } + *whitespace_end = start; + } + + static Token ParseToken(const Char* start, + const Char* end, + const Char** tokenStart, + const Char** token_end) { + SkipWhitespaceAndComments(start, end, tokenStart); + start = *tokenStart; + + if (start == end) + return NoInput; + + switch (*start) { + case 'n': + if (ParseConstToken(start, end, token_end, kNullString)) + return NullToken; + break; + case 't': + if (ParseConstToken(start, end, token_end, kTrueString)) + return BoolTrue; + break; + case 'f': + if (ParseConstToken(start, end, token_end, kFalseString)) + return BoolFalse; + break; + case '[': + *token_end = start + 1; + return ArrayBegin; + case ']': + *token_end = start + 1; + return ArrayEnd; + case ',': + *token_end = start + 1; + return ListSeparator; + case '{': + *token_end = start + 1; + return ObjectBegin; + case '}': + *token_end = start + 1; + return ObjectEnd; + case ':': + *token_end = start + 1; + return ObjectPairSeparator; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + if (ParseNumberToken(start, end, token_end)) + return Number; + break; + case '"': + if (ParseStringToken(start + 1, end, token_end)) + return StringLiteral; + break; + } + return InvalidToken; + } + + static int HexToInt(Char c) { + if ('0' <= c && c <= '9') + return c - '0'; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + assert(false); // Unreachable. + return 0; + } + + static bool DecodeString(const Char* start, + const Char* end, + std::vector<uint16_t>* output) { + if (start == end) + return true; + if (start > end) + return false; + output->reserve(end - start); + while (start < end) { + uint16_t c = *start++; + // If the |Char| we're dealing with is really a byte, then + // we have utf8 here, and we need to check for multibyte characters + // and transcode them to utf16 (either one or two utf16 chars). + if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) { + // Inspect the leading byte to figure out how long the utf8 + // byte sequence is; while doing this initialize |codepoint| + // with the first few bits. + // See table in: https://en.wikipedia.org/wiki/UTF-8 + // byte one is 110x xxxx -> 2 byte utf8 sequence + // byte one is 1110 xxxx -> 3 byte utf8 sequence + // byte one is 1111 0xxx -> 4 byte utf8 sequence + uint32_t codepoint; + int num_bytes_left; + if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence + num_bytes_left = 1; + codepoint = c & 0x1f; + } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence + num_bytes_left = 2; + codepoint = c & 0x0f; + } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence + codepoint = c & 0x07; + num_bytes_left = 3; + } else { + return false; // invalid leading byte + } + + // If we have enough bytes in our inpput, decode the remaining ones + // belonging to this Unicode character into |codepoint|. + if (start + num_bytes_left > end) + return false; + while (num_bytes_left > 0) { + c = *start++; + --num_bytes_left; + // Check the next byte is a continuation byte, that is 10xx xxxx. + if ((c & 0xc0) != 0x80) + return false; + codepoint = (codepoint << 6) | (c & 0x3f); + } + + // Disallow overlong encodings for ascii characters, as these + // would include " and other characters significant to JSON + // string termination / control. + if (codepoint < 0x7f) + return false; + // Invalid in UTF8, and can't be represented in UTF16 anyway. + if (codepoint > 0x10ffff) + return false; + + // So, now we transcode to UTF16, + // using the math described at https://en.wikipedia.org/wiki/UTF-16, + // for either one or two 16 bit characters. + if (codepoint < 0xffff) { + output->push_back(codepoint); + continue; + } + codepoint -= 0x10000; + output->push_back((codepoint >> 10) + 0xd800); // high surrogate + output->push_back((codepoint & 0x3ff) + 0xdc00); // low surrogate + continue; + } + if ('\\' != c) { + output->push_back(c); + continue; + } + if (start == end) + return false; + c = *start++; + + if (c == 'x') { + // \x is not supported. + return false; + } + + switch (c) { + case '"': + case '/': + case '\\': + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'u': + c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) + + (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3)); + start += 4; + break; + default: + return false; + } + output->push_back(c); + } + return true; + } + + void ParseValue(const Char* start, + const Char* end, + const Char** value_token_end, + int depth) { + if (depth > kStackLimit) { + HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start); + return; + } + const Char* token_start; + const Char* token_end; + Token token = ParseToken(start, end, &token_start, &token_end); + switch (token) { + case NoInput: + HandleError(Error::JSON_PARSER_NO_INPUT, token_start); + return; + case InvalidToken: + HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start); + return; + case NullToken: + handler_->HandleNull(); + break; + case BoolTrue: + handler_->HandleBool(true); + break; + case BoolFalse: + handler_->HandleBool(false); + break; + case Number: { + double value; + if (!CharsToDouble(token_start, token_end - token_start, &value)) { + HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start); + return; + } + if (value >= std::numeric_limits<int32_t>::min() && + value <= std::numeric_limits<int32_t>::max() && + static_cast<int32_t>(value) == value) + handler_->HandleInt32(static_cast<int32_t>(value)); + else + handler_->HandleDouble(value); + break; + } + case StringLiteral: { + std::vector<uint16_t> value; + bool ok = DecodeString(token_start + 1, token_end - 1, &value); + if (!ok) { + HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); + return; + } + handler_->HandleString16(span<uint16_t>(value.data(), value.size())); + break; + } + case ArrayBegin: { + handler_->HandleArrayBegin(); + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + while (token != ArrayEnd) { + ParseValue(start, end, &token_end, depth + 1); + if (error_) + return; + + // After a list value, we expect a comma or the end of the list. + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ListSeparator) { + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ArrayEnd) { + HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start); + return; + } + } else if (token != ArrayEnd) { + // Unexpected value after list value. Bail out. + HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, + token_start); + return; + } + } + handler_->HandleArrayEnd(); + break; + } + case ObjectBegin: { + handler_->HandleMapBegin(); + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + while (token != ObjectEnd) { + if (token != StringLiteral) { + HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, + token_start); + return; + } + std::vector<uint16_t> key; + if (!DecodeString(token_start + 1, token_end - 1, &key)) { + HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); + return; + } + handler_->HandleString16(span<uint16_t>(key.data(), key.size())); + start = token_end; + + token = ParseToken(start, end, &token_start, &token_end); + if (token != ObjectPairSeparator) { + HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start); + return; + } + start = token_end; + + ParseValue(start, end, &token_end, depth + 1); + if (error_) + return; + start = token_end; + + // After a key/value pair, we expect a comma or the end of the + // object. + token = ParseToken(start, end, &token_start, &token_end); + if (token == ListSeparator) { + start = token_end; + token = ParseToken(start, end, &token_start, &token_end); + if (token == ObjectEnd) { + HandleError(Error::JSON_PARSER_UNEXPECTED_MAP_END, token_start); + return; + } + } else if (token != ObjectEnd) { + // Unexpected value after last object value. Bail out. + HandleError(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, + token_start); + return; + } + } + handler_->HandleMapEnd(); + break; + } + + default: + // We got a token that's not a value. + HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start); + return; + } + + SkipWhitespaceAndComments(token_end, end, value_token_end); + } + + void HandleError(Error error, const Char* pos) { + assert(error != Error::OK); + if (!error_) { + handler_->HandleError(Status{error, pos - start_pos_}); + error_ = true; + } + } + + const Char* start_pos_ = nullptr; + bool error_ = false; + const Platform* platform_; + StreamingParserHandler* handler_; +}; +} // namespace + +void ParseJSON(const Platform* platform, + span<uint8_t> chars, + StreamingParserHandler* handler) { + JsonParser<uint8_t> parser(platform, handler); + parser.Parse(chars.data(), chars.size()); +} + +void ParseJSON(const Platform* platform, + span<uint16_t> chars, + StreamingParserHandler* handler) { + JsonParser<uint16_t> parser(platform, handler); + parser.Parse(chars.data(), chars.size()); +} +} // namespace json + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} +
diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/lib/encoding_h.template similarity index 65% copy from third_party/inspector_protocol/lib/CBOR_h.template copy to third_party/inspector_protocol/lib/encoding_h.template index 9d28adb..aba28c8 100644 --- a/third_party/inspector_protocol/lib/CBOR_h.template +++ b/third_party/inspector_protocol/lib/encoding_h.template
@@ -1,75 +1,29 @@ {# This template is generated by gen_cbor_templates.py. #} -// Generated by lib/CBOR_h.template. +// Generated by lib/encoding_h.template. // Copyright 2019 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 {{"_".join(config.protocol.namespace)}}_CBOR_h -#define {{"_".join(config.protocol.namespace)}}_CBOR_h +#ifndef {{"_".join(config.protocol.namespace)}}_encoding_h +#define {{"_".join(config.protocol.namespace)}}_encoding_h #include <cstddef> #include <cstdint> #include <memory> +#include <string> #include <vector> {% for namespace in config.protocol.namespace %} namespace {{namespace}} { {% endfor %} -// ===== encoding/status.h ===== +// ===== encoding/encoding.h ===== -// Error codes. -enum class Error { - OK = 0, - // JSON parsing errors - json_parser.{h,cc}. - JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01, - JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02, - JSON_PARSER_NO_INPUT = 0x03, - JSON_PARSER_INVALID_TOKEN = 0x04, - JSON_PARSER_INVALID_NUMBER = 0x05, - JSON_PARSER_INVALID_STRING = 0x06, - JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07, - JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08, - JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09, - JSON_PARSER_COLON_EXPECTED = 0x0a, - JSON_PARSER_UNEXPECTED_OBJECT_END = 0x0b, - JSON_PARSER_COMMA_OR_OBJECT_END_EXPECTED = 0x0c, - JSON_PARSER_VALUE_EXPECTED = 0x0d, - CBOR_INVALID_INT32 = 0x0e, - CBOR_INVALID_DOUBLE = 0x0f, - CBOR_INVALID_ENVELOPE = 0x10, - CBOR_INVALID_STRING8 = 0x11, - CBOR_INVALID_STRING16 = 0x12, - CBOR_INVALID_BINARY = 0x13, - CBOR_UNSUPPORTED_VALUE = 0x14, - CBOR_NO_INPUT = 0x15, - CBOR_INVALID_START_BYTE = 0x16, - CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17, - CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18, - CBOR_UNEXPECTED_EOF_IN_MAP = 0x19, - CBOR_INVALID_MAP_KEY = 0x1a, - CBOR_STACK_LIMIT_EXCEEDED = 0x1b, - CBOR_STRING8_MUST_BE_7BIT = 0x1c, - CBOR_TRAILING_JUNK = 0x1d, - CBOR_MAP_START_EXPECTED = 0x1e, -}; - -// A status value with position that can be copied. The default status -// is OK. Usually, error status values should come with a valid position. -struct Status { - static constexpr std::ptrdiff_t npos() { return -1; } - - bool ok() const { return error == Error::OK; } - - Error error = Error::OK; - std::ptrdiff_t pos = npos(); - Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {} - Status() = default; -}; - -// ===== encoding/span.h ===== +// ============================================================================= +// span - sequence of bytes +// ============================================================================= // This template is similar to std::span, which will be included in C++20. Like // std::span it uses ptrdiff_t, which is signed (and thus a bit annoying @@ -107,19 +61,78 @@ index_type size_; }; -// ===== encoding/json_parser_handler.h ===== +template <typename T> +span<T> SpanFromVector(const std::vector<T>& v) { + return span<T>(v.data(), v.size()); +} -// Handler interface for JSON parser events. See also json_parser.h. -class JSONParserHandler { +inline span<uint8_t> SpanFromStdString(const std::string& v) { + return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size()); +} + +// Error codes. +enum class Error { + OK = 0, + // JSON parsing errors - json_parser.{h,cc}. + JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01, + JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02, + JSON_PARSER_NO_INPUT = 0x03, + JSON_PARSER_INVALID_TOKEN = 0x04, + JSON_PARSER_INVALID_NUMBER = 0x05, + JSON_PARSER_INVALID_STRING = 0x06, + JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07, + JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08, + JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09, + JSON_PARSER_COLON_EXPECTED = 0x0a, + JSON_PARSER_UNEXPECTED_MAP_END = 0x0b, + JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c, + JSON_PARSER_VALUE_EXPECTED = 0x0d, + + CBOR_INVALID_INT32 = 0x0e, + CBOR_INVALID_DOUBLE = 0x0f, + CBOR_INVALID_ENVELOPE = 0x10, + CBOR_INVALID_STRING8 = 0x11, + CBOR_INVALID_STRING16 = 0x12, + CBOR_INVALID_BINARY = 0x13, + CBOR_UNSUPPORTED_VALUE = 0x14, + CBOR_NO_INPUT = 0x15, + CBOR_INVALID_START_BYTE = 0x16, + CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17, + CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18, + CBOR_UNEXPECTED_EOF_IN_MAP = 0x19, + CBOR_INVALID_MAP_KEY = 0x1a, + CBOR_STACK_LIMIT_EXCEEDED = 0x1b, + CBOR_STRING8_MUST_BE_7BIT = 0x1c, + CBOR_TRAILING_JUNK = 0x1d, + CBOR_MAP_START_EXPECTED = 0x1e, +}; + +// A status value with position that can be copied. The default status +// is OK. Usually, error status values should come with a valid position. +struct Status { + static constexpr std::ptrdiff_t npos() { return -1; } + + bool ok() const { return error == Error::OK; } + + Error error = Error::OK; + std::ptrdiff_t pos = npos(); + Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {} + Status() = default; +}; + +// Handler interface for parser events emitted by a streaming parser. +// See cbor::NewCBOREncoder, cbor::ParseCBOR, json::NewJSONEncoder, +// json::ParseJSON. +class StreamingParserHandler { public: - virtual ~JSONParserHandler() = default; - virtual void HandleObjectBegin() = 0; - virtual void HandleObjectEnd() = 0; + virtual ~StreamingParserHandler() = default; + virtual void HandleMapBegin() = 0; + virtual void HandleMapEnd() = 0; virtual void HandleArrayBegin() = 0; virtual void HandleArrayEnd() = 0; virtual void HandleString8(span<uint8_t> chars) = 0; virtual void HandleString16(span<uint16_t> chars) = 0; - virtual void HandleBinary(std::vector<uint8_t> bytes) = 0; + virtual void HandleBinary(span<uint8_t> bytes) = 0; virtual void HandleDouble(double value) = 0; virtual void HandleInt32(int32_t value) = 0; virtual void HandleBool(bool value) = 0; @@ -132,97 +145,7 @@ virtual void HandleError(Status error) = 0; }; -// ===== encoding/cbor_internals.h ===== - namespace cbor { -enum class MajorType; -} - -namespace cbor_internals { - -// Reads the start of a token with definitive size from |bytes|. -// |type| is the major type as specified in RFC 7049 Section 2.1. -// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size -// (e.g. for BYTE_STRING). -// If successful, returns the number of bytes read. Otherwise returns -1. -int8_t ReadTokenStart(span<uint8_t> bytes, cbor::MajorType* type, - uint64_t* value); - -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(cbor::MajorType type, uint64_t value, - std::vector<uint8_t>* encoded); -} // namespace cbor_internals - -// ===== encoding/cbor.h ===== - - -namespace cbor { - -// The major types from RFC 7049 Section 2.1. -enum class MajorType { - UNSIGNED = 0, - NEGATIVE = 1, - BYTE_STRING = 2, - STRING = 3, - ARRAY = 4, - MAP = 5, - TAG = 6, - SIMPLE_VALUE = 7 -}; - -// Indicates the number of bits the "initial byte" needs to be shifted to the -// right after applying |kMajorTypeMask| to produce the major type in the -// lowermost bits. -static constexpr uint8_t kMajorTypeBitShift = 5u; -// Mask selecting the low-order 5 bits of the "initial byte", which is where -// the additional information is encoded. -static constexpr uint8_t kAdditionalInformationMask = 0x1f; -// Mask selecting the high-order 3 bits of the "initial byte", which indicates -// the major type of the encoded value. -static constexpr uint8_t kMajorTypeMask = 0xe0; -// Indicates the integer is in the following byte. -static constexpr uint8_t kAdditionalInformation1Byte = 24u; -// Indicates the integer is in the next 2 bytes. -static constexpr uint8_t kAdditionalInformation2Bytes = 25u; -// Indicates the integer is in the next 4 bytes. -static constexpr uint8_t kAdditionalInformation4Bytes = 26u; -// Indicates the integer is in the next 8 bytes. -static constexpr uint8_t kAdditionalInformation8Bytes = 27u; - -// Encodes the initial byte, consisting of the |type| in the first 3 bits -// followed by 5 bits of |additional_info|. -constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { - return (static_cast<uint8_t>(type) << kMajorTypeBitShift) | - (additional_info & kAdditionalInformationMask); -} - -// TAG 24 indicates that what follows is a byte string which is -// encoded in CBOR format. We use this as a wrapper for -// maps and arrays, allowing us to skip them, because the -// byte string carries its size (byte length). -// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 -static constexpr uint8_t kInitialByteForEnvelope = - EncodeInitialByte(MajorType::TAG, 24); -// The initial byte for a byte string with at most 2^32 bytes -// of payload. This is used for envelope encoding, even if -// the byte string is shorter. -static constexpr uint8_t kInitialByteFor32BitLengthByteString = - EncodeInitialByte(MajorType::BYTE_STRING, 26); - -// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional -// info = 31. -static constexpr uint8_t kInitialByteIndefiniteLengthArray = - EncodeInitialByte(MajorType::ARRAY, 31); -static constexpr uint8_t kInitialByteIndefiniteLengthMap = - EncodeInitialByte(MajorType::MAP, 31); -// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite -// length maps / arrays. -static constexpr uint8_t kStopByte = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); - -} // namespace cbor - // The binary encoding for the inspector protocol follows the CBOR specification // (RFC 7049). Additional constraints: // - Only indefinite length maps and arrays are supported. @@ -239,12 +162,38 @@ // as CBOR BYTE_STRING (major type 2). For such strings, the number of // bytes encoded must be even. // - UTF8 strings (major type 3) are supported. -// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not +// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, never // as UTF16 strings. // - Arbitrary byte arrays, in the inspector protocol called 'binary', // are encoded as BYTE_STRING (major type 2), prefixed with a byte // indicating base64 when rendered as JSON. +// ============================================================================= +// Detecting CBOR content +// ============================================================================= + +// The first byte for an envelope, which we use for wrapping dictionaries +// and arrays; and the byte that indicates a byte string with 32 bit length. +// These two bytes start an envelope, and thereby also any CBOR message +// produced or consumed by this protocol. See also |EnvelopeEncoder| below. +uint8_t InitialByteForEnvelope(); +uint8_t InitialByteFor32BitLengthByteString(); + +// Checks whether |msg| is a cbor message. +bool IsCBORMessage(span<uint8_t> msg); + +// ============================================================================= +// Encoding individual CBOR items +// ============================================================================= + +// Some constants for CBOR tokens that only take a single byte on the wire. +uint8_t EncodeTrue(); +uint8_t EncodeFalse(); +uint8_t EncodeNull(); +uint8_t EncodeIndefiniteLengthArrayStart(); +uint8_t EncodeIndefiniteLengthMapStart(); +uint8_t EncodeStop(); + // Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE| // (major type 1) iff < 0. void EncodeInt32(int32_t value, std::vector<uint8_t>* out); @@ -275,13 +224,9 @@ // with additional info = 27, followed by 8 bytes in big endian. void EncodeDouble(double value, std::vector<uint8_t>* out); -// Some constants for CBOR tokens that only take a single byte on the wire. -uint8_t EncodeTrue(); -uint8_t EncodeFalse(); -uint8_t EncodeNull(); -uint8_t EncodeIndefiniteLengthArrayStart(); -uint8_t EncodeIndefiniteLengthMapStart(); -uint8_t EncodeStop(); +// ============================================================================= +// cbor::EnvelopeEncoder - for wrapping submessages +// ============================================================================= // An envelope indicates the byte length of a wrapped item. // We use this for maps and array, which allows the decoder @@ -304,20 +249,23 @@ std::size_t byte_size_pos_ = 0; }; -// This can be used to convert from JSON to CBOR, by passing the -// return value to the routines in json_parser.h. The handler will encode into -// |out|, and iff an error occurs it will set |status| to an error and clear -// |out|. Otherwise, |status.ok()| will be |true|. -std::unique_ptr<JSONParserHandler> NewJSONToCBOREncoder( - std::vector<uint8_t>* out, Status* status); +// ============================================================================= +// cbor::NewCBOREncoder - for encoding from a streaming parser +// ============================================================================= -// Parses a CBOR encoded message from |bytes|, sending JSON events to -// |json_out|. If an error occurs, sends |out->HandleError|, and parsing stops. -// The client is responsible for discarding the already received information in -// that case. -void ParseCBOR(span<uint8_t> bytes, JSONParserHandler* json_out); +// This can be used to convert to CBOR, by passing the return value to a parser +// that drives it. The handler will encode into |out|, and iff an error occurs +// it will set |status| to an error and clear |out|. Otherwise, |status.ok()| +// will be |true|. +std::unique_ptr<StreamingParserHandler> NewCBOREncoder( + std::vector<uint8_t>* out, + Status* status); -// Tags for the tokens within a CBOR message that CBORStream understands. +// ============================================================================= +// cbor::CBORTokenizer - for parsing individual CBOR items +// ============================================================================= + +// Tags for the tokens within a CBOR message that CBORTokenizer understands. // Note that this is not the same terminology as the CBOR spec (RFC 7049), // but rather, our adaptation. For instance, we lump unsigned and signed // major type into INT32 here (and disallow values outside the int32_t range). @@ -357,6 +305,18 @@ DONE, }; +// The major types from RFC 7049 Section 2.1. +enum class MajorType { + UNSIGNED = 0, + NEGATIVE = 1, + BYTE_STRING = 2, + STRING = 3, + ARRAY = 4, + MAP = 5, + TAG = 6, + SIMPLE_VALUE = 7 +}; + // CBORTokenizer segments a CBOR message, presenting the tokens therein as // numbers, strings, etc. This is not a complete CBOR parser, but makes it much // easier to implement one (e.g. ParseCBOR, above). It can also be used to parse @@ -403,6 +363,9 @@ // To be called only if ::TokenTag() == CBORTokenTag::BINARY. span<uint8_t> GetBinary() const; + // To be called only if ::TokenTag() == CBORTokenTag::ENVELOPE. + span<uint8_t> GetEnvelopeContents() const; + private: void ReadNextToken(bool enter_envelope); void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length); @@ -412,14 +375,72 @@ CBORTokenTag token_tag_; struct Status status_; std::ptrdiff_t token_byte_length_; - cbor::MajorType token_start_type_; + MajorType token_start_type_; uint64_t token_start_internal_value_; }; -void DumpCBOR(span<uint8_t> cbor); +// ============================================================================= +// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages +// ============================================================================= +// Parses a CBOR encoded message from |bytes|, sending events to +// |out|. If an error occurs, sends |out->HandleError|, and parsing stops. +// The client is responsible for discarding the already received information in +// that case. +void ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out); + +namespace internals { // Exposed only for writing tests. +int8_t ReadTokenStart(span<uint8_t> bytes, + cbor::MajorType* type, + uint64_t* value); + +void WriteTokenStart(cbor::MajorType type, + uint64_t value, + std::vector<uint8_t>* encoded); +} // namespace internals +} // namespace cbor + +namespace json { +// Client code must provide an instance. Implementation should delegate +// to whatever is appropriate. +class Platform { + public: + virtual ~Platform() = default; + // Parses |str| into |result|. Returns false iff there are + // leftover characters or parsing errors. + virtual bool StrToD(const char* str, double* result) const = 0; + + // Prints |value| in a format suitable for JSON. + virtual std::unique_ptr<char[]> DToStr(double value) const = 0; +}; + +// ============================================================================= +// json::NewJSONEncoder - for encoding streaming parser events as JSON +// ============================================================================= + +// Returns a handler object which will write ascii characters to |out|. +// |status->ok()| will be false iff the handler routine HandleError() is called. +// In that case, we'll stop emitting output. +// Except for calling the HandleError routine at any time, the client +// code must call the Handle* methods in an order in which they'd occur +// in valid JSON; otherwise we may crash (the code uses assert). +std::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform, + std::string* out, + Status* status); + +// ============================================================================= +// json::ParseJSON - for receiving streaming parser events for JSON +// ============================================================================= + +void ParseJSON(const Platform* platform, + span<uint8_t> chars, + StreamingParserHandler* handler); +void ParseJSON(const Platform* platform, + span<uint16_t> chars, + StreamingParserHandler* handler); +} // namespace json {% for namespace in config.protocol.namespace %} } // namespace {{namespace}} {% endfor %} -#endif // !defined({{"_".join(config.protocol.namespace)}}_CBOR_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_encoding_h)
diff --git a/third_party/inspector_protocol/roll.py b/third_party/inspector_protocol/roll.py index 59699e6..deb1b28 100755 --- a/third_party/inspector_protocol/roll.py +++ b/third_party/inspector_protocol/roll.py
@@ -13,7 +13,6 @@ FILES_TO_SYNC = [ - 'BUILD.gn', 'README.md', 'check_protocol_compatibility.py', 'code_generator.py',
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 331f07e5..f6bf534 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Thursday March 07 2019 +Date: Thursday March 14 2019 Branch: master -Commit: 8256c8b297c8b7c7ee4de24edff82ed67d6ef207 +Commit: 1533bd84f12e5b24b5c2e41d1729942c7aa218ad Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index 13614df..376acb9 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -444,8 +444,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/variance_sse2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_4t_intrin_sse2.c", ] -libvpx_srcs_x86_sse3 = [ -] +libvpx_srcs_x86_sse3 = [] libvpx_srcs_x86_ssse3 = [ "//third_party/libvpx/source/libvpx/vp8/encoder/x86/vp8_quantize_ssse3.c", "//third_party/libvpx/source/libvpx/vp9/encoder/x86/vp9_dct_ssse3.c", @@ -481,8 +480,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/variance_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_intrin_avx2.c", ] -libvpx_srcs_x86_avx512 = [ -] +libvpx_srcs_x86_avx512 = [] libvpx_srcs_x86_64 = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -897,9 +895,8 @@ "//third_party/libvpx/source/libvpx/vpx_ports/emms_mmx.asm", "//third_party/libvpx/source/libvpx/vpx_ports/float_control_word.asm", ] -libvpx_srcs_x86_64_mmx = [ - "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_mmx.c", -] +libvpx_srcs_x86_64_mmx = + [ "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_mmx.c" ] libvpx_srcs_x86_64_sse2 = [ "//third_party/libvpx/source/libvpx/vp8/common/x86/bilinear_filter_sse2.c", "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_sse2.c", @@ -930,8 +927,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/variance_sse2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_4t_intrin_sse2.c", ] -libvpx_srcs_x86_64_sse3 = [ -] +libvpx_srcs_x86_64_sse3 = [] libvpx_srcs_x86_64_ssse3 = [ "//third_party/libvpx/source/libvpx/vp8/encoder/x86/vp8_quantize_ssse3.c", "//third_party/libvpx/source/libvpx/vp9/encoder/x86/vp9_dct_ssse3.c", @@ -967,8 +963,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/variance_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_intrin_avx2.c", ] -libvpx_srcs_x86_64_avx512 = [ -] +libvpx_srcs_x86_64_avx512 = [] libvpx_srcs_arm = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -1311,8 +1306,7 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_arm_assembly = [ -] +libvpx_srcs_arm_assembly = [] libvpx_srcs_arm_neon = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -2570,8 +2564,7 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_arm64_assembly = [ -] +libvpx_srcs_arm64_assembly = [] libvpx_srcs_arm_neon_highbd = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -3436,8 +3429,7 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_arm64_highbd_assembly = [ -] +libvpx_srcs_arm64_highbd_assembly = [] libvpx_srcs_mips = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -3779,8 +3771,7 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_mips_assembly = [ -] +libvpx_srcs_mips_assembly = [] libvpx_srcs_nacl = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -4121,8 +4112,7 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_nacl_assembly = [ -] +libvpx_srcs_nacl_assembly = [] libvpx_srcs_generic = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.h", @@ -4463,5 +4453,4 @@ "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.c", "//third_party/libvpx/source/libvpx/vpx_util/vpx_write_yuv_frame.h", ] -libvpx_srcs_generic_assembly = [ -] +libvpx_srcs_generic_assembly = []
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index bde94740..72e4d8ce 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 8 #define VERSION_PATCH 0 -#define VERSION_EXTRA "207-g8256c8b29" +#define VERSION_EXTRA "239-g1533bd84f" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.8.0-207-g8256c8b29" -#define VERSION_STRING " v1.8.0-207-g8256c8b29" +#define VERSION_STRING_NOSP "v1.8.0-239-g1533bd84f" +#define VERSION_STRING " v1.8.0-239-g1533bd84f"
diff --git a/third_party/protobuf/proto_library.gni b/third_party/protobuf/proto_library.gni index 7d470ca6..bf22f7b 100644 --- a/third_party/protobuf/proto_library.gni +++ b/third_party/protobuf/proto_library.gni
@@ -56,6 +56,10 @@ # generator_plugin_options (optional) # Extra flags passed to the plugin. See cc_generator_options. # +# deps (optional) +# DEPRECATED: use proto_deps or link_deps instead (crbug.com/938011). +# Additional dependencies. +# # link_deps (optional) # Additional dependencies linked to library. # @@ -323,6 +327,9 @@ if (defined(invoker.proto_deps)) { deps += invoker.proto_deps } + if (defined(invoker.deps)) { + deps += invoker.deps + } } # Option to disable building a library in component build. @@ -414,6 +421,9 @@ # This will link any libraries in the deps (the use of invoker.deps in the # action won't link it). + if (defined(invoker.deps)) { + deps += invoker.deps + } if (defined(invoker.link_deps)) { deps += invoker.link_deps }
diff --git a/tools/cfi/blacklist.txt b/tools/cfi/blacklist.txt index 8ebf793..273b8788 100644 --- a/tools/cfi/blacklist.txt +++ b/tools/cfi/blacklist.txt
@@ -122,6 +122,7 @@ # ANGLE src:*third_party/angle/src/libANGLE/* +src:*third_party/angle/src/libEGL/* src:*third_party/angle/src/third_party/libXNVCtrl/NVCtrl.c # third_party/angle/src/gpu_info_util/SystemInfo_libpci.cpp fun:*GetPCIDevicesWithLibPCI*
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index a9e1a04..a3a2f28d 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -7,6 +7,8 @@ It is also used by package.py to build the prebuilt clang binaries.""" +from __future__ import print_function + import argparse import distutils.spawn import glob @@ -20,7 +22,13 @@ import tarfile import tempfile import time -import urllib2 + +try: + import urllib2 as urllib +except ImportError: # For Py3 compatibility + import urllib.request as urllib + import urllib.error as urllib + import zipfile @@ -95,7 +103,7 @@ try: sys.stdout.write('Downloading %s ' % url) sys.stdout.flush() - response = urllib2.urlopen(url) + response = urllib.urlopen(url) total_size = int(response.info().getheader('Content-Length').strip()) bytes_done = 0 dots_printed = 0 @@ -110,17 +118,17 @@ sys.stdout.flush() dots_printed = num_dots if bytes_done != total_size: - raise urllib2.URLError("only got %d of %d bytes" % - (bytes_done, total_size)) - print ' Done.' + raise urllib.URLError("only got %d of %d bytes" % + (bytes_done, total_size)) + print(' Done.') return - except urllib2.URLError as e: + except urllib.URLError as e: sys.stdout.write('\n') - print e - if num_retries == 0 or isinstance(e, urllib2.HTTPError) and e.code == 404: + print(e) + if num_retries == 0 or isinstance(e, urllib.HTTPError) and e.code == 404: raise e num_retries -= 1 - print 'Retrying in %d s ...' % retry_wait_s + print('Retrying in %d s ...' % retry_wait_s) time.sleep(retry_wait_s) retry_wait_s *= 2 @@ -218,10 +226,10 @@ # do the single-string transformation there. if sys.platform != 'win32': command = ' '.join([pipes.quote(c) for c in command]) - print 'Running', command + print('Running', command) if subprocess.call(command, env=env, shell=True) == 0: return True - print 'Failed.' + print('Failed.') if fail_hard: sys.exit(1) return False @@ -229,7 +237,7 @@ def CopyFile(src, dst): """Copy a file from src to dst.""" - print "Copying %s to %s" % (src, dst) + print("Copying %s to %s" % (src, dst)) shutil.copy(src, dst) @@ -243,17 +251,17 @@ def Checkout(name, url, dir): """Checkout the SVN module at url into dir. Use name for the log message.""" - print "Checking out %s r%s into '%s'" % (name, CLANG_REVISION, dir) + print("Checking out %s r%s into '%s'" % (name, CLANG_REVISION, dir)) command = ['svn', 'checkout', '--force', url + '@' + CLANG_REVISION, dir] if RunCommand(command, fail_hard=False): return if os.path.isdir(dir): - print "Removing %s." % (dir) + print("Removing %s." % dir) RmTree(dir) - print "Retrying." + print("Retrying.") RunCommand(command) @@ -350,7 +358,7 @@ GNUWIN_VERSION = '9' GNUWIN_STAMP = os.path.join(gnuwin_dir, 'stamp') if ReadStampFile(GNUWIN_STAMP) == GNUWIN_VERSION: - print 'GNU Win tools already up to date.' + print('GNU Win tools already up to date.') else: zip_name = 'gnuwin-%s.zip' % GNUWIN_VERSION DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR) @@ -439,8 +447,8 @@ version_out = subprocess.check_output([clang, '--version']) version_out = re.match(r'clang version ([0-9.]+)', version_out).group(1) if version_out != VERSION: - print ('unexpected clang version %s (not %s), update VERSION in update.py' - % (version_out, VERSION)) + print('unexpected clang version %s (not %s), update VERSION in update.py' + % (version_out, VERSION)) sys.exit(1) @@ -461,10 +469,10 @@ if runtimes_only: path_prefix = 'lib/clang/' + VERSION + '/lib/' DownloadAndUnpack(cds_full_url, LLVM_BUILD_DIR, path_prefix) - except urllib2.URLError: - print 'Failed to download prebuilt clang %s' % cds_file - print 'Use --force-local-build if you want to build locally.' - print 'Exiting.' + except urllib.URLError: + print('Failed to download prebuilt clang %s' % cds_file) + print('Use --force-local-build if you want to build locally.') + print('Exiting.') sys.exit(1) @@ -500,24 +508,24 @@ return 0 if args.with_android and not os.path.exists(ANDROID_NDK_DIR): - print 'Android NDK not found at ' + ANDROID_NDK_DIR - print 'The Android NDK is needed to build a Clang whose -fsanitize=address' - print 'works on Android. See ' - print 'https://www.chromium.org/developers/how-tos/android-build-instructions' - print 'for how to install the NDK, or pass --without-android.' + print('Android NDK not found at ' + ANDROID_NDK_DIR) + print('The Android NDK is needed to build a Clang whose -fsanitize=address') + print('works on Android. See ') + print('https://www.chromium.org/developers/how-tos/android-build-instructions') + print('for how to install the NDK, or pass --without-android.') return 1 if args.with_fuchsia and not os.path.exists(FUCHSIA_SDK_DIR): - print 'Fuchsia SDK not found at ' + FUCHSIA_SDK_DIR - print 'The Fuchsia SDK is needed to build libclang_rt for Fuchsia.' - print 'Install the Fuchsia SDK by adding fuchsia to the ' - print 'target_os section in your .gclient and running hooks, ' - print 'or pass --without-fuchsia.' - print 'https://chromium.googlesource.com/chromium/src/+/master/docs/fuchsia_build_instructions.md' - print 'for general Fuchsia build instructions.' + print('Fuchsia SDK not found at ' + FUCHSIA_SDK_DIR) + print('The Fuchsia SDK is needed to build libclang_rt for Fuchsia.') + print('Install the Fuchsia SDK by adding fuchsia to the ') + print('target_os section in your .gclient and running hooks, ') + print('or pass --without-fuchsia.') + print('https://chromium.googlesource.com/chromium/src/+/master/docs/fuchsia_build_instructions.md') + print('for general Fuchsia build instructions.') return 1 - print 'Locally building Clang %s...' % PACKAGE_VERSION + print('Locally building Clang %s...' % PACKAGE_VERSION) AddCMakeToPath(args) AddGnuWinToPath() @@ -557,7 +565,7 @@ base_cmake_args.append('-DLLVM_ENABLE_LIBXML2=FORCE_ON') if args.bootstrap: - print 'Building bootstrap compiler' + print('Building bootstrap compiler') EnsureDirExists(LLVM_BOOTSTRAP_DIR) os.chdir(LLVM_BOOTSTRAP_DIR) bootstrap_args = base_cmake_args + [ @@ -588,7 +596,7 @@ cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang') cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang++') - print 'Building final compiler' + print('Building final compiler') # LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is # needed, on OS X it requires libc++. clang only automatically links to libc++ @@ -632,7 +640,7 @@ # Build lld and code coverage tools. This is done separately from the rest of # the build because these tools require threading support. tools_with_threading = [ 'lld', 'llvm-cov', 'llvm-profdata' ] - print 'Building the following tools with threading support: %s' % ( + print('Building the following tools with threading support: %s' % str(tools_with_threading)) if os.path.exists(THREADS_ENABLED_BUILD_DIR): @@ -926,7 +934,7 @@ RunCommand(['ninja', 'check-all'], msvc_arch='x64') WriteStampFile(PACKAGE_VERSION) - print 'Clang update was successful.' + print('Clang update was successful.') return 0 @@ -983,10 +991,10 @@ args = parser.parse_args() if args.lto_lld and not args.bootstrap: - print '--lto-lld requires --bootstrap' + print('--lto-lld requires --bootstrap') return 1 if args.lto_lld and not sys.platform.startswith('linux'): - print '--lto-lld is only effective on Linux. Ignoring the option.' + print('--lto-lld is only effective on Linux. Ignoring the option.') args.lto_lld = False # Get svn if we're going to use it to check the revision or do a local build. @@ -995,9 +1003,9 @@ AddSvnToPathOnWin() if args.verify_version and args.verify_version != VERSION: - print 'VERSION is %s but --verify-version argument was %s, exiting.' % ( - VERSION, args.verify_version) - print 'clang_version in build/toolchain/toolchain.gni is likely outdated.' + print('VERSION is %s but --verify-version argument was %s, exiting.' % ( + VERSION, args.verify_version)) + print('clang_version in build/toolchain/toolchain.gni is likely outdated.') return 1 # DEVELOPER_DIR needs to be set when Xcode isn't in a standard location @@ -1009,9 +1017,9 @@ global CLANG_REVISION, PACKAGE_VERSION if args.print_revision: if use_head_revision or args.llvm_force_head_revision: - print GetSvnRevision(LLVM_DIR) + print(GetSvnRevision(LLVM_DIR)) else: - print PACKAGE_VERSION + print(PACKAGE_VERSION) return 0 if args.print_clang_version:
diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py index b5393a7..226c323 100755 --- a/tools/grit/grit/format/html_inline.py +++ b/tools/grit/grit/format/html_inline.py
@@ -55,7 +55,7 @@ re.MULTILINE) # This re matches '<img srcset="..."' _SRCSET_RE = lazy_re.compile( - r'<img\b(?:[^>]*?\s)srcset="(?!\[\[|{{)(?P<srcset>[^"\']*)"', + r'<img\b(?:[^>]*?\s)srcset="(?!\[\[|{{|\$i18n{)(?P<srcset>[^"\']*)"', re.MULTILINE) # This re is for splitting srcset value string into "image candidate strings". # Notes:
diff --git a/tools/grit/grit/format/html_inline_unittest.py b/tools/grit/grit/format/html_inline_unittest.py index eca6ada..96f1e26 100755 --- a/tools/grit/grit/format/html_inline_unittest.py +++ b/tools/grit/grit/format/html_inline_unittest.py
@@ -648,6 +648,38 @@ util.FixLineEnd(result.inlined_data, '\n')) tmp_dir.CleanUp() + def testImgSrcsetIgnoresI18n(self): + '''Tests that $i18n{...} strings are ignored when inlining. + ''' + + src_html = ''' + <html> + <head></head> + <body> + <img srcset="$i18n{foo}"> + </body> + </html> + ''' + + files = { + 'index.html': src_html, + } + + expected_inlined = src_html + + source_resources = set() + tmp_dir = util.TempDir(files) + for filename in files: + source_resources.add(tmp_dir.GetPath(util.normpath(filename))) + + result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None) + resources = result.inlined_files + resources.add(tmp_dir.GetPath('index.html')) + self.failUnlessEqual(resources, source_resources) + self.failUnlessEqual(expected_inlined, + util.FixLineEnd(result.inlined_data, '\n')) + tmp_dir.CleanUp() + def testConditionalInclude(self): '''Tests that output and dependency generation includes only files not'''\ ''' blocked by <if> macros.'''
diff --git a/tools/licenses.py b/tools/licenses.py index 4d609162d..f893756 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -192,6 +192,12 @@ "License": "BSD", "License File": "NOT_SHIPPED", }, + os.path.join('third_party', 'crashpad', 'crashpad', 'third_party', 'xnu'): { + "Name": "xnu", + "URL": "https://opensource.apple.com/source/xnu/", + "License": "Apple Public Source License 2.0", + "License File": "APPLE_LICENSE", + }, os.path.join('third_party', 'crashpad', 'crashpad', 'third_party', 'zlib'): { "Name": "zlib",
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index b246c7d..2378ac5 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -208,6 +208,7 @@ 'chromeos-amd64-generic-rel-vm-tests': 'cros_chrome_sdk_headless_ozone_dcheck_always_on', 'chromeos-kevin-rel-hw-tests': 'cros_chrome_sdk_headless_ozone', 'chromeos-vm-code-coverage': 'cros_chrome_sdk_headless_ozone_coverage', + 'linux-chromeos-code-coverage': 'chromeos_with_codecs_release_bot_coverage', 'Linux Builder Goma Canary': 'release_bot', 'Linux Builder Goma Latest Client': 'release_bot', @@ -349,6 +350,7 @@ 'Android FYI Release (Nexus 6P)': 'gpu_tests_android_release_trybot_arm64', 'Android FYI Release (Nexus 9)': 'gpu_tests_android_release_trybot_arm64', 'Android FYI Release (NVIDIA Shield TV)': 'gpu_tests_android_release_trybot_arm64', + 'Android FYI Release (Pixel 2)': 'gpu_tests_android_release_trybot', 'Android FYI 32 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot', 'Android FYI 32 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot', 'Android FYI 32 Vk Release (Pixel XL)': 'gpu_tests_android_vulkan_release_trybot', @@ -622,6 +624,7 @@ 'gpu-manual-try-android-m-nexus-6p-64': 'gpu_tests_android_release_trybot_arm64', 'gpu-manual-try-android-m-nexus-9-64': 'gpu_tests_android_release_trybot_arm64', 'gpu-manual-try-android-n-nvidia-shield-tv-64': 'gpu_tests_android_release_trybot_arm64', + 'gpu-manual-try-android-p-pixel-2-32': 'gpu_tests_android_release_trybot', 'gpu-manual-try-android-p-pixel-2-32-vk': 'gpu_tests_android_vulkan_release_trybot', 'gpu-manual-try-android-p-pixel-2-32-deqp-vk': 'deqp_android_vulkan_release_trybot', 'gpu-manual-try-android-p-pixel-2-64-vk': 'gpu_tests_android_vulkan_release_trybot_arm64', @@ -1170,6 +1173,10 @@ 'chromeos_with_codecs', 'release_bot', 'use_vaapi', ], + 'chromeos_with_codecs_release_bot_coverage': [ + 'chromeos_with_codecs', 'release_bot', 'use_vaapi', 'use_clang_coverage', + ], + 'chromeos_with_codecs_release_trybot': [ 'chromeos_with_codecs', 'release_trybot', 'use_vaapi', 'no_symbols', ],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 568c3371..b14c7931 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -31700,6 +31700,7 @@ <int value="-1720653947" label="WebRtcHybridAgc:disabled"/> <int value="-1719833926" label="disable-answers-in-suggest"/> <int value="-1716654100" label="tab-capture-downscale-quality"/> + <int value="-1716140224" label="EnableEmbeddedAssistantUI:disabled"/> <int value="-1715180530" label="OmniboxUIExperimentShowSuffixOnAllSearchSuggestions:disabled"/> <int value="-1714128884" label="disable-launcher-search-provider-api"/> @@ -33320,6 +33321,7 @@ <int value="941036016" label="ContentSuggestionsSettings:disabled"/> <int value="941883332" label="ProactiveTabFreezeAndDiscard:disabled"/> <int value="943319566" label="enable-intent-picker"/> + <int value="944484780" label="EnableEmbeddedAssistantUI:enabled"/> <int value="946185008" label="EnableAppDataSearch:disabled"/> <int value="946688335" label="OmniboxSpareRenderer:disabled"/> <int value="952558794" label="enable-remote-assistance"/> @@ -50452,12 +50454,23 @@ </enum> <enum name="SpareWebContentsStatus"> + <obsolete> + Superseded by SpareWebContentsStatus2 as of 03/2019. + </obsolete> <int value="0" label="Created"/> <int value="1" label="Used"/> <int value="2" label="Render process gone"/> <int value="3" label="Destroyed"/> </enum> +<enum name="SpareWebContentsStatus2"> + <int value="0" label="Created"/> + <int value="1" label="Used"/> + <int value="2" label="Render process gone"/> + <int value="3" label="Destroyed"/> + <int value="4" label="Stolen"/> +</enum> + <enum name="SpdyFrameFlowControlState"> <int value="0" label="Send not stalled"/> <int value="1" label="Send stalled by stream"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8e12354..30d39622 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -13561,6 +13561,18 @@ </summary> </histogram> +<histogram base="true" name="Browser.Tabs.TotalSwitchDuration" units="ms" + expires_after="2019-08-31"> +<!-- Name completed by histogram_suffixes name="TabSwitchingTime" --> + + <owner>ejoe@google.com</owner> + <owner>jonross@chromium.com</owner> + <summary> + The time between the input event timestamp and the frame presentation time + on a tab switch. + </summary> +</histogram> + <histogram name="BrowserActions.NumTabCreatedInBackground" units="tabNum"> <owner>peconn@chromium.org</owner> <summary> @@ -128871,6 +128883,28 @@ </summary> </histogram> +<histogram name="WebAudio.AudioContextOptions.sampleRate" units="Hz" + expires_after="2019-09-08"> + <owner>rtoy@chromium.org</owner> + <owner>hongchan@chromium.org</owner> + <summary> + The sample rate requested by developer to be used as the sample rate when + constructing an AudioContext with an AudioContextOptions dictionary. This is + recorded for each AudioContext created, probably just one or two per page. + </summary> +</histogram> + +<histogram name="WebAudio.AudioContextOptions.sampleRateRatio" + expires_after="2019-09-08"> + <owner>rtoy@chromium.org</owner> + <owner>hongchan@chromium.org</owner> + <summary> + The ratio of the user-selected sample rate to the hardware sample rate of an + AudioContext. The ratio is represented as a percentage. This is recorded for + each AudioContext created, probably just one or two per page. + </summary> +</histogram> + <histogram name="WebAudio.AudioDestination.CallbackBufferSize"> <owner>rtoy@chromium.org</owner> <owner>hongchan@chromium.org</owner> @@ -148090,6 +148124,18 @@ <affected-histogram name="Tabs.UsedInInterval.Count"/> </histogram_suffixes> +<histogram_suffixes name="TabSwitchingTime" separator="."> + <suffix name="NoSavedFrames" + label="The time from the input timestamp on a tab switch, until the + frame is presented on the screen when there is no saved frame in + the cache."/> + <suffix name="WithSavedFrames" + label="The time from the input timestamp on a tab switch, until the + frame is presented on the screen when there are saved frames in + the cache."/> + <affected-histogram name="Browser.Tabs.TotalSwitchDuration"/> +</histogram_suffixes> + <histogram_suffixes name="TabSwitchInputLatency" separator="."> <suffix name="Keyboard" label="The time it takes from receiving a keyboard input event that
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr.py b/tools/perf/cli_tools/update_wpr/update_wpr.py index d7f0879..ee8faaf 100644 --- a/tools/perf/cli_tools/update_wpr/update_wpr.py +++ b/tools/perf/cli_tools/update_wpr/update_wpr.py
@@ -112,44 +112,6 @@ cli_helpers.Info(' %-26s%s' % ('[%s]:' % line[0], line[2])) -def _PrintRunInfo(out_file, results_details=True): - try: - if results_details: - _PrintResultsHTMLInfo(out_file) - except Exception as e: - cli_helpers.Error('Could not print results.html tests: %s' % e) - - def shell(cmd): - return subprocess.check_output(cmd, shell=True).rstrip() - - def statsFor(name, filters='wc -l'): - cmd = 'grep "DevTools console .%s." "%s"' % (name, out_file) - cmd += ' | ' + filters - output = shell(cmd) or '0' - if len(output) > 7: - cli_helpers.Info(' %-26s%s' % ('[%s]:' % name, cmd)) - cli_helpers.Info(' ' + output.replace('\n', '\n ')) - else: - cli_helpers.Info(' %-16s%-8s %s' % ('[%s]:' % name, output, cmd)) - - cli_helpers.Info('Stdout/Stderr Log: %s' % out_file) - cli_helpers.Info('Chrome Log: %s.chrome.log' % out_file) - cli_helpers.Info( - ' Total output: %s' % - subprocess.check_output(['wc', '-l', out_file]).rstrip()) - cli_helpers.Info( - ' Total Console: %s' % - shell('grep "DevTools console" "%s" | wc -l' % out_file)) - statsFor('security') - statsFor('network', 'cut -d " " -f 20- | sort | uniq -c | sort -nr') - - chrome_log = '%s.chrome.log' % out_file - if os.path.isfile(chrome_log): - cmd = 'grep "Uncaught .*Error" "%s"' % chrome_log - count = shell(cmd + '| wc -l') - cli_helpers.Info(' %-16s%-8s %s' % ('[javascript]:', count, cmd)) - - def _UploadArchiveToGoogleStorage(archive): """Uploads specified WPR archive to the GS.""" cli_helpers.Run([ @@ -244,7 +206,7 @@ if self._IsDesktop(): args.append('system_health.memory_desktop') else: - args.extend('system_health.memory_mobile') + args.extend(['system_health.memory_mobile', '--device={device_id}']) args.extend([ @@ -257,9 +219,48 @@ args.append('--use-live-sites') out_file = self._CheckLog(args, log_name=log_name) self._ExtractResultsFile(out_file) - _ExtractLogFile(out_file) + if self._IsDesktop(): # Mobile test runner does not product the log file. + _ExtractLogFile(out_file) return out_file + def _PrintRunInfo(self, out_file, results_details=True): + try: + if results_details: + _PrintResultsHTMLInfo(out_file) + except Exception as e: + cli_helpers.Error('Could not print results.html tests: %s' % e) + + def shell(cmd): + return subprocess.check_output(cmd, shell=True).rstrip() + + def statsFor(name, filters='wc -l'): + cmd = 'grep "DevTools console .%s." "%s"' % (name, out_file) + cmd += ' | ' + filters + output = shell(cmd) or '0' + if len(output) > 7: + cli_helpers.Info(' %-26s%s' % ('[%s]:' % name, cmd)) + cli_helpers.Info(' ' + output.replace('\n', '\n ')) + else: + cli_helpers.Info(' %-16s%-8s %s' % ('[%s]:' % name, output, cmd)) + + cli_helpers.Info('Stdout/Stderr Log: %s' % out_file) + if self._IsDesktop(): # Mobile test runner does not product the log file. + cli_helpers.Info('Chrome Log: %s.chrome.log' % out_file) + cli_helpers.Info( + ' Total output: %s' % + subprocess.check_output(['wc', '-l', out_file]).rstrip()) + cli_helpers.Info( + ' Total Console: %s' % + shell('grep "DevTools console" "%s" | wc -l' % out_file)) + statsFor('security') + statsFor('network', 'cut -d " " -f 20- | sort | uniq -c | sort -nr') + + chrome_log = '%s.chrome.log' % out_file + if os.path.isfile(chrome_log): + cmd = 'grep "Uncaught .*Error" "%s"' % chrome_log + count = shell(cmd + '| wc -l') + cli_helpers.Info(' %-16s%-8s %s' % ('[javascript]:', count, cmd)) + def _GetBranchIssueUrl(self): output_file = os.path.join(self.output_dir, 'git_cl_issue.json') subprocess.check_output(['git', 'cl', 'issue', '--json', output_file]) @@ -337,7 +338,7 @@ cli_helpers.Step('LIVE RUN: %s' % self.story) out_file = self._RunSystemHealthMemoryBenchmark( log_name='live', live=True) - _PrintRunInfo(out_file) + self._PrintRunInfo(out_file) return out_file def Cleanup(self): @@ -357,13 +358,13 @@ else: args.extend(['--device={device_id}', 'mobile_system_health_story_set']) out_file = self._CheckLog(args, log_name='record') - _PrintRunInfo(out_file, results_details=False) + self._PrintRunInfo(out_file, results_details=False) def ReplayWpr(self): cli_helpers.Step('REPLAY WPR: %s' % self.story) out_file = self._RunSystemHealthMemoryBenchmark( log_name='replay', live=False) - _PrintRunInfo(out_file) + self._PrintRunInfo(out_file) return out_file def UploadWpr(self): @@ -384,7 +385,8 @@ 'with tools/perf/update_wpr script' % self.story) if self.bug_id: commit_message += '\n\nBug: %s' % self.bug_id - cli_helpers.Run(['git', 'commit', '-a', '-m', commit_message]) + if subprocess.call(['git', 'diff', '--quiet']): + cli_helpers.Run(['git', 'commit', '-a', '-m', commit_message]) commit_msg_file = os.path.join(self.output_dir, 'commit_message.tmp') with open(commit_msg_file, 'w') as fd: fd.write(commit_message)
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py index 26d6bb0..a875a38f 100644 --- a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py +++ b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py
@@ -165,7 +165,7 @@ @mock.patch(WPR_UPDATER + 'WprUpdater._RunSystemHealthMemoryBenchmark', return_value='<out-file>') - @mock.patch(WPR_UPDATER + '_PrintRunInfo') + @mock.patch(WPR_UPDATER + 'WprUpdater._PrintRunInfo') def testLiveRun(self, print_run_info, run_benchmark): self.wpr_updater.LiveRun() run_benchmark.assert_called_once_with(log_name='live', live=True) @@ -223,7 +223,7 @@ @mock.patch(WPR_UPDATER + '_PrintResultsHTMLInfo', side_effect=[Exception()]) def testPrintRunInfo(self, print_results): self._check_output.return_value = '0\n' - update_wpr._PrintRunInfo('<outfile>', True) + self.wpr_updater._PrintRunInfo('<outfile>', True) print_results.assert_called_once_with('<outfile>') self.assertListEqual(self._info.mock_calls, [ mock.call('Stdout/Stderr Log: <outfile>'), @@ -255,7 +255,7 @@ mock.call('.../data/dir/<archive>.sha1'), ]) - @mock.patch(WPR_UPDATER + '_PrintRunInfo') + @mock.patch(WPR_UPDATER + 'WprUpdater._PrintRunInfo') @mock.patch(WPR_UPDATER + 'WprUpdater._DeleteExistingWpr') def testRecordWprDesktop(self, delete_existing_wpr, print_run_info): del delete_existing_wpr, print_run_info # Unused. @@ -265,7 +265,7 @@ '--browser=system', 'desktop_system_health_story_set' ], env={'LC_ALL': 'en_US.UTF-8'}, log_path='/tmp/dir/record_<tstamp>') - @mock.patch(WPR_UPDATER + '_PrintRunInfo') + @mock.patch(WPR_UPDATER + 'WprUpdater._PrintRunInfo') @mock.patch(WPR_UPDATER + 'WprUpdater._DeleteExistingWpr') def testRecordWprMobile(self, delete_existing_wpr, print_run_info): del delete_existing_wpr, print_run_info # Unused. @@ -277,7 +277,7 @@ 'mobile_system_health_story_set' ], env={'LC_ALL': 'en_US.UTF-8'}, log_path='/tmp/dir/record_<tstamp>') - @mock.patch(WPR_UPDATER + '_PrintRunInfo') + @mock.patch(WPR_UPDATER + 'WprUpdater._PrintRunInfo') @mock.patch(WPR_UPDATER + 'WprUpdater._RunSystemHealthMemoryBenchmark', return_value='<out-file>') def testReplayWpr(self, run_benchmark, print_run_info): @@ -296,7 +296,9 @@ mock.call(['git', 'add', '<archive>.sha1']) ]) - def testUploadCL(self): + @mock.patch('subprocess.call', return_value=1) + def testUploadCL(self, subprocess_call): + del subprocess_call # Unused. self._run.return_value = 42 self.assertEqual(self.wpr_updater.UploadCL(), 42) self.assertListEqual(self._run.mock_calls, [
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 1cc04c4..25e771bd 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -100,7 +100,6 @@ } ], 'platform': 'android-chrome', - 'browser': 'bin/monochrome_64_32_bundle', 'dimension': { 'pool': 'chrome.tests.perf-fyi', 'os': 'Android', @@ -911,8 +910,6 @@ # For trybot testing we always use the reference build if tester_config.get('testing', False): browser_name = 'reference' - elif 'browser' in tester_config: - browser_name = 'exact' elif tester_config['platform'] == 'android': browser_name = 'android-chromium' elif tester_config['platform'].startswith('android-'): @@ -929,13 +926,7 @@ '--upload-results' ] - if 'browser' in tester_config: - test_args.append('--browser-executable=../../out/Release/%s' % - tester_config['browser']) - if tester_config['platform'].startswith('android'): - test_args.append('--device=android') - - if tester_config['platform'].startswith('android-webview'): + if browser_name.startswith('android-webview'): test_args.append( '--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk')
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index 7697b49..3f326e7 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -97,61 +97,6 @@ } self.assertEquals(returned_test, expected_generated_test) - def testGeneratePerformanceTestSuiteExact(self): - swarming_dimensions = [ - {'os': 'SkyNet', 'pool': 'T-RIP'} - ] - test_config = { - 'platform': 'android-webview', - 'browser': 'bin/monochrome_64_32_bundle', - 'dimension': swarming_dimensions, - } - test = { - 'isolate': 'performance_test_suite', - 'extra_args': [ - '--run-ref-build', - '--test-shard-map-filename=shard_map.json', - ], - 'num_shards': 26 - } - returned_test = perf_data_generator.generate_performance_test( - test_config, test) - - expected_generated_test = { - 'override_compile_targets': ['performance_test_suite'], - 'isolate_name': 'performance_test_suite', - 'args': ['-v', '--browser=exact', '--upload-results', - '--browser-executable=../../out/Release' - '/bin/monochrome_64_32_bundle', - '--device=android', - '--webview-embedder-apk=../../out/Release' - '/apks/SystemWebViewShell.apk', - '--run-ref-build', - '--test-shard-map-filename=shard_map.json'], - 'trigger_script': { - 'args': [ - '--multiple-dimension-script-verbose', - 'True' - ], - 'requires_simultaneous_shard_dispatch': True, - 'script': '//testing/trigger_scripts/perf_device_trigger.py' - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py' - }, - 'swarming': { - 'ignore_task_failure': False, - 'can_use_on_swarming_builders': True, - 'expiration': 7200, - 'io_timeout': 1800, - 'hard_timeout': 36000, - 'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]], - 'shards': 26 - }, - 'name': 'performance_test_suite' - } - self.assertEquals(returned_test, expected_generated_test) - def testGeneratePerformanceTestSuiteWebview(self): swarming_dimensions = [ {'os': 'SkyNet', 'pool': 'T-RIP'}
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py index 7ace5f3..df7cd111 100644 --- a/tools/perf/core/perf_json_config_validator.py +++ b/tools/perf/core/perf_json_config_validator.py
@@ -81,18 +81,17 @@ browser_options = _ParseBrowserFlags(test_config['args']) if 'WebView' in builder_name or 'webview' in builder_name: if browser_options.browser not in ( - 'android-webview', 'android-webview-google', 'exact'): + 'android-webview', 'android-webview-google'): raise ValueError( - "%s must use 'android-webview', 'android-webview-google' or 'exact' " - "browser" % builder_name) + "%s must use 'android-webview' or 'android-webview-google' browser" % + builder_name) if not browser_options.webview_embedder_apk: raise ValueError('%s must set --webview-embedder-apk flag' % builder_name) elif 'Android' in builder_name or 'android' in builder_name: - if browser_options.browser not in ( - 'android-chromium', 'android-chrome', 'exact'): + if browser_options.browser not in ('android-chromium', 'android-chrome'): raise ValueError( - "%s must use 'android-chromium', 'android-chrome' or 'exact' " - "browser" % builder_name) + "%s must use 'android-chromium' or 'android-chrome' browser" % + builder_name) elif builder_name in ('win-10-perf', 'Win 7 Nvidia GPU Perf'): if browser_options.browser != 'release_x64': raise ValueError("%s must use 'release_x64' browser type" %
diff --git a/ui/android/display_android_manager.cc b/ui/android/display_android_manager.cc index fc3407b..8509bd7b 100644 --- a/ui/android/display_android_manager.cc +++ b/ui/android/display_android_manager.cc
@@ -21,18 +21,20 @@ using display::Display; using display::DisplayList; -void SetScreenAndroid() { +void SetScreenAndroid(bool use_display_wide_color_gamut) { // Do not override existing Screen. DCHECK_EQ(display::Screen::GetScreen(), nullptr); - DisplayAndroidManager* manager = new DisplayAndroidManager(); + DisplayAndroidManager* manager = + new DisplayAndroidManager(use_display_wide_color_gamut); display::Screen::SetScreenInstance(manager); JNIEnv* env = AttachCurrentThread(); Java_DisplayAndroidManager_onNativeSideCreated(env, (jlong)manager); } -DisplayAndroidManager::DisplayAndroidManager() {} +DisplayAndroidManager::DisplayAndroidManager(bool use_display_wide_color_gamut) + : use_display_wide_color_gamut_(use_display_wide_color_gamut) {} DisplayAndroidManager::~DisplayAndroidManager() {} @@ -79,9 +81,11 @@ if (!Display::HasForceDeviceScaleFactor()) display->set_device_scale_factor(dipScale); if (!Display::HasForceDisplayColorProfile()) { - // TODO(ccameron): Use CreateDisplayP3D65 if isWideColorGamut is true, once - // the feature is ready to use. - display->set_color_space(gfx::ColorSpace::CreateSRGB()); + if (isWideColorGamut) { + display->set_color_space(gfx::ColorSpace::CreateDisplayP3D65()); + } else { + display->set_color_space(gfx::ColorSpace::CreateSRGB()); + } } display->set_size_in_pixels(size_in_pixels); @@ -110,7 +114,8 @@ display::Display display(sdkDisplayId, bounds_in_dip); DoUpdateDisplay(&display, bounds_in_pixels.size(), dipScale, rotationDegrees, - bitsPerPixel, bitsPerComponent, isWideColorGamut); + bitsPerPixel, bitsPerComponent, + isWideColorGamut && use_display_wide_color_gamut_); ProcessDisplayChanged(display, sdkDisplayId == primary_display_id_); }
diff --git a/ui/android/display_android_manager.h b/ui/android/display_android_manager.h index f1fc6a49..e278624c 100644 --- a/ui/android/display_android_manager.h +++ b/ui/android/display_android_manager.h
@@ -51,8 +51,8 @@ private: friend class WindowAndroid; - friend void SetScreenAndroid(); - DisplayAndroidManager(); + friend void SetScreenAndroid(bool use_display_wide_color_gamut); + explicit DisplayAndroidManager(bool use_display_wide_color_gamut); static void DoUpdateDisplay(display::Display* display, gfx::Size size_in_pixels, @@ -62,6 +62,7 @@ int bitsPerComponent, bool isWideColorGamut); + const bool use_display_wide_color_gamut_; int primary_display_id_ = 0; DISALLOW_COPY_AND_ASSIGN(DisplayAndroidManager);
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml index 01e1ead..c1639897 100644 --- a/ui/android/java/res/values/color_palette.xml +++ b/ui/android/java/res/values/color_palette.xml
@@ -44,6 +44,8 @@ <color name="default_icon_color_white_pressed" tools:ignore="UnusedResources"> @color/white_alpha_50 </color> + <!-- Common text colors --> + <color name="default_text_color_dark">@color/modern_grey_900</color> <color name="default_red_light" tools:ignore="UnusedResources">@color/google_red_300</color> <color name="default_red_dark" tools:ignore="UnusedResources">@color/google_red_700</color>
diff --git a/ui/android/java/res/values/colors.xml b/ui/android/java/res/values/colors.xml index afaecd83..fc5fd39 100644 --- a/ui/android/java/res/values/colors.xml +++ b/ui/android/java/res/values/colors.xml
@@ -7,7 +7,7 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- TODO(huayinz): remove tools:ignore once these colors are used in ui/android --> <!-- Common text colors --> - <color name="default_text_color">@color/modern_grey_900</color> + <color name="default_text_color">@color/default_text_color_dark</color> <color name="default_text_color_secondary">@color/modern_grey_700</color> <!-- Text color for non-clickable blue text. --> <color name="default_text_color_blue" tools:ignore="UnusedResources">@color/modern_blue_600</color>
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java index 7889bdd..f0b667d 100644 --- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -55,14 +55,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidObserver { private static final String TAG = "WindowAndroid"; - // Allow client to control whether wide gamut is enabled. - private static boolean sEnableWideColorGamut; - - public static void enableWideColorGamut() { - assert !sEnableWideColorGamut; - sEnableWideColorGamut = true; - } - private KeyboardVisibilityDelegate mKeyboardVisibilityDelegate = KeyboardVisibilityDelegate.getInstance(); @@ -707,7 +699,6 @@ // gamut (on supported hardware and os). However it is important for embedders like WebView // which do not make the wide gamut decision to check this at run time. private boolean getWindowIsWideColorGamut() { - if (!sEnableWideColorGamut) return false; if (!BuildInfo.isAtLeastQ()) return false; Window window = getWindow(); if (window == null) return false;
diff --git a/ui/android/screen_android.h b/ui/android/screen_android.h index 1482223..4e61a2c 100644 --- a/ui/android/screen_android.h +++ b/ui/android/screen_android.h
@@ -10,7 +10,7 @@ namespace ui { -UI_ANDROID_EXPORT void SetScreenAndroid(); +UI_ANDROID_EXPORT void SetScreenAndroid(bool use_display_wide_color_gamut); } // namespace display
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc index fff35c2..c5bd4f5 100644 --- a/ui/android/window_android.cc +++ b/ui/android/window_android.cc
@@ -396,9 +396,6 @@ &display, display.GetSizeInPixel(), display.device_scale_factor(), display.RotationAsDegree(), display.color_depth(), display.depth_per_component(), window_is_wide_color_gamut_); - if (window_is_wide_color_gamut_) { - display.set_color_space(gfx::ColorSpace::CreateDisplayP3D65()); - } return display; }
diff --git a/ui/aura/mus/property_converter.cc b/ui/aura/mus/property_converter.cc index dd9cd90..cee64d4 100644 --- a/ui/aura/mus/property_converter.cc +++ b/ui/aura/mus/property_converter.cc
@@ -76,6 +76,8 @@ ws::mojom::WindowManager::kAppIconLarge_Property); RegisterImageSkiaProperty(client::kAppIconSmallKey, ws::mojom::WindowManager::kAppIconSmall_Property); + RegisterImageSkiaProperty(client::kAvatarIconKey, + ws::mojom::WindowManager::kAvatarIcon_Property); RegisterPrimitiveProperty(client::kAlwaysOnTopKey, ws::mojom::WindowManager::kAlwaysOnTop_Property, CreateAcceptAnyValueCallback());
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc index 75baf1fd..8b4c1ba 100644 --- a/ui/aura/mus/window_port_mus.cc +++ b/ui/aura/mus/window_port_mus.cc
@@ -137,7 +137,7 @@ } void WindowPortMus::SetCursor(const ui::Cursor& cursor) { - if (cursor_.IsSameAs(cursor)) + if (cursor == cursor_) return; window_tree_client_->SetCursor(this, cursor_, cursor);
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index 714ef6e..69ac7c3 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -236,8 +236,10 @@ void WindowTreeClient::SetCursor(WindowMus* window, const ui::Cursor& old_cursor, const ui::Cursor& new_cursor) { - DCHECK(tree_); + if (old_cursor == new_cursor) + return; + DCHECK(tree_); const uint32_t change_id = ScheduleInFlightChange( std::make_unique<InFlightCursorChange>(window, old_cursor)); tree_->SetCursor(change_id, window->server_id(), new_cursor);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 43bfcf4..085ef60 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -908,6 +908,7 @@ "cocoa/touch_bar_util_unittest.mm", "cocoa/tracking_area_unittest.mm", "cocoa/weak_ptr_nsobject_unittest.mm", + "cursor/cursor_unittest.cc", "cursor/cursor_util_unittest.cc", "models/list_model_unittest.cc", "models/list_selection_model_unittest.cc",
diff --git a/ui/base/cursor/cursor.cc b/ui/base/cursor/cursor.cc index 1ed7f1b9..6dc54dc 100644 --- a/ui/base/cursor/cursor.cc +++ b/ui/base/cursor/cursor.cc
@@ -5,23 +5,20 @@ #include "ui/base/cursor/cursor.h" #include "base/logging.h" +#include "ui/gfx/skia_util.h" namespace ui { -Cursor::Cursor() - : native_type_(CursorType::kNull), - platform_cursor_(0), - device_scale_factor_(0.0f) {} +Cursor::Cursor() = default; -Cursor::Cursor(CursorType type) - : native_type_(type), platform_cursor_(0), device_scale_factor_(0.0f) {} +Cursor::Cursor(CursorType type) : native_type_(type) {} Cursor::Cursor(const Cursor& cursor) : native_type_(cursor.native_type_), platform_cursor_(cursor.platform_cursor_), device_scale_factor_(cursor.device_scale_factor_), - custom_bitmap_(cursor.custom_bitmap_), - custom_hotspot_(cursor.custom_hotspot_) { + custom_hotspot_(cursor.custom_hotspot_), + custom_bitmap_(cursor.custom_bitmap_) { if (native_type_ == CursorType::kCustom) RefCustomCursor(); } @@ -68,15 +65,18 @@ #endif } -bool Cursor::IsSameAs(const Cursor& rhs) const { - return native_type_ == rhs.native_type_ && - custom_hotspot_ == rhs.custom_hotspot_ && - device_scale_factor_ == rhs.device_scale_factor_ && - custom_bitmap_.getGenerationID() == - rhs.custom_bitmap_.getGenerationID(); +bool Cursor::operator==(const Cursor& cursor) const { + return native_type_ == cursor.native_type_ && + platform_cursor_ == cursor.platform_cursor_ && + device_scale_factor_ == cursor.device_scale_factor_ && + custom_hotspot_ == cursor.custom_hotspot_ && + (native_type_ != CursorType::kCustom || + custom_bitmap_.getGenerationID() == + cursor.custom_bitmap_.getGenerationID() || + gfx::BitmapsAreEqual(custom_bitmap_, cursor.custom_bitmap_)); } -void Cursor::Assign(const Cursor& cursor) { +void Cursor::operator=(const Cursor& cursor) { if (*this == cursor) return; if (native_type_ == CursorType::kCustom) @@ -86,8 +86,8 @@ if (native_type_ == CursorType::kCustom) RefCustomCursor(); device_scale_factor_ = cursor.device_scale_factor_; - custom_bitmap_ = cursor.custom_bitmap_; custom_hotspot_ = cursor.custom_hotspot_; + custom_bitmap_ = cursor.custom_bitmap_; } } // namespace ui
diff --git a/ui/base/cursor/cursor.h b/ui/base/cursor/cursor.h index 06b5510a9..d95ad138d 100644 --- a/ui/base/cursor/cursor.h +++ b/ui/base/cursor/cursor.h
@@ -47,12 +47,8 @@ CursorType native_type() const { return native_type_; } PlatformCursor platform() const { return platform_cursor_; } - float device_scale_factor() const { - return device_scale_factor_; - } - void set_device_scale_factor(float device_scale_factor) { - device_scale_factor_ = device_scale_factor; - } + float device_scale_factor() const { return device_scale_factor_; } + void set_device_scale_factor(float scale) { device_scale_factor_ = scale; } SkBitmap GetBitmap() const; void set_custom_bitmap(const SkBitmap& bitmap) { custom_bitmap_ = bitmap; } @@ -62,65 +58,35 @@ custom_hotspot_ = hotspot; } + // Note: custom cursor comparison may perform expensive pixel equality checks! + bool operator==(const Cursor& cursor) const; + bool operator!=(const Cursor& cursor) const { return !(*this == cursor); } + bool operator==(CursorType type) const { return native_type_ == type; } - bool operator==(const Cursor& cursor) const { - return native_type_ == cursor.native_type_ && - platform_cursor_ == cursor.platform_cursor_ && - device_scale_factor_ == cursor.device_scale_factor_ && - custom_bitmap_.info() == cursor.custom_bitmap_.info() && - custom_bitmap_.rowBytes() == cursor.custom_bitmap_.rowBytes() && - custom_bitmap_.getPixels() == cursor.custom_bitmap_.getPixels() && - custom_hotspot_ == cursor.custom_hotspot_; - } bool operator!=(CursorType type) const { return native_type_ != type; } - bool operator!=(const Cursor& cursor) const { - return native_type_ != cursor.native_type_ || - platform_cursor_ != cursor.platform_cursor_ || - device_scale_factor_ != cursor.device_scale_factor_ || - custom_bitmap_.info() != cursor.custom_bitmap_.info() || - custom_bitmap_.rowBytes() != cursor.custom_bitmap_.rowBytes() || - custom_bitmap_.getPixels() != cursor.custom_bitmap_.getPixels() || - custom_hotspot_ != cursor.custom_hotspot_; - } - void operator=(const Cursor& cursor) { - Assign(cursor); - } - - // Checks if the data in |rhs| was created from the same input data. - // - // This is subtly different from operator==, as we need this to be a - // lightweight operation instead of performing pixel equality checks on - // arbitrary sized SkBitmaps. So we check the internal SkBitmap generation - // IDs, which are per-process, monotonically increasing ids which get changed - // whenever there's a modification to the pixel data. This means that this - // method can have false negatives: two SkBitmap instances made with the same - // input data (but which weren't copied from each other) can have equal pixel - // data, but different generation ids. - bool IsSameAs(const Cursor& rhs) const; + void operator=(const Cursor& cursor); private: - void Assign(const Cursor& cursor); - #if defined(USE_AURA) SkBitmap GetDefaultBitmap() const; gfx::Point GetDefaultHotspot() const; #endif - // See definitions above. - CursorType native_type_; + // The basic cursor type. + CursorType native_type_ = CursorType::kNull; - PlatformCursor platform_cursor_; + // The native platform cursor. + PlatformCursor platform_cursor_ = 0; // The device scale factor for the cursor. - float device_scale_factor_; + float device_scale_factor_ = 0.0f; - // The bitmap for the cursor. This is only used when it is custom cursor type. - SkBitmap custom_bitmap_; - - // The hotspot for the cursor. This is only used when it is custom cursor - // type. + // The hotspot for the cursor. This is only used for the custom cursor type. gfx::Point custom_hotspot_; + + // The bitmap for the cursor. This is only used for the custom cursor type. + SkBitmap custom_bitmap_; }; } // namespace ui
diff --git a/ui/base/cursor/cursor_unittest.cc b/ui/base/cursor/cursor_unittest.cc new file mode 100644 index 0000000..71685501 --- /dev/null +++ b/ui/base/cursor/cursor_unittest.cc
@@ -0,0 +1,78 @@ +// Copyright 2019 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/base/cursor/cursor.h" + +#include <algorithm> + +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/skia_util.h" + +namespace ui { +namespace { + +TEST(CursorTest, Null) { + Cursor cursor; + EXPECT_EQ(CursorType::kNull, cursor.native_type()); +} + +TEST(CursorTest, BasicType) { + Cursor cursor(CursorType::kPointer); + EXPECT_EQ(CursorType::kPointer, cursor.native_type()); + + Cursor copy(cursor); + EXPECT_EQ(cursor, copy); +} + +TEST(CursorTest, CustomType) { + Cursor cursor(CursorType::kCustom); + EXPECT_EQ(CursorType::kCustom, cursor.native_type()); + + const float kScale = 2.0f; + cursor.set_device_scale_factor(kScale); + EXPECT_EQ(kScale, cursor.device_scale_factor()); + + const gfx::Point kHotspot = gfx::Point(5, 2); + cursor.set_custom_hotspot(kHotspot); + EXPECT_EQ(kHotspot, cursor.GetHotspot()); + + SkBitmap bitmap; + bitmap.allocN32Pixels(10, 10); + bitmap.eraseColor(SK_ColorRED); + cursor.set_custom_bitmap(bitmap); + + EXPECT_EQ(bitmap.getGenerationID(), cursor.GetBitmap().getGenerationID()); + EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, cursor.GetBitmap())); + + Cursor copy(cursor); + EXPECT_EQ(cursor.GetBitmap().getGenerationID(), + copy.GetBitmap().getGenerationID()); + EXPECT_TRUE(gfx::BitmapsAreEqual(cursor.GetBitmap(), copy.GetBitmap())); + EXPECT_EQ(cursor, copy); +} + +TEST(CursorTest, CustomTypeComparesBitmapPixels) { + Cursor cursor1(CursorType::kCustom); + Cursor cursor2(CursorType::kCustom); + + SkBitmap bitmap1; + bitmap1.allocN32Pixels(10, 10); + bitmap1.eraseColor(SK_ColorRED); + cursor1.set_custom_bitmap(bitmap1); + + SkBitmap bitmap2; + bitmap2.allocN32Pixels(10, 10); + bitmap2.eraseColor(SK_ColorRED); + cursor2.set_custom_bitmap(bitmap2); + + EXPECT_NE(cursor1.GetBitmap().getGenerationID(), + cursor2.GetBitmap().getGenerationID()); + EXPECT_TRUE(gfx::BitmapsAreEqual(cursor1.GetBitmap(), cursor2.GetBitmap())); + EXPECT_EQ(cursor1, cursor2); +} + +} // namespace +} // namespace ui
diff --git a/ui/base/mojo/cursor_struct_traits_unittest.cc b/ui/base/mojo/cursor_struct_traits_unittest.cc index 1510471..f37f01bd 100644 --- a/ui/base/mojo/cursor_struct_traits_unittest.cc +++ b/ui/base/mojo/cursor_struct_traits_unittest.cc
@@ -10,6 +10,7 @@ #include "ui/base/cursor/cursor.h" #include "ui/base/mojo/cursor.mojom.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "ui/gfx/skia_util.h" namespace ui { @@ -23,9 +24,9 @@ } // namespace -// Tests numeric cursor ids. +// Test that basic cursor structs are passed correctly across the wire. TEST_F(CursorStructTraitsTest, TestBuiltIn) { - for (int i = 0; i < 43; ++i) { + for (int i = 0; i < static_cast<int>(ui::CursorType::kCustom); ++i) { ui::CursorType type = static_cast<ui::CursorType>(i); ui::Cursor input(type); @@ -35,7 +36,7 @@ } } -// Test that we copy cursor bitmaps and metadata across the wire. +// Test that cursor bitmaps and metadata are passed correctly across the wire. TEST_F(CursorStructTraitsTest, TestBitmapCursor) { ui::Cursor input(ui::CursorType::kCustom); @@ -51,35 +52,27 @@ input.set_device_scale_factor(kScale); ui::Cursor output; - ASSERT_TRUE(EchoCursor(input, &output)); + EXPECT_TRUE(EchoCursor(input, &output)); + EXPECT_EQ(input, output); EXPECT_EQ(ui::CursorType::kCustom, output.native_type()); EXPECT_EQ(kScale, output.device_scale_factor()); EXPECT_EQ(kHotspot, output.GetHotspot()); - // Even if the pixel data is logically the same, expect that it has different - // generation ids. - EXPECT_FALSE(output.IsSameAs(input)); + // Even though the pixel data is the same, the bitmap generation ids differ. + EXPECT_TRUE(gfx::BitmapsAreEqual(input.GetBitmap(), output.GetBitmap())); + EXPECT_NE(input.GetBitmap().getGenerationID(), + output.GetBitmap().getGenerationID()); - // Make a copy of output. It should be the same as output. + // Make a copy of output; the bitmap generation ids should be the same. ui::Cursor copy = output; - EXPECT_TRUE(copy.IsSameAs(output)); - - // But make sure that the pixel data actually is equivalent. - ASSERT_EQ(input.GetBitmap().width(), output.GetBitmap().width()); - ASSERT_EQ(input.GetBitmap().height(), output.GetBitmap().height()); - - for (int x = 0; x < input.GetBitmap().width(); ++x) { - for (int y = 0; y < input.GetBitmap().height(); ++y) { - EXPECT_EQ(input.GetBitmap().getColor(x, y), - output.GetBitmap().getColor(x, y)); - } - } + EXPECT_EQ(output.GetBitmap().getGenerationID(), + copy.GetBitmap().getGenerationID()); + EXPECT_EQ(input, output); } -// Test that we deal with empty bitmaps. (When a cursor resource isn't loaded -// in the renderer, the renderer will send a custom cursor with an empty -// bitmap.) +// Test that empty bitmaps are passed correctly over the wire. This happens when +// renderers relay a custom cursor before the bitmap resource is loaded. TEST_F(CursorStructTraitsTest, TestEmptyCursor) { const gfx::Point kHotspot = gfx::Point(5, 2); const float kScale = 2.0f;
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 43acfc9..ccc2372b 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -215,6 +215,8 @@ clone->SetVisible(GetTargetVisibility()); clone->SetFillsBoundsOpaquely(fills_bounds_opaquely_); clone->SetFillsBoundsCompletely(fills_bounds_completely_); + clone->SetRoundedCornerRadius(rounded_corner_radii()); + clone->SetIsFastRoundedCorner(is_fast_rounded_corner()); clone->set_name(name_); return clone; @@ -575,6 +577,17 @@ const std::array<uint32_t, 4>& corner_radii) { cc_layer_->SetRoundedCorner(corner_radii); ScheduleDraw(); + + for (const auto& mirror : mirrors_) + mirror->dest()->SetRoundedCornerRadius(corner_radii); +} + +void Layer::SetIsFastRoundedCorner(bool enable) { + cc_layer_->SetIsFastRoundedCorner(enable); + ScheduleDraw(); + + for (const auto& mirror : mirrors_) + mirror->dest()->SetIsFastRoundedCorner(enable); } // static @@ -646,6 +659,8 @@ cc_layer_->SafeOpaqueBackgroundColor()); new_layer->SetCacheRenderSurface(cc_layer_->cache_render_surface()); new_layer->SetTrilinearFiltering(cc_layer_->trilinear_filtering()); + new_layer->SetRoundedCorner(cc_layer_->corner_radii()); + new_layer->SetIsFastRoundedCorner(cc_layer_->is_fast_rounded_corner()); cc_layer_ = new_layer.get(); if (content_layer_) {
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index d8718b0..9f55961 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -277,6 +277,14 @@ return cc_layer_->corner_radii(); } + // If set to true, this layer would not trigger a render surface (if possible) + // due to having a rounded corner resulting in a better performance at the + // cost of maybe having some blending artifacts. + void SetIsFastRoundedCorner(bool enable); + bool is_fast_rounded_corner() const { + return cc_layer_->is_fast_rounded_corner(); + } + // Converts a point from the coordinates of |source| to the coordinates of // |target|. Necessarily, |source| and |target| must inhabit the same Layer // tree.
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index f3befcc3..7cca4fc 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -761,6 +761,8 @@ layer->SetLayerInverted(true); layer->AddCacheRenderSurfaceRequest(); layer->AddTrilinearFilteringRequest(); + layer->SetRoundedCornerRadius({1, 2, 4, 5}); + layer->SetIsFastRoundedCorner(true); auto clone = layer->Clone(); @@ -775,16 +777,23 @@ // Cloning should not preserve trilinear_filtering flag. EXPECT_NE(layer->cc_layer_for_testing()->trilinear_filtering(), clone->cc_layer_for_testing()->trilinear_filtering()); + EXPECT_EQ(layer->rounded_corner_radii(), clone->rounded_corner_radii()); + EXPECT_EQ(layer->is_fast_rounded_corner(), clone->is_fast_rounded_corner()); layer->SetTransform(gfx::Transform()); layer->SetColor(SK_ColorGREEN); layer->SetLayerInverted(false); + layer->SetIsFastRoundedCorner(false); + layer->SetRoundedCornerRadius({3, 6, 9, 12}); // The clone is an independent copy, so state changes do not propagate. EXPECT_EQ(transform, clone->GetTargetTransform()); EXPECT_EQ(SK_ColorRED, clone->background_color()); EXPECT_EQ(SK_ColorRED, clone->GetTargetColor()); EXPECT_TRUE(clone->layer_inverted()); + EXPECT_FALSE(layer->is_fast_rounded_corner()); + EXPECT_TRUE(clone->is_fast_rounded_corner()); + EXPECT_NE(layer->rounded_corner_radii(), clone->rounded_corner_radii()); constexpr SkColor kTransparent = SK_ColorTRANSPARENT; layer->SetColor(kTransparent); @@ -893,6 +902,16 @@ child->set_sync_bounds(true); child->SetBounds(new_bounds); EXPECT_EQ(new_bounds, mirror->bounds()); + + // Check for rounded corner mirror behavior + constexpr std::array<uint32_t, 4> kEmptyCornerRadii = {0, 0, 0, 0}; + EXPECT_EQ(mirror->rounded_corner_radii(), kEmptyCornerRadii); + EXPECT_FALSE(mirror->is_fast_rounded_corner()); + constexpr std::array<uint32_t, 4> corner_radii = {2, 3, 4, 5}; + child->SetRoundedCornerRadius(corner_radii); + child->SetIsFastRoundedCorner(true); + EXPECT_EQ(mirror->rounded_corner_radii(), corner_radii); + EXPECT_TRUE(mirror->is_fast_rounded_corner()); } // Tests for SurfaceLayer cloning and mirroring. This tests certain properties @@ -1000,11 +1019,18 @@ l1->SetVisible(false); l1->SetBounds(gfx::Rect(4, 5)); + constexpr std::array<uint32_t, 4> kCornerRadii = {1, 2, 3, 4}; + l1->SetRoundedCornerRadius(kCornerRadii); + l1->SetIsFastRoundedCorner(true); + EXPECT_EQ(gfx::Point3F(), l1->cc_layer_for_testing()->transform_origin()); EXPECT_TRUE(l1->cc_layer_for_testing()->DrawsContent()); EXPECT_TRUE(l1->cc_layer_for_testing()->contents_opaque()); EXPECT_TRUE(l1->cc_layer_for_testing()->hide_layer_and_subtree()); EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer_for_testing()->bounds()); + EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); + EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); + EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); cc::Layer* before_layer = l1->cc_layer_for_testing(); @@ -1023,6 +1049,9 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->contents_opaque()); EXPECT_TRUE(l1->cc_layer_for_testing()->hide_layer_and_subtree()); EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer_for_testing()->bounds()); + EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); + EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); + EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); EXPECT_FALSE(callback1_run); bool callback2_run = false; @@ -1042,6 +1071,9 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->contents_opaque()); EXPECT_TRUE(l1->cc_layer_for_testing()->hide_layer_and_subtree()); EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer_for_testing()->bounds()); + EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); + EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); + EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); EXPECT_TRUE(callback2_run); before_layer = l1->cc_layer_for_testing(); @@ -1062,6 +1094,9 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->contents_opaque()); EXPECT_TRUE(l1->cc_layer_for_testing()->hide_layer_and_subtree()); EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer_for_testing()->bounds()); + EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); + EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); + EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); EXPECT_FALSE(callback3_run); // Release the on |l1| mailbox to clean up the test.
diff --git a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js index ce5271c..f7e2c89 100644 --- a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js +++ b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
@@ -606,6 +606,61 @@ return test.util.sync.sendEvent(contentWindow, targetQuery, event); }; + +/** + * Sends a drag'n'drop set of events from |srcTarget| to |dstTarget|. + * + * @param {Window} contentWindow Window to be tested. + * @param {string} srcTarget Query to specify the element as the source to be + * dragged. + * @param {string} dstTarget Query to specify the element as the destination + * to drop. + * @param {boolean=} skipDrop True if it should only hover over dstTarget. + * to drop. + * @return {boolean} True if the event is sent to the target, false otherwise. + */ +test.util.sync.fakeDragAndDrop = + (contentWindow, srcTarget, dstTarget, skipDrop) => { + const options = { + bubbles: true, + composed: true, + dataTransfer: new DataTransfer(), + }; + const srcElement = contentWindow.document && + contentWindow.document.querySelector(srcTarget); + const dstElement = contentWindow.document && + contentWindow.document.querySelector(dstTarget); + + if (!srcElement || !dstElement) { + return false; + } + + // Get the middle of the src element, because some of Files app logic + // requires clientX and clientY. + const srcRect = srcElement.getBoundingClientRect(); + const srcOptions = Object.assign( + { + clientX: srcRect.left + (srcRect.width / 2), + clientY: srcRect.top + (srcRect.height / 2), + }, + options); + + const dragStart = new DragEvent('dragstart', srcOptions); + const dragEnter = new DragEvent('dragenter', options); + const dragOver = new DragEvent('dragover', options); + const drop = new DragEvent('drop', options); + const dragEnd = new DragEvent('dragEnd', options); + + srcElement.dispatchEvent(dragStart); + dstElement.dispatchEvent(dragEnter); + dstElement.dispatchEvent(dragOver); + if (!skipDrop) { + dstElement.dispatchEvent(drop); + } + srcElement.dispatchEvent(dragEnd); + return true; + }; + /** * Focuses to the element specified by |targetQuery|. This method does not * provide any guarantee whether the element is actually focused or not.
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html index 949d7712..3b40174 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
@@ -24,7 +24,7 @@ </div> <div id="file-path">[[filePath]]</div> <div class="buttons-group"> - <paper-button id="open-button" on-tap="onOpenInNewButtonTap" hidden$="[[!hasTask]]" aria-label="$i18n{QUICK_VIEW_OPEN_IN_NEW_BUTTON_LABEL}" tabindex="0" has-tooltip> + <paper-button id="open-button" on-tap="onOpenInNewButtonTap" hidden$="[[!hasTask]]" aria-label="$i18n{QUICK_VIEW_OPEN_IN_NEW_BUTTON_LABEL}" tabindex="0"> <span>$i18n{QUICK_VIEW_OPEN_IN_NEW_BUTTON_LABEL}</span> </paper-button> <files-icon-button toggles id="metadata-button" on-tap="onMetadataButtonTap_" active="{{metadataBoxActive}}" aria-label="$i18n{QUICK_VIEW_TOGGLE_METADATA_BOX_BUTTON_LABEL}" tabindex="0" has-tooltip>
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index 0835190..a57076b7 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -699,10 +699,11 @@ } const location = root && fileManager.volumeManager.getLocationInfo(root); const writable = location && !location.isReadOnly; - const removable = location && location.rootType === - VolumeManagerCommon.RootType.REMOVABLE; - event.canExecute = removable && (isUnrecognizedVolume || writable); - event.command.setHidden(!removable); + const isRoot = location && location.isRootEntry; + const removableRoot = location && isRoot && + location.rootType === VolumeManagerCommon.RootType.REMOVABLE; + event.canExecute = removableRoot && (isUnrecognizedVolume || writable); + event.command.setHidden(!removableRoot); } });
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js index 44e5f887..f6492cc6 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -1766,7 +1766,8 @@ return new DropEffectAndLabel( DropEffectType.NONE, strf('OPENING_LINUX_FILES')); } - if (destinationLocationInfo.volumeInfo.isReadOnlyRemovableDevice) { + if (destinationLocationInfo.volumeInfo && + destinationLocationInfo.volumeInfo.isReadOnlyRemovableDevice) { return new DropEffectAndLabel(DropEffectType.NONE, strf('DEVICE_WRITE_PROTECTED')); }
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index db662e1..2e2780c 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -243,6 +243,7 @@ <cr-menu-item command="#share-with-linux"></cr-menu-item> <cr-menu-item command="#manage-linux-sharing"></cr-menu-item> <hr visibleif="full-page"> + <cr-menu-item command="#format"></cr-menu-item> <cr-menu-item command="#rename"></cr-menu-item> <cr-menu-item command="#create-folder-shortcut"></cr-menu-item> <cr-menu-item command="#delete">$i18n{DELETE_BUTTON_LABEL}</cr-menu-item>
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index 70e6789e..35bfb1a 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -798,6 +798,7 @@ ]; const partition1Menus = [ ['#share-with-linux', true], + ['#format', true], ['#rename', false], ['#new-folder', true], ];
diff --git a/ui/file_manager/integration_tests/file_manager/transfer.js b/ui/file_manager/integration_tests/file_manager/transfer.js index eccbba0..65d3b90 100644 --- a/ui/file_manager/integration_tests/file_manager/transfer.js +++ b/ui/file_manager/integration_tests/file_manager/transfer.js
@@ -480,3 +480,79 @@ '', (await remoteCall.waitForElement(appId, '.progress-frame label')).text); }; + +/** + * Tests that we can drag a file from #file-list to #directory-tree. + * It copies the file from Downloads to Downloads/photos. + */ +testcase.transferDragAndDrop = async () => { + const entries = [ENTRIES.hello, ENTRIES.photos]; + + // Open files app. + const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, entries, []); + + // Expand Downloads to display "photos" folder in the directory tree. + await expandTreeItem(appId, '#directory-tree [entry-label="Downloads"]'); + + // Drag has to start in the file list column "name" text content, otherwise it + // starts a selection instead of a drag. + const src = + `#file-list li[file-name="${ENTRIES.hello.nameText}"] .entry-name`; + const dst = '#directory-tree [entry-label="photos"]'; + + // Select the file to be dragged. + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeMouseClick', appId, [src]), + 'fakeMouseClick failed'); + + // Drag and drop it. + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('fakeDragAndDrop', appId, [src, dst]), + 'fakeDragAndDrop failed'); + + // Navigate to the dst folder. + chrome.test.assertTrue( + !!await remoteCall.callRemoteTestUtil('fakeMouseClick', appId, [dst]), + 'fakeMouseClick failed'); + + // Wait for navigation to finish. + await remoteCall.waitUntilCurrentDirectoryIsChanged( + appId, '/My files/Downloads/photos'); + + // Wait for the expected files to appear in the file list. + await remoteCall.waitForFiles( + appId, TestEntryInfo.getExpectedRows([ENTRIES.hello]), + {ignoreLastModifiedTime: true}); +}; + +/** + * Tests that we can drag a file from #file-list and hover above USB root as + * EntryList without raising an error. + */ +testcase.transferDragAndHover = async () => { + const entries = [ENTRIES.hello, ENTRIES.photos]; + + await sendTestMessage({name: 'mountUsbWithPartitions'}); + await sendTestMessage({name: 'mountFakeUsb'}); + + // Open files app. + const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, entries, []); + + // Drag has to start in the file list column "name" text content, otherwise it + // starts a selection instead of a drag. + const src = + `#file-list li[file-name="${ENTRIES.hello.nameText}"] .entry-name`; + const dst1 = '#directory-tree [entry-label="Drive Label"]'; + const dst2 = '#directory-tree [entry-label="fake-usb"]'; + + // Wait for USB roots to be ready. + await remoteCall.waitForElement(appId, dst1); + await remoteCall.waitForElement(appId, dst2); + + // Drag and hover it. + const skipDrop = true; + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil( + 'fakeDragAndDrop', appId, [src, dst1, skipDrop]), + 'fakeDragAndDrop failed'); +};
diff --git a/ui/gl/gl_stub_api.cc b/ui/gl/gl_stub_api.cc index 144bc30..534a291 100644 --- a/ui/gl/gl_stub_api.cc +++ b/ui/gl/gl_stub_api.cc
@@ -6,15 +6,6 @@ namespace gl { -namespace { - -void GenHelper(GLsizei count, GLuint* objects) { - for (GLsizei i = 0; i < count; ++i) - objects[i] = i + 1; -} - -} // anonymous namespace - GLStubApi::GLStubApi() {} GLStubApi::~GLStubApi() = default;
diff --git a/ui/gl/gl_stub_api.h b/ui/gl/gl_stub_api.h index 01bd331..3b3baba 100644 --- a/ui/gl/gl_stub_api.h +++ b/ui/gl/gl_stub_api.h
@@ -72,8 +72,17 @@ GLboolean glUnmapBufferFn(GLenum target) override; private: + // The only consumers of GLStubApi are GpuChannelTestCommon (gpu_unittests) + // and GPU fuzzers. We get a new GLStubApi for every case executed by + // fuzzers, so we don't have to worry about ID exhaustion. + void GenHelper(GLsizei count, GLuint* objects) { + for (GLsizei i = 0; i < count; ++i) + objects[i] = next_id_++; + } + std::string version_; std::string extensions_; + GLuint next_id_ = 1; DISALLOW_COPY_AND_ASSIGN(GLStubApi); };
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 0ea28e02..76779020 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -123,6 +123,8 @@ "views/proportional_image_view.h", "views/slide_out_controller.cc", "views/slide_out_controller.h", + "views/timestamp_view.cc", + "views/timestamp_view.h", ] if (!is_chromeos) { sources += [ @@ -225,6 +227,7 @@ "views/message_popup_collection_unittest.cc", "views/notification_view_md_unittest.cc", "views/slide_out_controller_unittest.cc", + "views/timestamp_view_unittest.cc", ] if (!is_chromeos) { sources += [ @@ -237,6 +240,7 @@ # fonts used by bounded_label_unittest.cc. "//ui/compositor", "//ui/display", + "//ui/strings", "//ui/views", "//ui/views:test_support", ]
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc index 5bae6eb9..2fe528d13 100644 --- a/ui/message_center/views/notification_header_view.cc +++ b/ui/message_center/views/notification_header_view.cc
@@ -18,6 +18,7 @@ #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/vector_icons.h" #include "ui/message_center/views/notification_control_buttons_view.h" +#include "ui/message_center/views/timestamp_view.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/animation/ink_drop_stub.h" #include "ui/views/border.h" @@ -62,13 +63,6 @@ // Bullet character. The divider symbol between different parts of the header. constexpr wchar_t kNotificationHeaderDivider[] = L" \u2022 "; -// base::TimeBase has similar constants, but some of them are missing. -constexpr int64_t kMinuteInMillis = 60LL * 1000LL; -constexpr int64_t kHourInMillis = 60LL * kMinuteInMillis; -constexpr int64_t kDayInMillis = 24LL * kHourInMillis; -// In Android, DateUtils.YEAR_IN_MILLIS is 364 days. -constexpr int64_t kYearInMillis = 364LL * kDayInMillis; - // "Roboto-Regular, 12sp" is specified in the mock. constexpr int kHeaderTextFontSize = 12; @@ -119,35 +113,6 @@ node_data->SetName(tooltip_text()); } -// Do relative time string formatting that is similar to -// com.java.android.widget.DateTimeView.updateRelativeTime. -// Chromium has its own base::TimeFormat::Simple(), but none of the formats -// supported by the function is similar to Android's one. -base::string16 FormatToRelativeTime(base::Time past) { - base::Time now = base::Time::Now(); - int64_t duration = (now - past).InMilliseconds(); - if (duration < kMinuteInMillis) { - return l10n_util::GetStringUTF16( - IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST); - } else if (duration < kHourInMillis) { - int count = static_cast<int>(duration / kMinuteInMillis); - return l10n_util::GetPluralStringFUTF16( - IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST, count); - } else if (duration < kDayInMillis) { - int count = static_cast<int>(duration / kHourInMillis); - return l10n_util::GetPluralStringFUTF16( - IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST, count); - } else if (duration < kYearInMillis) { - int count = static_cast<int>(duration / kDayInMillis); - return l10n_util::GetPluralStringFUTF16( - IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST, count); - } else { - int count = static_cast<int>(duration / kYearInMillis); - return l10n_util::GetPluralStringFUTF16( - IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST, count); - } -} - gfx::FontList GetHeaderTextFontList() { gfx::Font default_font; int font_size_delta = kHeaderTextFontSize - default_font.GetFontSize(); @@ -266,7 +231,7 @@ AddChildView(timestamp_divider_); // Timestamp view - timestamp_view_ = new views::Label(base::string16()); + timestamp_view_ = new TimestampView(); timestamp_view_->SetFontList(font_list); timestamp_view_->SetLineHeight(font_list_height); timestamp_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); @@ -354,8 +319,8 @@ node_data->AddState(ax::mojom::State::kExpanded); } -void NotificationHeaderView::SetTimestamp(base::Time past) { - timestamp_view_->SetText(FormatToRelativeTime(past)); +void NotificationHeaderView::SetTimestamp(base::Time timestamp) { + timestamp_view_->SetTimestamp(timestamp); has_timestamp_ = true; UpdateSummaryTextVisibility(); }
diff --git a/ui/message_center/views/notification_header_view.h b/ui/message_center/views/notification_header_view.h index edca12d..feb4ac4 100644 --- a/ui/message_center/views/notification_header_view.h +++ b/ui/message_center/views/notification_header_view.h
@@ -14,11 +14,12 @@ namespace views { class ImageView; class Label; -} +} // namespace views namespace message_center { class NotificationControlButtonsView; +class TimestampView; class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button { public: @@ -29,7 +30,7 @@ void SetAppNameElideBehavior(gfx::ElideBehavior elide_behavior); void SetProgress(int progress); void SetOverflowIndicator(int count); - void SetTimestamp(base::Time past); + void SetTimestamp(base::Time timestamp); void SetExpandButtonEnabled(bool enabled); void SetExpanded(bool expanded); void SetSettingsButtonEnabled(bool enabled); @@ -67,7 +68,7 @@ views::Label* summary_text_divider_ = nullptr; views::Label* summary_text_view_ = nullptr; views::Label* timestamp_divider_ = nullptr; - views::Label* timestamp_view_ = nullptr; + TimestampView* timestamp_view_ = nullptr; views::ImageView* app_icon_view_ = nullptr; views::ImageView* expand_button_ = nullptr;
diff --git a/ui/message_center/views/timestamp_view.cc b/ui/message_center/views/timestamp_view.cc new file mode 100644 index 0000000..cc8d477 --- /dev/null +++ b/ui/message_center/views/timestamp_view.cc
@@ -0,0 +1,71 @@ +// Copyright 2019 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/message_center/views/timestamp_view.h" + +#include "base/strings/string16.h" +#include "base/time/time.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/strings/grit/ui_strings.h" + +namespace message_center { + +namespace { + +// base::TimeBase has similar constants, but some of them are missing. +constexpr int64_t kMinuteInMillis = 60LL * 1000LL; +constexpr int64_t kHourInMillis = 60LL * kMinuteInMillis; +constexpr int64_t kDayInMillis = 24LL * kHourInMillis; +// In Android, DateUtils.YEAR_IN_MILLIS is 364 days. +constexpr int64_t kYearInMillis = 364LL * kDayInMillis; + +// Do relative time string formatting that is similar to +// com.java.android.widget.DateTimeView.updateRelativeTime. +// Chromium has its own base::TimeFormat::Simple(), but none of the formats +// supported by the function is similar to Android's one. +base::string16 FormatToRelativeTime(base::TimeDelta delta) { + int64_t duration = std::abs(delta.InMilliseconds()); + bool past = delta <= base::TimeDelta(); + if (duration < kMinuteInMillis) { + return l10n_util::GetStringUTF16( + IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST); + } else if (duration < kHourInMillis) { + int count = static_cast<int>(duration / kMinuteInMillis); + return l10n_util::GetPluralStringFUTF16( + past ? IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST + : IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE, + count); + } else if (duration < kDayInMillis) { + int count = static_cast<int>(duration / kHourInMillis); + return l10n_util::GetPluralStringFUTF16( + past ? IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST + : IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, + count); + } else if (duration < kYearInMillis) { + // TODO(https://crbug.com/914432): Use a calendar to calculate this. + int count = static_cast<int>(duration / kDayInMillis); + return l10n_util::GetPluralStringFUTF16( + past ? IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST + : IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST_FUTURE, + count); + } else { + int count = static_cast<int>(duration / kYearInMillis); + return l10n_util::GetPluralStringFUTF16( + past ? IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST + : IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE, + count); + } +} + +} // namespace + +TimestampView::TimestampView() = default; + +TimestampView::~TimestampView() = default; + +void TimestampView::SetTimestamp(base::Time timestamp) { + SetText(FormatToRelativeTime(timestamp - base::Time::Now())); +} + +} // namespace message_center
diff --git a/ui/message_center/views/timestamp_view.h b/ui/message_center/views/timestamp_view.h new file mode 100644 index 0000000..9a322f18 --- /dev/null +++ b/ui/message_center/views/timestamp_view.h
@@ -0,0 +1,29 @@ +// Copyright 2019 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_MESSAGE_CENTER_VIEWS_TIMESTAMP_VIEW_H_ +#define UI_MESSAGE_CENTER_VIEWS_TIMESTAMP_VIEW_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "ui/message_center/message_center_export.h" +#include "ui/views/controls/label.h" + +namespace message_center { + +class MESSAGE_CENTER_EXPORT TimestampView : public views::Label { + public: + TimestampView(); + ~TimestampView() override; + + // Formats |timestamp| relative to base::Time::Now(). + void SetTimestamp(base::Time timestamp); + + private: + DISALLOW_COPY_AND_ASSIGN(TimestampView); +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_VIEWS_TIMESTAMP_VIEW_H_
diff --git a/ui/message_center/views/timestamp_view_unittest.cc b/ui/message_center/views/timestamp_view_unittest.cc new file mode 100644 index 0000000..e6be720 --- /dev/null +++ b/ui/message_center/views/timestamp_view_unittest.cc
@@ -0,0 +1,167 @@ +// Copyright 2019 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/message_center/views/timestamp_view.h" + +#include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/strings/grit/ui_strings.h" +#include "ui/views/test/views_test_base.h" + +namespace message_center { + +namespace { + +// In Android, DateUtils.YEAR_IN_MILLIS is 364 days. +constexpr int64_t kYearInMillis = 364LL * base::Time::kMillisecondsPerDay; +constexpr base::TimeDelta kTimeAdvance = base::TimeDelta::FromMilliseconds(1); + +} // namespace + +class TimestampViewTest : public views::ViewsTestBase { + public: + TimestampViewTest() = default; + ~TimestampViewTest() override = default; + + // ViewsTestBase: + void SetUp() override { + // Setup a mocked time environment. + scoped_task_environment_ = new ScopedTaskEnvironment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME, + ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME); + set_scoped_task_environment(base::WrapUnique(scoped_task_environment_)); + + // Advance time a little bit so that TimeTicks::Now().is_null() becomes + // false. + scoped_task_environment_->FastForwardBy(kTimeAdvance); + + ViewsTestBase::SetUp(); + + views::Widget::InitParams params = + CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.bounds = gfx::Rect(200, 200); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget_.Init(params); + views::View* container = new views::View(); + widget_.SetContentsView(container); + + timestamp_view_ = new TimestampView(); + container->AddChildView(timestamp_view_); + + widget_.Show(); + } + + void TearDown() override { + widget_.Close(); + ViewsTestBase::TearDown(); + } + + protected: + TimestampView* view() { return timestamp_view_; } + + private: + TimestampView* timestamp_view_ = nullptr; + views::Widget widget_; + ScopedTaskEnvironment* scoped_task_environment_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(TimestampViewTest); +}; + +TEST_F(TimestampViewTest, FormatToRelativeTime) { + // Test 30 seconds in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromSeconds(30)); + EXPECT_EQ( + l10n_util::GetStringUTF16(IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST), + view()->text()); + // Test 30 seconds in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromSeconds(-30)); + EXPECT_EQ( + l10n_util::GetStringUTF16(IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST), + view()->text()); + + // Test 60 seconds in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromSeconds(60)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE, 1), + view()->text()); + // Test 60 seconds in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromSeconds(-60)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST, 1), + view()->text()); + + // Test 5 minutes in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromMinutes(5)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE, 5), + view()->text()); + // Test 5 minutes in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromMinutes(-5)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST, 5), + view()->text()); + + // Test 60 minutes in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromMinutes(60)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, 1), + view()->text()); + // Test 60 minutes in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromMinutes(-60)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST, 1), + view()->text()); + + // Test 10 hours in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromHours(10)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, 10), + view()->text()); + // Test 10 hours in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromHours(-10)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST, 10), + view()->text()); + + // Test 24 hours in the future. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromHours(24)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST_FUTURE, 1), + view()->text()); + // Test 24 hours in the past. + view()->SetTimestamp(base::Time::Now() + base::TimeDelta::FromHours(-24)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST, 1), + view()->text()); + + // Test 1 year in the future. + view()->SetTimestamp(base::Time::Now() + + base::TimeDelta::FromMilliseconds(kYearInMillis)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE, 1), + view()->text()); + // Test 1 year in the past. + view()->SetTimestamp(base::Time::Now() + + base::TimeDelta::FromMilliseconds(-kYearInMillis)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST, 1), + view()->text()); + + // Test 10 years in the future. + view()->SetTimestamp(base::Time::Now() + + base::TimeDelta::FromMilliseconds(kYearInMillis * 10)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE, 10), + view()->text()); + // Test 10 years in the past. + view()->SetTimestamp(base::Time::Now() + + base::TimeDelta::FromMilliseconds(-kYearInMillis * 10)); + EXPECT_EQ(l10n_util::GetPluralStringFUTF16( + IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST, 10), + view()->text()); +} + +} // namespace message_center
diff --git a/ui/ozone/platform/wayland/test/test_data_source.cc b/ui/ozone/platform/wayland/test/test_data_source.cc index ade78494..a0ef41e7 100644 --- a/ui/ozone/platform/wayland/test/test_data_source.cc +++ b/ui/ozone/platform/wayland/test/test_data_source.cc
@@ -5,6 +5,7 @@ #include "ui/ozone/platform/wayland/test/test_data_source.h" #include <wayland-server-core.h> +#include <utility> #include "base/bind.h" #include "base/files/file_util.h" @@ -30,13 +31,13 @@ bytes.insert(bytes.end(), chunk, chunk + bytes_read); continue; } - if (!bytes_read) - return bytes; if (bytes_read < 0) { - LOG(ERROR) << "Failed to read selection data from clipboard."; - return std::vector<uint8_t>(); + PLOG(ERROR) << "Failed to read data"; + bytes.clear(); } + break; } + return bytes; } void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { @@ -70,8 +71,7 @@ TestDataSource::TestDataSource(wl_resource* resource) : ServerObject(resource), task_runner_( - base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})), - read_data_weak_ptr_factory_(this) {} + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})) {} TestDataSource::~TestDataSource() {} @@ -79,30 +79,23 @@ NOTIMPLEMENTED(); } -void TestDataSource::ReadData(ReadDataCallback callback) { +void TestDataSource::ReadData(const std::string& mime_type, + ReadDataCallback callback) { base::ScopedFD read_fd; base::ScopedFD write_fd; CreatePipe(&read_fd, &write_fd); // 1. Send the SEND event to notify client's DataSource that it's time // to send us the drag data thrhough the write_fd file descriptor. - wl_data_source_send_send(resource(), kTextMimeTypeUtf8, write_fd.get()); + wl_data_source_send_send(resource(), mime_type.c_str(), write_fd.get()); wl_client_flush(wl_resource_get_client(resource())); // 2. Schedule the ReadDataOnWorkerThread task. The result of read - // operation will be delivered through TestDataSource::DataReadCb, - // which will then call the callback function requested by the caller. - PostTaskAndReplyWithResult( + // operation will be then passed in to the callback requested by the caller. + base::PostTaskAndReplyWithResult( task_runner_.get(), FROM_HERE, base::BindOnce(&ReadDataOnWorkerThread, std::move(read_fd)), - base::BindOnce(&TestDataSource::DataReadCb, - read_data_weak_ptr_factory_.GetWeakPtr(), - std::move(callback))); -} - -void TestDataSource::DataReadCb(ReadDataCallback callback, - const std::vector<uint8_t>& data) { - std::move(callback).Run(data); + std::move(callback)); } void TestDataSource::OnCancelled() {
diff --git a/ui/ozone/platform/wayland/test/test_data_source.h b/ui/ozone/platform/wayland/test/test_data_source.h index 4d62962..32592071 100644 --- a/ui/ozone/platform/wayland/test/test_data_source.h +++ b/ui/ozone/platform/wayland/test/test_data_source.h
@@ -5,12 +5,12 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_DATA_SOURCE_H_ #define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_DATA_SOURCE_H_ +#include <wayland-server-protocol-core.h> + #include <memory> #include <string> #include <vector> -#include <wayland-server-protocol-core.h> - #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "ui/ozone/platform/wayland/test/server_object.h" @@ -32,17 +32,13 @@ void Offer(const std::string& mime_type); - using ReadDataCallback = - base::OnceCallback<void(const std::vector<uint8_t>&)>; - void ReadData(ReadDataCallback); + using ReadDataCallback = base::OnceCallback<void(std::vector<uint8_t>&&)>; + void ReadData(const std::string& mime_type, ReadDataCallback callback); void OnCancelled(); private: - void DataReadCb(ReadDataCallback callback, const std::vector<uint8_t>& data); - const scoped_refptr<base::SequencedTaskRunner> task_runner_; - base::WeakPtrFactory<TestDataSource> read_data_weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(TestDataSource); };
diff --git a/ui/ozone/platform/wayland/wayland_data_device_unittest.cc b/ui/ozone/platform/wayland/wayland_data_device_unittest.cc index 5aff53a6..54c5905 100644 --- a/ui/ozone/platform/wayland/wayland_data_device_unittest.cc +++ b/ui/ozone/platform/wayland/wayland_data_device_unittest.cc
@@ -29,7 +29,7 @@ // OzonePlatform::GetPlatformClipboard. class MockClipboardClient { public: - MockClipboardClient(WaylandConnection* connection) { + explicit MockClipboardClient(WaylandConnection* connection) { DCHECK(connection); // See comment above for reasoning to access the WaylandConnection // directly from here. @@ -99,19 +99,20 @@ // ... and the server reads it. base::RunLoop run_loop; auto callback = base::BindOnce( - [](base::RunLoop* loop, const std::vector<uint8_t>& data) { + [](base::RunLoop* loop, std::vector<uint8_t>&& data) { std::string string_data(data.begin(), data.end()); EXPECT_EQ(wl::kSampleClipboardText, string_data); loop->Quit(); }, &run_loop); - data_device_manager_->data_source()->ReadData(std::move(callback)); + data_device_manager_->data_source()->ReadData(wl::kTextMimeTypeUtf8, + std::move(callback)); run_loop.Run(); } TEST_P(WaylandDataDeviceManagerTest, ReadFromClibpard) { - // TODO: implement this in terms of an actual wl_surface that gets - // focused and compositor sends data_device data to it. + // TODO(nickdiego): implement this in terms of an actual wl_surface that + // gets focused and compositor sends data_device data to it. auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); data_offer->OnOffer(wl::kTextMimeTypeUtf8); data_device_manager_->data_device()->OnSelection(data_offer); @@ -150,10 +151,9 @@ window_->set_pointer_focus(true); // The client starts dragging. - std::unique_ptr<OSExchangeData> os_exchange_data = - std::make_unique<OSExchangeData>(); + OSExchangeData os_exchange_data; int operation = DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE; - connection_->StartDrag(*os_exchange_data, operation); + connection_->StartDrag(os_exchange_data, operation); WaylandDataSource::DragDataMap data; data[wl::kTextMimeTypeUtf8] = wl::kSampleTextForDragAndDrop; @@ -163,13 +163,45 @@ // The server reads the data and the callback gets it. base::RunLoop run_loop; auto callback = base::BindOnce( - [](base::RunLoop* loop, const std::vector<uint8_t>& data) { + [](base::RunLoop* loop, std::vector<uint8_t>&& data) { std::string result(data.begin(), data.end()); EXPECT_EQ(wl::kSampleTextForDragAndDrop, result); loop->Quit(); }, &run_loop); - data_device_manager_->data_source()->ReadData(std::move(callback)); + data_device_manager_->data_source()->ReadData(wl::kTextMimeTypeUtf8, + std::move(callback)); + run_loop.Run(); + window_->set_pointer_focus(restored_focus); +} + +TEST_P(WaylandDataDeviceManagerTest, StartDragWithWrongMimeType) { + bool restored_focus = window_->has_pointer_focus(); + window_->set_pointer_focus(true); + + // The client starts dragging offering data with wl::kTextMimeTypeUtf8 + // mime type. + OSExchangeData os_exchange_data; + int operation = DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE; + connection_->StartDrag(os_exchange_data, operation); + + WaylandDataSource::DragDataMap data; + data[wl::kTextMimeTypeUtf8] = wl::kSampleTextForDragAndDrop; + connection_->drag_data_source()->SetDragData(data); + Sync(); + + // The server should get an empty data buffer in ReadData callback + // when trying to read it. + base::RunLoop run_loop; + auto callback = base::BindOnce( + [](base::RunLoop* loop, std::vector<uint8_t>&& data) { + std::string result(data.begin(), data.end()); + EXPECT_EQ("", result); + loop->Quit(); + }, + &run_loop); + data_device_manager_->data_source()->ReadData(wl::kTextMimeTypeText, + std::move(callback)); run_loop.Run(); window_->set_pointer_focus(restored_focus); }
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 7017d9c..6de181ea 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -728,6 +728,18 @@ <message name="IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST" desc="Phrase describing a time duration using years that is as short as possible, preferrably one character. Should be same as AndroidPlatform msgId 7848711145196397042. (frameworks/base/core/res/res/values/strings.xml:plurals:duration_years_shortest) [ICU Syntax]"> {YEARS, plural, =1 {1y} other {#y}} </message> + <message name="IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE" desc="Phrase describing a time duration using minutes that is as short as possible, preferrably one character. This version should be a future point in time. Should be same as AndroidPlatform msgId 3277614521231489951. (frameworks/base/core/res/res/values/strings.xml:plurals:duration_minutes_shortest_future) [ICU Syntax]"> + {MINUTES, plural, =1 {in 1m} other {in #m}} + </message> + <message name="IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE" desc="Phrase describing a time duration using hours that is as short as possible, preferrably one character. This version should be a future point in time. Should be same as AndroidPlatform msgId 2152452368397489370. (frameworks/base/core/res/res/values/strings.xml:plurals:duration_hours_shortest_future) [ICU Syntax]"> + {HOURS, plural, =1 {in 1h} other {in #h}} + </message> + <message name="IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST_FUTURE" desc="Phrase describing a time duration using days that is as short as possible, preferrably one character. This version should be a future point in time. Should be same as AndroidPlatform msgId 8088331502820295701. (frameworks/base/core/res/res/values/strings.xml:plurals:duration_days_shortest_future) [ICU Syntax]"> + {DAYS, plural, =1 {in 1d} other {in #d}} + </message> + <message name="IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE" desc="Phrase describing a time duration using years that is as short as possible, preferrably one character. This version should be a future point in time. Should be same as AndroidPlatform msgId 2317006667145250301. (frameworks/base/core/res/res/values/strings.xml:plurals:duration_years_shortest_future) [ICU Syntax]"> + {YEARS, plural, =1 {in 1y} other {in #y}} + </message> <message name="IDS_MESSAGE_CENTER_BLOCK_ALL_NOTIFICATIONS_SITE" desc="The label for the radio button to block all the notifications from this notification origin."> Block all notifications from this site </message>
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 9b0c450..8c4cb159 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -626,10 +626,10 @@ // Allow |menu_runner_| to be set by the testing API, but if this method is // ever invoked recursively, ensure the old menu is closed. if (!menu_runner_ || menu_runner_->IsRunning()) { - menu_runner_.reset( - new MenuRunner(menu_model_.get(), MenuRunner::COMBOBOX, - base::Bind(&Combobox::OnMenuClosed, - base::Unretained(this), original_state))); + menu_runner_.reset(new MenuRunner( + menu_model_.get(), MenuRunner::COMBOBOX, + base::BindRepeating(&Combobox::OnMenuClosed, base::Unretained(this), + original_state))); } menu_runner_->RunMenuAt(GetWidget(), nullptr, bounds, MENU_ANCHOR_TOPLEFT, source_type);
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index 6169d04..78e4224 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -362,9 +362,6 @@ ~MenuController() override; - // Runs the platform specific bits of the message loop. - void RunMessageLoop(); - // Invokes AcceleratorPressed() on the hot tracked view if there is one. // Returns true if AcceleratorPressed() was invoked. bool SendAcceleratorToHotTrackedView();
diff --git a/ui/views/controls/menu/menu_model_adapter.cc b/ui/views/controls/menu/menu_model_adapter.cc index 03186888..6fa4fcd 100644 --- a/ui/views/controls/menu/menu_model_adapter.cc +++ b/ui/views/controls/menu/menu_model_adapter.cc
@@ -13,10 +13,12 @@ namespace views { MenuModelAdapter::MenuModelAdapter(ui::MenuModel* menu_model) - : MenuModelAdapter(menu_model, base::Closure() /*null callback*/) {} + : MenuModelAdapter(menu_model, base::RepeatingClosure() /*null callback*/) { +} -MenuModelAdapter::MenuModelAdapter(ui::MenuModel* menu_model, - const base::Closure& on_menu_closed_callback) +MenuModelAdapter::MenuModelAdapter( + ui::MenuModel* menu_model, + const base::RepeatingClosure& on_menu_closed_callback) : menu_model_(menu_model), triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON),
diff --git a/ui/views/controls/menu/menu_model_adapter.h b/ui/views/controls/menu/menu_model_adapter.h index 240525c..2e4b8f9 100644 --- a/ui/views/controls/menu/menu_model_adapter.h +++ b/ui/views/controls/menu/menu_model_adapter.h
@@ -30,7 +30,7 @@ // reflected in the created MenuItemView. explicit MenuModelAdapter(ui::MenuModel* menu_model); MenuModelAdapter(ui::MenuModel* menu_model, - const base::Closure& on_menu_closed_callback); + const base::RepeatingClosure& on_menu_closed_callback); ~MenuModelAdapter() override; // Populate a MenuItemView menu with the ui::MenuModel items @@ -108,7 +108,7 @@ std::map<MenuItemView*, ui::MenuModel*> menu_map_; // Optional callback triggered during OnMenuClosed(). - base::Closure on_menu_closed_callback_; + base::RepeatingClosure on_menu_closed_callback_; DISALLOW_COPY_AND_ASSIGN(MenuModelAdapter); };
diff --git a/ui/views/controls/menu/menu_runner.cc b/ui/views/controls/menu/menu_runner.cc index bd16bfc..b0a2f3d 100644 --- a/ui/views/controls/menu/menu_runner.cc +++ b/ui/views/controls/menu/menu_runner.cc
@@ -14,7 +14,7 @@ MenuRunner::MenuRunner(ui::MenuModel* menu_model, int32_t run_types, - const base::Closure& on_menu_closed_callback) + const base::RepeatingClosure& on_menu_closed_callback) : run_types_(run_types), impl_( internal::MenuRunnerImplInterface::Create(menu_model,
diff --git a/ui/views/controls/menu/menu_runner.h b/ui/views/controls/menu/menu_runner.h index 967f6f2..549d859 100644 --- a/ui/views/controls/menu/menu_runner.h +++ b/ui/views/controls/menu/menu_runner.h
@@ -114,7 +114,8 @@ // The MenuModelDelegate of |menu_model| will be overwritten by this call. MenuRunner(ui::MenuModel* menu_model, int32_t run_types, - const base::Closure& on_menu_closed_callback = base::Closure()); + const base::RepeatingClosure& on_menu_closed_callback = + base::RepeatingClosure()); // Creates a runner for a custom-created toolkit-views menu. MenuRunner(MenuItemView* menu, int32_t run_types);
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm index 89c0fc28..4f9dd1e 100644 --- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm +++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -110,8 +110,8 @@ native_view_subview_count_ = [[parent_->GetNativeView().GetNativeNSView() subviews] count]; - base::Closure on_close = base::Bind(&MenuRunnerCocoaTest::MenuCloseCallback, - base::Unretained(this)); + base::RepeatingClosure on_close = base::BindRepeating( + &MenuRunnerCocoaTest::MenuCloseCallback, base::Unretained(this)); if (GetParam() == MenuType::NATIVE) runner_ = new internal::MenuRunnerImplCocoa(menu_.get(), on_close); else @@ -296,7 +296,7 @@ QuitAsyncRunLoop(); } - base::Closure quit_closure_; + base::RepeatingClosure quit_closure_; DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest); };
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc index bab3051..ad08635 100644 --- a/ui/views/controls/menu/menu_runner_impl.cc +++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -28,7 +28,7 @@ MenuRunnerImplInterface* MenuRunnerImplInterface::Create( ui::MenuModel* menu_model, int32_t run_types, - const base::Closure& on_menu_closed_callback) { + const base::RepeatingClosure& on_menu_closed_callback) { return new MenuRunnerImplAdapter(menu_model, on_menu_closed_callback); } #endif
diff --git a/ui/views/controls/menu/menu_runner_impl_adapter.cc b/ui/views/controls/menu/menu_runner_impl_adapter.cc index 8b6c0a5..4feef7b 100644 --- a/ui/views/controls/menu/menu_runner_impl_adapter.cc +++ b/ui/views/controls/menu/menu_runner_impl_adapter.cc
@@ -12,7 +12,7 @@ MenuRunnerImplAdapter::MenuRunnerImplAdapter( ui::MenuModel* menu_model, - const base::Closure& on_menu_done_callback) + const base::RepeatingClosure& on_menu_done_callback) : menu_model_adapter_( new MenuModelAdapter(menu_model, on_menu_done_callback)), impl_(new MenuRunnerImpl(menu_model_adapter_->CreateMenu())) {}
diff --git a/ui/views/controls/menu/menu_runner_impl_adapter.h b/ui/views/controls/menu/menu_runner_impl_adapter.h index e70d7b60..c1b15458c 100644 --- a/ui/views/controls/menu/menu_runner_impl_adapter.h +++ b/ui/views/controls/menu/menu_runner_impl_adapter.h
@@ -23,7 +23,7 @@ class VIEWS_EXPORT MenuRunnerImplAdapter : public MenuRunnerImplInterface { public: MenuRunnerImplAdapter(ui::MenuModel* menu_model, - const base::Closure& on_menu_closed_callback); + const base::RepeatingClosure& on_menu_closed_callback); // MenuRunnerImplInterface: bool IsRunning() const override;
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.h b/ui/views/controls/menu/menu_runner_impl_cocoa.h index 599000d..0104753 100644 --- a/ui/views/controls/menu/menu_runner_impl_cocoa.h +++ b/ui/views/controls/menu/menu_runner_impl_cocoa.h
@@ -25,7 +25,7 @@ class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface { public: MenuRunnerImplCocoa(ui::MenuModel* menu, - const base::Closure& on_menu_closed_callback); + const base::RepeatingClosure& on_menu_closed_callback); bool IsRunning() const override; void Release() override; @@ -55,7 +55,7 @@ base::TimeTicks closing_event_time_; // Invoked before RunMenuAt() returns, except upon a Release(). - base::Closure on_menu_closed_callback_; + base::RepeatingClosure on_menu_closed_callback_; DISALLOW_COPY_AND_ASSIGN(MenuRunnerImplCocoa); };
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm index f67cdcbd..4886786 100644 --- a/ui/views/controls/menu/menu_runner_impl_cocoa.mm +++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -122,7 +122,7 @@ MenuRunnerImplInterface* MenuRunnerImplInterface::Create( ui::MenuModel* menu_model, int32_t run_types, - const base::Closure& on_menu_closed_callback) { + const base::RepeatingClosure& on_menu_closed_callback) { if ((run_types & MenuRunner::CONTEXT_MENU) && !(run_types & MenuRunner::IS_NESTED)) { return new MenuRunnerImplCocoa(menu_model, on_menu_closed_callback); @@ -132,7 +132,7 @@ MenuRunnerImplCocoa::MenuRunnerImplCocoa( ui::MenuModel* menu, - const base::Closure& on_menu_closed_callback) + const base::RepeatingClosure& on_menu_closed_callback) : running_(false), delete_after_run_(false), closing_event_time_(base::TimeTicks()),
diff --git a/ui/views/controls/menu/menu_runner_impl_interface.h b/ui/views/controls/menu/menu_runner_impl_interface.h index f6e5bd0..9661f40 100644 --- a/ui/views/controls/menu/menu_runner_impl_interface.h +++ b/ui/views/controls/menu/menu_runner_impl_interface.h
@@ -26,7 +26,7 @@ static MenuRunnerImplInterface* Create( ui::MenuModel* menu_model, int32_t run_types, - const base::Closure& on_menu_closed_callback); + const base::RepeatingClosure& on_menu_closed_callback); // Returns true if we're in a nested run loop running the menu. virtual bool IsRunning() const = 0;
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc index 377b8fa..6f0a067b 100644 --- a/ui/views/controls/scroll_view_unittest.cc +++ b/ui/views/controls/scroll_view_unittest.cc
@@ -325,7 +325,7 @@ // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default. bool use_overlay_scrollers_ = false; - base::Closure quit_closure_; + base::RepeatingClosure quit_closure_; #if defined(OS_MACOSX) std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_;
diff --git a/ui/views/linux_ui/linux_ui.h b/ui/views/linux_ui/linux_ui.h index 9206e18..c1b3a57b 100644 --- a/ui/views/linux_ui/linux_ui.h +++ b/ui/views/linux_ui/linux_ui.h
@@ -79,8 +79,8 @@ kRightClick, }; - typedef base::Callback<ui::NativeTheme*(aura::Window* window)> - NativeThemeGetter; + using NativeThemeGetter = + base::RepeatingCallback<ui::NativeTheme*(aura::Window* window)>; ~LinuxUI() override {} @@ -114,7 +114,7 @@ virtual ui::NativeTheme* GetNativeTheme(aura::Window* window) const = 0; // Used to set an override NativeTheme. - virtual void SetNativeThemeOverride(const NativeThemeGetter& callback) = 0; + virtual void SetNativeThemeOverride(NativeThemeGetter callback) = 0; // Returns whether we should be using the native theme provided by this // object by default.
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc index 3b0cda498..22a3a4b 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.cc +++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -151,10 +151,10 @@ }; void OnMoveLoopEnd(bool* out_success, - base::Closure quit_closure, + base::OnceClosure quit_closure, bool in_success) { *out_success = in_success; - quit_closure.Run(); + std::move(quit_closure).Run(); } } // namespace
diff --git a/ui/views/test/x11_property_change_waiter.cc b/ui/views/test/x11_property_change_waiter.cc index 5747ee6b..f4ca1952 100644 --- a/ui/views/test/x11_property_change_waiter.cc +++ b/ui/views/test/x11_property_change_waiter.cc
@@ -4,6 +4,8 @@ #include "ui/views/test/x11_property_change_waiter.h" +#include <utility> + #include "base/run_loop.h" #include "ui/base/x/x11_window_event_manager.h" #include "ui/events/platform/platform_event_source.h" @@ -64,7 +66,7 @@ wait_ = false; if (!quit_closure_.is_null()) - quit_closure_.Run(); + std::move(quit_closure_).Run(); return ui::POST_DISPATCH_PERFORM_DEFAULT; }
diff --git a/ui/views/test/x11_property_change_waiter.h b/ui/views/test/x11_property_change_waiter.h index 7f1eec3f..1ab020a 100644 --- a/ui/views/test/x11_property_change_waiter.h +++ b/ui/views/test/x11_property_change_waiter.h
@@ -53,7 +53,7 @@ bool wait_; // Ends the run loop. - base::Closure quit_closure_; + base::OnceClosure quit_closure_; std::unique_ptr<ui::ScopedEventDispatcher> dispatcher_;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc index 58f5681..bc93e06 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -343,8 +343,8 @@ } void QuitNestedLoopAndCloseWidget(std::unique_ptr<Widget> widget, - base::Closure* quit_runloop) { - quit_runloop->Run(); + base::OnceClosure quit_runloop) { + std::move(quit_runloop).Run(); } // Verifies that a widget can be destroyed when running a nested message-loop. @@ -360,11 +360,9 @@ // task will be executed from the nested loop initiated with the call to // |RunWithDispatcher()| below. base::RunLoop run_loop; - base::Closure quit_runloop = run_loop.QuitClosure(); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&QuitNestedLoopAndCloseWidget, std::move(widget), - base::Unretained(&quit_runloop))); + FROM_HERE, base::BindOnce(&QuitNestedLoopAndCloseWidget, + std::move(widget), run_loop.QuitClosure())); run_loop.Run(); }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index 6f98928..d460531 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -2366,8 +2366,7 @@ return gfx::ToEnclosingRect(rect_in_pixels); } -std::unique_ptr<base::Closure> -DesktopWindowTreeHostX11::DisableEventListening() { +base::OnceClosure DesktopWindowTreeHostX11::DisableEventListening() { // Allows to open multiple file-pickers. See https://crbug.com/678982 modal_dialog_counter_++; if (modal_dialog_counter_ == 1) { @@ -2377,9 +2376,8 @@ window(), std::make_unique<aura::NullWindowTargeter>()); } - return std::make_unique<base::Closure>( - base::Bind(&DesktopWindowTreeHostX11::EnableEventListening, - weak_factory_.GetWeakPtr())); + return base::BindOnce(&DesktopWindowTreeHostX11::EnableEventListening, + weak_factory_.GetWeakPtr()); } void DesktopWindowTreeHostX11::EnableEventListening() {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index c547609..43bd1f4e 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -86,7 +86,7 @@ static void CleanUpWindowList(void (*func)(aura::Window* window)); // Disables event listening to make |dialog| modal. - std::unique_ptr<base::Closure> DisableEventListening(); + base::OnceClosure DisableEventListening(); // Returns a map of KeyboardEvent code to KeyboardEvent key values. base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc index eb61fb3..f6a6d7b 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -162,12 +162,6 @@ return false; } -// Flush the message loop. -void RunAllPendingInMessageLoop() { - base::RunLoop run_loop; - run_loop.RunUntilIdle(); -} - } // namespace class DesktopWindowTreeHostX11Test : public ViewsTestBase { @@ -259,7 +253,7 @@ } // Ensure that the task which is posted when a window is resized is run. - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // xvfb does not support Xrandr so we cannot check the maximized window's // bounds.
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index 593f24d..fb7313d4 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
@@ -234,7 +234,7 @@ grab_input_window_ = x11::None; in_move_loop_ = false; - quit_closure_.Run(); + std::move(quit_closure_).Run(); } bool X11WholeScreenMoveLoop::GrabPointer(gfx::NativeCursor cursor) {
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h index 37c718e..62631fa2 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
@@ -84,7 +84,7 @@ // Whether the pointer was grabbed on |grab_input_window_|. bool grabbed_pointer_; - base::Closure quit_closure_; + base::OnceClosure quit_closure_; // Keeps track of whether the move-loop is cancled by the user (e.g. by // pressing escape).
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index 6bc26ab..533f137 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc
@@ -7,6 +7,7 @@ #include <set> #include "base/bind.h" +#include "base/callback.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" @@ -2182,22 +2183,22 @@ // destroyed. class CloseDestroysWidget : public Widget { public: - explicit CloseDestroysWidget(bool* destroyed) - : destroyed_(destroyed) { + CloseDestroysWidget(bool* destroyed, base::OnceClosure quit_closure) + : destroyed_(destroyed), quit_closure_(std::move(quit_closure)) { + DCHECK(destroyed_); + DCHECK(quit_closure_); } ~CloseDestroysWidget() override { - if (destroyed_) { - *destroyed_ = true; - base::RunLoop::QuitCurrentDeprecated(); - } + *destroyed_ = true; + std::move(quit_closure_).Run(); } void Detach() { destroyed_ = NULL; } private: - // If non-null set to true from destructor. bool* destroyed_; + base::OnceClosure quit_closure_; DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget); }; @@ -2243,7 +2244,9 @@ // Verifies Close() results in destroying. TEST_F(DesktopWidgetTest, CloseDestroys) { bool destroyed = false; - CloseDestroysWidget* widget = new CloseDestroysWidget(&destroyed); + base::RunLoop run_loop; + CloseDestroysWidget* widget = + new CloseDestroysWidget(&destroyed, run_loop.QuitClosure()); Widget::InitParams params = CreateParams(views::Widget::InitParams::TYPE_MENU); params.opacity = Widget::InitParams::OPAQUE_WINDOW; @@ -2253,7 +2256,7 @@ widget->Close(); EXPECT_FALSE(destroyed); // Run the message loop as Close() asynchronously deletes. - base::RunLoop().Run(); + run_loop.Run(); EXPECT_TRUE(destroyed); // Close() should destroy the widget. If not we'll cleanup to avoid leaks. if (!destroyed) {
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html index 5b8ba4f..3b4cff4c 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
@@ -14,13 +14,16 @@ --cr-toolbar-height: 56px; --paper-icon-button-ink-color: white; align-items: center; - /* TODO(dbeam): default background-color instead of external styling. */ + background-color: var(--google-blue-700); color: #fff; display: flex; height: var(--cr-toolbar-height); } :host-context([dark]) { + background-color: rgba(255, 255, 255, .04); + border-bottom: var(--cr-separator-line); + box-sizing: border-box; color: var(--cr-secondary-text-color); }
diff --git a/ui/webui/resources/css/md_colors.css b/ui/webui/resources/css/md_colors.css index 28a2dc1..9750520 100644 --- a/ui/webui/resources/css/md_colors.css +++ b/ui/webui/resources/css/md_colors.css
@@ -9,10 +9,13 @@ --md-loading-message-color: #6e6e6e; /* --google-blue-700, rewritten as a native custom property for speed. */ --md-toolbar-color: rgb(51, 103, 214); + --md-toolbar-height: 56px; } html[dark] { --md-background-color: rgb(32, 33, 36); /* --google-grey-900 */ --md-loading-message-color: #9AA0A6; /* --google-grey-refresh-500 */ + /* --cr-separator-line */ + --md-toolbar-border: 1px solid rgba(255, 255, 255, .1); --md-toolbar-color: rgba(255, 255, 255, .04); }