diff --git a/DEPS b/DEPS index 8766d07a0..0529502 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,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': 'fba26ea9b7fc7ed45d80ba0bd923d1824fd49534', + 'skia_revision': 'ae532f68a035e50530c846233fe60dabdd9e3414', # 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': '19f1033a265556dec3fdd575526c6fa48e240974', + 'v8_revision': 'a14a5f4fa219cba654c25e6deeb8f3229075e7ef', # 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. @@ -238,7 +238,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'a7461e3086866272cb69fbfa23c7fc8b0321a425', # commit position 19097 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '262f12e06b811d265a437d760a3add82477af106', # commit position 19232 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc index 4d09fd4..07715b2885 100644 --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -120,7 +120,6 @@ base::android::MemoryPressureListenerAndroid::RegisterSystemCallback( base::android::AttachCurrentThread()); - DeferredGpuCommandService::SetInstance(); breakpad::CrashDumpObserver::Create(); if (crash_reporter::IsCrashReporterEnabled()) { @@ -170,6 +169,10 @@ // TODO(meacer): Remove when PlzNavigate ships. content::RenderFrameHost::AllowDataUrlNavigationForAndroidWebView(); + + // This only works because webview uses in-process gpu + // which is not started up early by BrowserMainLoop. + DeferredGpuCommandService::SetInstance(); } bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
diff --git a/base/trace_event/memory_allocator_dump_guid.cc b/base/trace_event/memory_allocator_dump_guid.cc index 4df7aa46..08ac677 100644 --- a/base/trace_event/memory_allocator_dump_guid.cc +++ b/base/trace_event/memory_allocator_dump_guid.cc
@@ -13,8 +13,6 @@ namespace { -bool g_use_shared_memory_guid = true; - uint64_t HashString(const std::string& str) { uint64_t hash[(kSHA1Length + sizeof(uint64_t) - 1) / sizeof(uint64_t)] = {0}; SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.data()), str.size(), @@ -24,15 +22,6 @@ } // namespace -// static -bool MemoryAllocatorDumpGuid::UseSharedMemoryBasedGUIDs() { - // TODO(hajimehoshi): This should just become the default behavior once the - // Mojo GUID (crbug.com/604726) is fixed. - if (g_use_shared_memory_guid) - return true; - return false; -} - MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(uint64_t guid) : guid_(guid) {} MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid()
diff --git a/base/trace_event/memory_allocator_dump_guid.h b/base/trace_event/memory_allocator_dump_guid.h index 32ce6b4..2a420a2 100644 --- a/base/trace_event/memory_allocator_dump_guid.h +++ b/base/trace_event/memory_allocator_dump_guid.h
@@ -16,10 +16,6 @@ class BASE_EXPORT MemoryAllocatorDumpGuid { public: - // If the clients of base::SharedMemory should use the global dump guid(s) - // created by SharedMemoryTracker. - static bool UseSharedMemoryBasedGUIDs(); - MemoryAllocatorDumpGuid(); explicit MemoryAllocatorDumpGuid(uint64_t guid);
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index 18177f6..400c73f 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc
@@ -430,42 +430,31 @@ const UnguessableToken& shared_memory_guid, int importance, bool is_weak) { - if (MemoryAllocatorDumpGuid::UseSharedMemoryBasedGUIDs()) { - DCHECK(!shared_memory_guid.is_empty()); - // New model where the global dumps created by SharedMemoryTracker are used - // for the clients. + DCHECK(!shared_memory_guid.is_empty()); + // New model where the global dumps created by SharedMemoryTracker are used + // for the clients. - // The guid of the local dump created by SharedMemoryTracker for the memory - // segment. - auto local_shm_guid = - SharedMemoryTracker::GetDumpIdForTracing(shared_memory_guid); + // The guid of the local dump created by SharedMemoryTracker for the memory + // segment. + auto local_shm_guid = + SharedMemoryTracker::GetDumpIdForTracing(shared_memory_guid); - // The dump guid of the global dump created by the tracker for the memory - // segment. - auto global_shm_guid = - SharedMemoryTracker::GetGlobalDumpIdForTracing(shared_memory_guid); + // The dump guid of the global dump created by the tracker for the memory + // segment. + auto global_shm_guid = + SharedMemoryTracker::GetGlobalDumpIdForTracing(shared_memory_guid); - // Create an edge between local dump of the client and the local dump of the - // SharedMemoryTracker. Do not need to create the dumps here since the - // tracker would create them. The importance is also required here for the - // case of single process mode. - AddOwnershipEdge(client_local_dump_guid, local_shm_guid, importance); + // Create an edge between local dump of the client and the local dump of the + // SharedMemoryTracker. Do not need to create the dumps here since the tracker + // would create them. The importance is also required here for the case of + // single process mode. + AddOwnershipEdge(client_local_dump_guid, local_shm_guid, importance); - // TODO(ssid): Handle the case of weak dumps here. This needs a new function - // GetOrCreaetGlobalDump() in PMD since we need to change the behavior of - // the created global dump. - // Create an edge that overrides the edge created by SharedMemoryTracker. - AddOwnershipEdge(local_shm_guid, global_shm_guid, importance); - } else { - // This is the old model where the clients create global dumps for - // themselves. - if (is_weak) - CreateWeakSharedGlobalAllocatorDump(client_global_dump_guid); - else - CreateSharedGlobalAllocatorDump(client_global_dump_guid); - AddOwnershipEdge(client_local_dump_guid, client_global_dump_guid, - importance); - } + // TODO(ssid): Handle the case of weak dumps here. This needs a new function + // GetOrCreaetGlobalDump() in PMD since we need to change the behavior of the + // created global dump. + // Create an edge that overrides the edge created by SharedMemoryTracker. + AddOwnershipEdge(local_shm_guid, global_shm_guid, importance); } void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index ca88549..5090f7e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -136,6 +136,7 @@ @Test @MediumTest @Feature({"NewTabPage", "RenderTest"}) + @CommandLineFlags.Add("disable-features=NTPCondensedLayout") public void testRender() throws IOException { mActivityTestRule.getInstrumentation().waitForIdleSync(); mRenderTestRule.render(mTileGridLayout, "most_visited");
diff --git a/chrome/browser/apps/app_url_redirector.cc b/chrome/browser/apps/app_url_redirector.cc index e5ec867..58b91cf0 100644 --- a/chrome/browser/apps/app_url_redirector.cc +++ b/chrome/browser/apps/app_url_redirector.cc
@@ -6,9 +6,15 @@ #include "apps/launcher.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/logging.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/extensions/app_launch_params.h" +#include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "components/navigation_interception/intercept_navigation_throttle.h" #include "components/navigation_interception/navigation_params.h" @@ -35,6 +41,12 @@ const navigation_interception::NavigationParams& params) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Redirecting for Bookmark Apps is hidden behind a feature flag. + if (app->from_bookmark() && + !base::FeatureList::IsEnabled(features::kDesktopPWAWindowing)) { + return false; + } + // Redirect top-level navigations only. This excludes iframes and webviews // in particular. if (source->IsSubframe()) { @@ -57,6 +69,27 @@ Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); + if (app->from_bookmark()) { + Browser* browser = chrome::FindBrowserWithWebContents(source); + if (browser == nullptr) { + DVLOG(1) << "Don't override: No browser, can't know if already in app."; + return false; + } + + if (browser->app_name() == + web_app::GenerateApplicationNameFromExtensionId(app->id())) { + DVLOG(1) << "Don't override: Already in app."; + return false; + } + + AppLaunchParams launch_params( + profile, app.get(), extensions::LAUNCH_CONTAINER_WINDOW, + WindowOpenDisposition::CURRENT_TAB, extensions::SOURCE_URL_HANDLER); + launch_params.override_url = params.url(); + OpenApplication(launch_params); + return true; + } + DVLOG(1) << "Launching app handler with URL: " << params.url().spec() << " -> " << app->name() << "(" << app->id() << "):" << handler_id;
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index a4aa225..ba2c11e 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -107,7 +107,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/pref_names.h" -#include "chrome/grit/chromium_strings.h" #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/cert_loader.h" @@ -170,12 +169,10 @@ #include "ui/base/ime/chromeos/ime_keyboard.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/touch/touch_device.h" #include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/chromeos/events/pref_names.h" #include "ui/events/event_utils.h" -#include "ui/message_center/message_center.h" #if BUILDFLAG(ENABLE_RLZ) #include "components/rlz/rlz_tracker.h" @@ -790,11 +787,6 @@ VLOG(1) << "Relaunching browser for user: " << account_id.Serialize() << " with hash: " << user_id_hash; } - - // Set product name ("Chrome OS" or "Chromium OS") to be used in context - // header of new-style notification. - message_center::MessageCenter::Get()->SetProductOSName( - l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)); } class GuestLanguageSetCallbackData {
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc index a853633..580e2c8b 100644 --- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc +++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -242,6 +243,9 @@ ASSERT_TRUE(GetDatabaseEnabled()); GURL url("http://www.google.com"); + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); prerender::PrerenderManager* prerender_manager = prerender::PrerenderManagerFactory::GetForBrowserContext(profile());
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc index d5ec19df..901b34d 100644 --- a/chrome/browser/extensions/bookmark_app_helper.cc +++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/favicon_downloader.h" @@ -31,6 +32,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/webshare/share_target_pref_helper.h" +#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/origin_trials/chrome_origin_trial_policy.h" @@ -357,6 +359,9 @@ if (manifest.start_url.is_valid()) web_app_info->app_url = manifest.start_url; + if (!manifest.scope.is_empty()) + web_app_info->scope = manifest.scope; + // If any icons are specified in the manifest, they take precedence over any // we picked up from the web_app stuff. if (!manifest.icons.empty()) { @@ -805,6 +810,7 @@ web_app_info.app_url = AppLaunchInfo::GetLaunchWebURL(extension); web_app_info.title = base::UTF8ToUTF16(extension->non_localized_name()); web_app_info.description = base::UTF8ToUTF16(extension->description()); + web_app_info.scope = GetScopeURLFromBookmarkApp(extension); const ExtensionIconSet& icon_set = extensions::IconsInfo::GetIcons(extension); std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc index da3146b2..277660d 100644 --- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc +++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/banners/app_banner_settings_helper.h" +#include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" @@ -29,6 +30,8 @@ const char kAppUrl[] = "http://www.chromium.org"; const char kAlternativeAppUrl[] = "http://www.notchromium.org"; +const char kAppScope[] = "http://www.chromium.org"; +const char kAppAlternativeScope[] = "http://www.chromium.org/new/"; const char kAppTitle[] = "Test title"; const char kAppShortName[] = "Test short name"; const char kAlternativeAppTitle[] = "Different test title"; @@ -194,6 +197,7 @@ EXPECT_EQ(original.title, newly_made.title); EXPECT_EQ(original.description, newly_made.description); EXPECT_EQ(original.app_url, newly_made.app_url); + EXPECT_EQ(original.scope, newly_made.scope); // There should be 6 icons, as there are three sizes which need to be // generated, and each will generate a 1x and 2x icon. EXPECT_EQ(6u, newly_made.icons.size()); @@ -360,6 +364,7 @@ content::Manifest manifest; manifest.start_url = GURL(kAppUrl); manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false); + manifest.scope = GURL(kAppScope); helper.CompleteGetManifest(manifest); std::map<GURL, std::vector<SkBitmap> > icon_map; @@ -374,6 +379,7 @@ EXPECT_TRUE(extension->from_bookmark()); EXPECT_EQ(kAppTitle, extension->name()); EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension)); + EXPECT_EQ(GURL(kAppScope), GetScopeURLFromBookmarkApp(extension)); EXPECT_FALSE( AppBannerSettingsHelper::GetSingleBannerEvent( contents.get(), manifest.start_url, manifest.start_url.spec(), @@ -386,6 +392,7 @@ web_app_info.app_url = GURL(kAppUrl); web_app_info.title = base::UTF8ToUTF16(kAppTitle); web_app_info.description = base::UTF8ToUTF16(kAppDescription); + web_app_info.scope = GURL(kAppScope); web_app_info.icons.push_back( CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED)); @@ -403,6 +410,7 @@ EXPECT_EQ(kAppTitle, extension->name()); EXPECT_EQ(kAppDescription, extension->description()); EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension)); + EXPECT_EQ(GURL(kAppScope), GetScopeURLFromBookmarkApp(extension)); EXPECT_FALSE( IconsInfo::GetIconResource(extension, kIconSizeTiny, ExtensionIconSet::MATCH_EXACTLY).empty()); @@ -428,6 +436,7 @@ web_app_info.app_url = GURL(kAppUrl); web_app_info.title = base::UTF8ToUTF16(kAppTitle); web_app_info.description = base::UTF8ToUTF16(kAppDescription); + web_app_info.scope = GURL(kAppScope); web_app_info.icons.push_back( CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED)); @@ -442,6 +451,7 @@ EXPECT_EQ(kAppTitle, extension->name()); EXPECT_EQ(kAppDescription, extension->description()); EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension)); + EXPECT_EQ(GURL(kAppScope), GetScopeURLFromBookmarkApp(extension)); EXPECT_FALSE(extensions::IconsInfo::GetIconResource( extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY) .empty()); @@ -449,6 +459,7 @@ web_app_info.title = base::UTF8ToUTF16(kAlternativeAppTitle); web_app_info.icons[0] = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED); + web_app_info.scope = GURL(kAppAlternativeScope); extensions::CreateOrUpdateBookmarkApp(service_, &web_app_info); content::RunAllBlockingPoolTasksUntilIdle(); @@ -461,6 +472,8 @@ EXPECT_EQ(kAlternativeAppTitle, extension->name()); EXPECT_EQ(kAppDescription, extension->description()); EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension)); + EXPECT_EQ(GURL(kAppAlternativeScope), + GetScopeURLFromBookmarkApp(extension)); EXPECT_FALSE(extensions::IconsInfo::GetIconResource( extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY) .empty()); @@ -475,6 +488,7 @@ web_app_info.app_url = GURL(kAppUrl); web_app_info.title = base::UTF8ToUTF16(kAppTitle); web_app_info.description = base::UTF8ToUTF16(kAppDescription); + web_app_info.scope = GURL(kAppScope); extensions::CreateOrUpdateBookmarkApp(service_, &web_app_info); content::RunAllBlockingPoolTasksUntilIdle();
diff --git a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc new file mode 100644 index 0000000..2265088f --- /dev/null +++ b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
@@ -0,0 +1,259 @@ +// 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 "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/extensions/bookmark_app_helper.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/web_application_info.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/notification_types.h" +#include "net/test/embedded_test_server/embedded_test_server.h" + +namespace extensions { + +const char kAppUrlPath[] = + "/extensions/bookmark_apps/url_handlers/in_scope/index.html"; +const char kScopePath[] = "/extensions/bookmark_apps/url_handlers/in_scope/"; +const char kInScopeUrlPath[] = + "/extensions/bookmark_apps/url_handlers/in_scope/other.html"; +const char kOutOfScopeUrlPath[] = + "/extensions/bookmark_apps/url_handlers/out_of_scope/other.html"; + +class BookmarkAppUrlRedirectorBrowserTest : public ExtensionBrowserTest { + public: + void SetUp() override { + scoped_feature_list_ = base::MakeUnique<base::test::ScopedFeatureList>(); + scoped_feature_list_->InitAndEnableFeature(features::kDesktopPWAWindowing); + ExtensionBrowserTest::SetUp(); + } + + void InstallTestBookmarkApp() { + ASSERT_TRUE(embedded_test_server()->Start()); + size_t num_extensions = + ExtensionRegistry::Get(profile())->enabled_extensions().size(); + + WebApplicationInfo web_app_info; + web_app_info.app_url = embedded_test_server()->GetURL(kAppUrlPath); + web_app_info.scope = embedded_test_server()->GetURL(kScopePath); + web_app_info.title = base::UTF8ToUTF16("Test app"); + web_app_info.description = base::UTF8ToUTF16("Test description"); + + content::WindowedNotificationObserver windowed_observer( + extensions::NOTIFICATION_CRX_INSTALLER_DONE, + content::NotificationService::AllSources()); + extensions::CreateOrUpdateBookmarkApp(extension_service(), &web_app_info); + windowed_observer.Wait(); + + ASSERT_EQ(++num_extensions, + ExtensionRegistry::Get(profile())->enabled_extensions().size()); + } + + Browser* OpenTestBookmarkApp() { + GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), app_url); + url_observer.Wait(); + + return chrome::FindLastActive(); + } + + void ResetFeatureList() { scoped_feature_list_.reset(); } + + private: + std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; +}; + +// Tests that navigating to the Web App's app_url doesn't open a new window +// if features::kDesktopPWAWindowing is disabled before installing the app. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, + FeatureDisable_BeforeInstall) { + ResetFeatureList(); + InstallTestBookmarkApp(); + + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), app_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(browser(), chrome::FindLastActive()); + + EXPECT_EQ(app_url, browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); +} + +// Tests that navigating to the Web App's app_url doesn't open a new window +// if features::kDesktopPWAWindowing is disabled after installing the app. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, + FeatureDisable_AfterInstall) { + InstallTestBookmarkApp(); + ResetFeatureList(); + + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), app_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(browser(), chrome::FindLastActive()); + + EXPECT_EQ(app_url, browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); +} + +// Tests that navigating to the Web App's app_url opens a new browser window. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, AppUrl) { + InstallTestBookmarkApp(); + + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + GURL initial_url = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL(); + + GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), app_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_NE(browser(), chrome::FindLastActive()); + + EXPECT_EQ(initial_url, browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); + EXPECT_EQ(app_url, chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); +} + +// Tests that navigating to a URL in the Web App's scope opens a new browser +// window. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, InScopeUrl) { + InstallTestBookmarkApp(); + + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + GURL initial_url = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL(); + + GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + in_scope_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), in_scope_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_NE(browser(), chrome::FindLastActive()); + + EXPECT_EQ(initial_url, browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); + EXPECT_EQ(in_scope_url, chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); +} + +// Tests that navigating to a URL out of the Web App's scope but with the +// same origin doesn't open a new browser window. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, OutOfScopeUrl) { + InstallTestBookmarkApp(); + + int num_tabs = browser()->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + GURL out_of_scope_url = embedded_test_server()->GetURL(kOutOfScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + out_of_scope_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), out_of_scope_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(browser(), chrome::FindLastActive()); + + EXPECT_EQ(out_of_scope_url, chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); +} + +// Tests that navigating inside the app doesn't open new browser windows. +IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, InAppNavigation) { + InstallTestBookmarkApp(); + Browser* app_browser = OpenTestBookmarkApp(); + + int num_tabs_browser = browser()->tab_strip_model()->count(); + int num_tabs_app_browser = app_browser->tab_strip_model()->count(); + size_t num_browsers = chrome::GetBrowserCount(profile()); + + { + GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + in_scope_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(app_browser, in_scope_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(app_browser, chrome::FindLastActive()); + + EXPECT_EQ(in_scope_url, app_browser->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); + } + + { + GURL out_of_scope_url = embedded_test_server()->GetURL(kOutOfScopeUrlPath); + ui_test_utils::UrlLoadObserver url_observer( + out_of_scope_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(app_browser, out_of_scope_url); + url_observer.Wait(); + + EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); + EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); + EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); + EXPECT_EQ(app_browser, chrome::FindLastActive()); + + EXPECT_EQ(out_of_scope_url, app_browser->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); + } +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc index e8304f2..a667ba8e 100644 --- a/chrome/browser/extensions/convert_web_app.cc +++ b/chrome/browser/extensions/convert_web_app.cc
@@ -27,6 +27,7 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/web_application_info.h" #include "crypto/sha2.h" #include "extensions/common/constants.h" @@ -47,6 +48,7 @@ namespace { const char kIconsDirName[] = "icons"; +const char kScopeUrlHandlerId[] = "scope"; // Create the public key for the converted web app. // @@ -66,6 +68,54 @@ } // namespace +std::unique_ptr<base::DictionaryValue> CreateURLHandlersForBookmarkApp( + const GURL& scope_url, + const base::string16& title) { + auto matches = base::MakeUnique<base::ListValue>(); + matches->AppendString(scope_url.GetOrigin().Resolve(scope_url.path()).spec() + + "*"); + + auto scope_handler = base::MakeUnique<base::DictionaryValue>(); + scope_handler->SetList(keys::kMatches, std::move(matches)); + // The URL handler title is not used anywhere but we set it to the + // web app's title just in case. + scope_handler->SetString(keys::kUrlHandlerTitle, base::UTF16ToUTF8(title)); + + auto url_handlers = base::MakeUnique<base::DictionaryValue>(); + // Use "scope" as the url handler's identifier. + url_handlers->SetDictionary(kScopeUrlHandlerId, std::move(scope_handler)); + return url_handlers; +} + +GURL GetScopeURLFromBookmarkApp(const Extension* extension) { + DCHECK(extension->from_bookmark()); + const std::vector<UrlHandlerInfo>* url_handlers = + UrlHandlers::GetUrlHandlers(extension); + if (!url_handlers) + return GURL(); + + // A Bookmark app created by us should only have a url_handler with id + // kScopeUrlHandlerId. This URL handler should have a single pattern which + // corresponds to the web manifest's scope. The URL handler's pattern should + // be the Web Manifest's scope's origin + path with a wildcard, '*', appended + // to it. + auto handler_it = std::find_if( + url_handlers->begin(), url_handlers->end(), + [](const UrlHandlerInfo& info) { return info.id == kScopeUrlHandlerId; }); + if (handler_it == url_handlers->end()) { + return GURL(); + } + + const auto& patterns = handler_it->patterns; + DCHECK(patterns.size() == 1); + const auto& pattern_iter = patterns.begin(); + // Remove the '*' character at the end (which was added when creating the URL + // handler, see CreateURLHandlersForBookmarkApp()). + const std::string& pattern_str = pattern_iter->GetAsString(); + DCHECK_EQ(pattern_str.back(), '*'); + return GURL(pattern_str.substr(0, pattern_str.size() - 1)); +} + // Generates a version for the converted app using the current date. This isn't // really needed, but it seems like useful information. std::string ConvertTimeToExtensionVersion(const Time& create_time) { @@ -117,6 +167,11 @@ web_app.generated_icon_color)); } + if (!web_app.scope.is_empty()) { + root->SetDictionary(keys::kUrlHandlers, CreateURLHandlersForBookmarkApp( + web_app.scope, web_app.title)); + } + // Add the icons and linked icon information. auto icons = base::MakeUnique<base::DictionaryValue>(); auto linked_icons = base::MakeUnique<base::ListValue>();
diff --git a/chrome/browser/extensions/convert_web_app.h b/chrome/browser/extensions/convert_web_app.h index 7c9551a..55ee03da 100644 --- a/chrome/browser/extensions/convert_web_app.h +++ b/chrome/browser/extensions/convert_web_app.h
@@ -10,15 +10,45 @@ #include "base/memory/ref_counted.h" namespace base { +class DictionaryValue; class FilePath; class Time; } +class GURL; struct WebApplicationInfo; namespace extensions { class Extension; +// Creates a DictionaryValue with a single URL handler for |scope_url| and +// |title|. |title| is meant to appear in relevant UI surfaces but it's not used +// anywhere yet. The resulting DictionaryValue can be used as the "url_handlers" +// field in a Chrome Apps manifest. +// +// To create a URL handler that will match the same URLs as the "within +// scope" algorithm of the Web Manifest spec, we remove everything +// but the origin and path and append a wildcard, i.e. "*", to the result. +// According to the Web Manifest spec, a URL |url| is within scope of +// |scope_url| if |url|'s origin is the same as |scope_url|'s origin and +// |url|'s path starts with |scope_url|'s path. +// Note that this results in some unexpected URLs being within scope +// according to the spec: +// Suppose |scope_url| is "https://example.com/foo" and |url| is +// "https://example.com/foobar.html", then according to the spec algorithm +// |url| is within scope. +// See https://github.com/w3c/manifest/issues/554 for details. +// +// GetScopeURLFromBookmarkApp() reverses this operation, i.e. removes +// the '*' from the scope URL handler, to retrieve the scope for a Bookmark App. +// So if you change this, you also have to change GetScopeURLFromBookmarkApp(). +std::unique_ptr<base::DictionaryValue> CreateURLHandlersForBookmarkApp( + const GURL& scope_url, + const base::string16& title); + +// Retrieves the scope URL from a Bookmark App's URL handlers. +GURL GetScopeURLFromBookmarkApp(const Extension* extension); + // Generates a version number for an extension from a time. The goal is to make // use of the version number to communicate the date in a human readable form, // while maintaining high enough resolution to change each time an app is
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc index 5addbde..7fc4082 100644 --- a/chrome/browser/extensions/convert_web_app_unittest.cc +++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -13,17 +13,20 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/path_service.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/version.h" +#include "chrome/browser/extensions/bookmark_app_helper.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/web_application_info.h" #include "extensions/common/extension.h" #include "extensions/common/extension_icon_set.h" #include "extensions/common/extension_resource.h" +#include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permissions_data.h" @@ -34,6 +37,8 @@ namespace extensions { +namespace keys = manifest_keys; + namespace { // Returns an icon info corresponding to a canned icon. @@ -87,6 +92,141 @@ } // namespace +TEST(ExtensionFromWebApp, GetScopeURLFromBookmarkApp) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + base::DictionaryValue manifest; + manifest.SetString(keys::kName, "Test App"); + manifest.SetString(keys::kVersion, "0"); + manifest.SetString(keys::kLaunchWebURL, "http://aaronboodman.com/gearpad/"); + + // Create a "url_handlers" dictionary with one URL handler generated from + // the scope. + // { + // "scope": { + // "matches": [ "http://aaronboodman.com/gearpad/*" ], + // "title": "Test App" + // }, + // } + GURL scope_url = GURL("http://aaronboodman.com/gearpad/"); + manifest.SetDictionary(keys::kUrlHandlers, + CreateURLHandlersForBookmarkApp( + scope_url, base::ASCIIToUTF16("Test App"))); + + std::string error; + scoped_refptr<Extension> bookmark_app = + Extension::Create(extensions_dir.GetPath(), Manifest::INTERNAL, manifest, + Extension::FROM_BOOKMARK, &error); + ASSERT_TRUE(bookmark_app.get()); + + EXPECT_EQ(scope_url, GetScopeURLFromBookmarkApp(bookmark_app.get())); +} + +TEST(ExtensionFromWebApp, GetScopeURLFromBookmarkApp_NoURLHandlers) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + base::DictionaryValue manifest; + manifest.SetString(keys::kName, "Test App"); + manifest.SetString(keys::kVersion, "0"); + manifest.SetString(keys::kLaunchWebURL, "http://aaronboodman.com/gearpad/"); + manifest.SetDictionary(keys::kUrlHandlers, + base::MakeUnique<base::DictionaryValue>()); + + std::string error; + scoped_refptr<Extension> bookmark_app = + Extension::Create(extensions_dir.GetPath(), Manifest::INTERNAL, manifest, + Extension::FROM_BOOKMARK, &error); + ASSERT_TRUE(bookmark_app.get()); + + EXPECT_EQ(GURL(), GetScopeURLFromBookmarkApp(bookmark_app.get())); +} + +TEST(ExtensionFromWebApp, GetScopeURLFromBookmarkApp_WrongURLHandler) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + base::DictionaryValue manifest; + manifest.SetString(keys::kName, "Test App"); + manifest.SetString(keys::kVersion, "0"); + manifest.SetString(keys::kLaunchWebURL, "http://aaronboodman.com/gearpad/"); + + // Create a "url_handlers" dictionary with one URL handler not generated + // from the scope. + // { + // "test_url_handler": { + // "matches": [ "http://*.aaronboodman.com/" ], + // "title": "test handler" + // } + // } + auto test_matches = base::MakeUnique<base::ListValue>(); + test_matches->AppendString("http://*.aaronboodman.com/"); + + auto test_handler = base::MakeUnique<base::DictionaryValue>(); + test_handler->SetList(keys::kMatches, std::move(test_matches)); + test_handler->SetString(keys::kUrlHandlerTitle, "test handler"); + + auto url_handlers = base::MakeUnique<base::DictionaryValue>(); + url_handlers->SetDictionary("test_url_handler", std::move(test_handler)); + manifest.SetDictionary(keys::kUrlHandlers, std::move(url_handlers)); + + std::string error; + scoped_refptr<Extension> bookmark_app = + Extension::Create(extensions_dir.GetPath(), Manifest::INTERNAL, manifest, + Extension::FROM_BOOKMARK, &error); + ASSERT_TRUE(bookmark_app.get()); + + EXPECT_EQ(GURL(), GetScopeURLFromBookmarkApp(bookmark_app.get())); +} + +TEST(ExtensionFromWebApp, GetScopeURLFromBookmarkApp_ExtraURLHandler) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + base::DictionaryValue manifest; + manifest.SetString(keys::kName, "Test App"); + manifest.SetString(keys::kVersion, "0"); + manifest.SetString(keys::kLaunchWebURL, "http://aaronboodman.com/gearpad/"); + + // Create a "url_handlers" dictionary with two URL handlers. One for + // the scope and and extra one for testing. + // { + // "scope": { + // "matches": [ "http://aaronboodman.com/gearpad/*" ], + // "title": "Test App" + // }, + // "test_url_handler": { + // "matches": [ "http://*.aaronboodman.com/" ], + // "title": "test handler" + // } + // } + GURL scope_url = GURL("http://aaronboodman.com/gearpad/"); + std::unique_ptr<base::DictionaryValue> url_handlers = + CreateURLHandlersForBookmarkApp(scope_url, + base::ASCIIToUTF16("Test App")); + + auto test_matches = base::MakeUnique<base::ListValue>(); + test_matches->AppendString("http://*.aaronboodman.com/"); + + auto test_handler = base::MakeUnique<base::DictionaryValue>(); + test_handler->SetList(keys::kMatches, std::move(test_matches)); + test_handler->SetString(keys::kUrlHandlerTitle, "test handler"); + + url_handlers->SetDictionary("test_url_handler", std::move(test_handler)); + manifest.SetDictionary(keys::kUrlHandlers, std::move(url_handlers)); + + std::string error; + scoped_refptr<Extension> bookmark_app = + Extension::Create(extensions_dir.GetPath(), Manifest::INTERNAL, manifest, + Extension::FROM_BOOKMARK, &error); + ASSERT_TRUE(bookmark_app.get()); + + // Check that we can retrieve the scope even if there is an extra + // url handler. + EXPECT_EQ(scope_url, GetScopeURLFromBookmarkApp(bookmark_app.get())); +} + TEST(ExtensionFromWebApp, GenerateVersion) { EXPECT_EQ("2010.1.1.0", ConvertTimeToExtensionVersion( @@ -108,6 +248,7 @@ web_app.description = base::ASCIIToUTF16("The best text editor in the universe!"); web_app.app_url = GURL("http://aaronboodman.com/gearpad/"); + web_app.scope = GURL("http://aaronboodman.com/gearpad/"); const int sizes[] = {16, 48, 128}; for (size_t i = 0; i < arraysize(sizes); ++i) { @@ -134,6 +275,7 @@ EXPECT_EQ(base::UTF16ToUTF8(web_app.title), extension->name()); EXPECT_EQ(base::UTF16ToUTF8(web_app.description), extension->description()); EXPECT_EQ(web_app.app_url, AppLaunchInfo::GetFullLaunchURL(extension.get())); + EXPECT_EQ(web_app.scope, GetScopeURLFromBookmarkApp(extension.get())); EXPECT_EQ(0u, extension->permissions_data()->active_permissions().apis().size()); ASSERT_EQ(0u, extension->web_extent().patterns().size()); @@ -179,10 +321,31 @@ EXPECT_EQ(base::UTF16ToUTF8(web_app.title), extension->name()); EXPECT_EQ("", extension->description()); EXPECT_EQ(web_app.app_url, AppLaunchInfo::GetFullLaunchURL(extension.get())); + EXPECT_TRUE(GetScopeURLFromBookmarkApp(extension.get()).is_empty()); EXPECT_EQ(0u, IconsInfo::GetIcons(extension.get()).map().size()); EXPECT_EQ(0u, extension->permissions_data()->active_permissions().apis().size()); ASSERT_EQ(0u, extension->web_extent().patterns().size()); } +// Tests that a scope not ending in "/" works correctly. +// The tested behavior is unexpected but is working correctly according +// to the Web Manifest spec. https://github.com/w3c/manifest/issues/554 +TEST(ExtensionFromWebApp, ScopeDoesNotEndInSlash) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + WebApplicationInfo web_app; + web_app.title = base::ASCIIToUTF16("Gearpad"); + web_app.description = + base::ASCIIToUTF16("The best text editor in the universe!"); + web_app.app_url = GURL("http://aaronboodman.com/gearpad/"); + web_app.scope = GURL("http://aaronboodman.com/gear"); + + scoped_refptr<Extension> extension = ConvertWebAppToExtension( + web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0), extensions_dir.GetPath()); + ASSERT_TRUE(extension.get()); + EXPECT_EQ(web_app.scope, GetScopeURLFromBookmarkApp(extension.get())); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc index cb7c50df..7425df7 100644 --- a/chrome/browser/extensions/crx_installer_browsertest.cc +++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -141,6 +141,7 @@ web_app_info.title = base::UTF8ToUTF16(title); web_app_info.description = base::UTF8ToUTF16(description); web_app_info.app_url = GURL(app_url); + web_app_info.scope = GURL(app_url); web_app_info.icons.push_back(CreateIconInfoWithBitmap(size));
diff --git a/chrome/browser/extensions/extension_sync_data.cc b/chrome/browser/extensions/extension_sync_data.cc index 43def385..209cb21 100644 --- a/chrome/browser/extensions/extension_sync_data.cc +++ b/chrome/browser/extensions/extension_sync_data.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/common/extensions/manifest_handlers/app_icon_color_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" @@ -125,6 +126,7 @@ if (is_app_ && extension.from_bookmark()) { bookmark_app_description_ = extension.description(); bookmark_app_url_ = AppLaunchInfo::GetLaunchWebURL(&extension).spec(); + bookmark_app_scope_ = GetScopeURLFromBookmarkApp(&extension).spec(); bookmark_app_icon_color_ = AppIconColorInfo::GetIconColorString(&extension); extensions::LinkedAppIcons icons = LinkedAppIcons::GetLinkedAppIcons(&extension); @@ -219,6 +221,9 @@ if (!bookmark_app_description_.empty()) specifics->set_bookmark_app_description(bookmark_app_description_); + if (!bookmark_app_scope_.empty()) + specifics->set_bookmark_app_scope(bookmark_app_scope_); + if (!bookmark_app_icon_color_.empty()) specifics->set_bookmark_app_icon_color(bookmark_app_icon_color_); @@ -295,6 +300,7 @@ bookmark_app_url_ = specifics.bookmark_app_url(); bookmark_app_description_ = specifics.bookmark_app_description(); + bookmark_app_scope_ = specifics.bookmark_app_url(); bookmark_app_icon_color_ = specifics.bookmark_app_icon_color(); for (int i = 0; i < specifics.linked_app_icons_size(); ++i) {
diff --git a/chrome/browser/extensions/extension_sync_data.h b/chrome/browser/extensions/extension_sync_data.h index 24f7d40..5578b7f1 100644 --- a/chrome/browser/extensions/extension_sync_data.h +++ b/chrome/browser/extensions/extension_sync_data.h
@@ -118,6 +118,7 @@ const std::string& bookmark_app_description() const { return bookmark_app_description_; } + const std::string& bookmark_app_scope() const { return bookmark_app_scope_; } const std::string& bookmark_app_icon_color() const { return bookmark_app_icon_color_; } @@ -168,6 +169,7 @@ extensions::LaunchType launch_type_; std::string bookmark_app_url_; std::string bookmark_app_description_; + std::string bookmark_app_scope_; std::string bookmark_app_icon_color_; std::vector<LinkedAppIconInfo> linked_icons_; };
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc index fd538cb..602a43b 100644 --- a/chrome/browser/extensions/extension_sync_service.cc +++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -570,6 +570,7 @@ web_app_info.title = base::UTF8ToUTF16(extension_sync_data.name()); web_app_info.description = base::UTF8ToUTF16(extension_sync_data.bookmark_app_description()); + web_app_info.scope = GURL(extension_sync_data.bookmark_app_scope()); if (!extension_sync_data.bookmark_app_icon_color().empty()) { extensions::image_util::ParseHexColorString( extension_sync_data.bookmark_app_icon_color(),
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc index 49cef54..7c9bed4dd 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc
@@ -18,6 +18,8 @@ #include "base/time/time.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/prerender/prerender_field_trial.h" +#include "chrome/browser/prerender/prerender_manager.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_service.h" @@ -348,6 +350,9 @@ AutocompleteMatch match; match.type = AutocompleteMatchType::HISTORY_URL; + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH); for (size_t i = 0; i < arraysize(test_url_db); ++i) { match.destination_url = GURL(test_url_db[i].url); @@ -362,6 +367,9 @@ AutocompleteMatch match; match.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED; + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH); for (size_t i = 0; i < arraysize(test_url_db); ++i) { match.destination_url = GURL(test_url_db[i].url);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 295cfec..312d2bb9 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -599,6 +599,10 @@ test_utils::PrerenderInProcessBrowserTest::SetUpOnMainThread(); prerender::PrerenderManager::SetMode( prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetInstantMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetOmniboxMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); // This one test fails with the host resolver redirecting all hosts.
diff --git a/chrome/browser/prerender/prerender_field_trial.cc b/chrome/browser/prerender/prerender_field_trial.cc index 56835cf..a152c60e 100644 --- a/chrome/browser/prerender/prerender_field_trial.cc +++ b/chrome/browser/prerender/prerender_field_trial.cc
@@ -71,7 +71,7 @@ void ConfigurePrerender() { PrerenderManager::PrerenderManagerMode overall_mode = ParsePrerenderMode(kNoStatePrefetchFeatureModeParameterName, - PrerenderManager::PRERENDER_MODE_ENABLED); + PrerenderManager::PRERENDER_MODE_DISABLED); PrerenderManager::SetMode(overall_mode); PrerenderManager::SetInstantMode(ParsePrerenderMode(
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index f0b3455..53bd31e4 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -166,11 +166,11 @@ // static PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_DISABLED; PrerenderManager::PrerenderManagerMode PrerenderManager::instant_mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_DISABLED; PrerenderManager::PrerenderManagerMode PrerenderManager::omnibox_mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_DISABLED; struct PrerenderManager::NavigationRecord { NavigationRecord(const GURL& url, base::TimeTicks time, Origin origin)
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 9eac021b..2cc5e9e 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -462,22 +462,16 @@ TEST_F(PrerenderTest, PrerenderRespectsDisableFlag) { test_utils::RestorePrerenderMode restore_prerender_mode; - ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); - ASSERT_EQ(PrerenderManager::PRERENDER_MODE_ENABLED, + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(kNoStatePrefetchFeature); + prerender::ConfigurePrerender(); + EXPECT_FALSE(PrerenderManager::IsAnyPrerenderingPossible()); + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, PrerenderManager::GetMode(ORIGIN_NONE)); - - { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(kNoStatePrefetchFeature); - prerender::ConfigurePrerender(); - EXPECT_FALSE(PrerenderManager::IsAnyPrerenderingPossible()); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_NONE)); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_OMNIBOX)); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_INSTANT)); - } + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, + PrerenderManager::GetMode(ORIGIN_OMNIBOX)); + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, + PrerenderManager::GetMode(ORIGIN_INSTANT)); } TEST_F(PrerenderTest, PrerenderRespectsFieldTrialParameters) { @@ -603,6 +597,7 @@ TEST_F(PrerenderTest, PrerenderRespectsThirdPartyCookiesPref) { GURL url("http://www.google.com/"); test_utils::RestorePrerenderMode restore_prerender_mode; + PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); @@ -614,6 +609,7 @@ TEST_F(PrerenderTest, OfflinePrerenderIgnoresThirdPartyCookiesPref) { GURL url("http://www.google.com/"); test_utils::RestorePrerenderMode restore_prerender_mode; + PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); @@ -715,6 +711,7 @@ TEST_F(PrerenderTest, PrerenderDisabledOnLowEndDevice) { GURL url("http://www.google.com/"); + prerender_manager()->SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); prerender_manager()->SetIsLowEndDevice(true); EXPECT_FALSE(AddSimplePrerender(url)); @@ -724,6 +721,7 @@ TEST_F(PrerenderTest, OfflinePrerenderPossibleOnLowEndDevice) { GURL url("http://www.google.com/"); + prerender_manager()->SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); prerender_manager()->SetIsLowEndDevice(true); @@ -1393,6 +1391,8 @@ TEST_F(PrerenderTest, OmniboxNotAllowedWhenDisabled) { DisablePrerender(); + test_utils::RestorePrerenderMode restore_prerender_mode; + PrerenderManager::SetOmniboxMode(PrerenderManager::PRERENDER_MODE_ENABLED); EXPECT_FALSE(prerender_manager()->AddPrerenderFromOmnibox( GURL("http://www.example.com"), nullptr, gfx::Size())); histogram_tester().ExpectUniqueSample("Prerender.FinalStatus",
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc index 57dd9473..180eb1f 100644 --- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -370,7 +370,7 @@ ASSERT_TRUE(AppsMatchChecker().Wait()); } -IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkApp) { +IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkAppBasic) { ASSERT_TRUE(SetupSync()); ASSERT_TRUE(AllProfilesHaveSameApps()); @@ -378,7 +378,8 @@ GetExtensionRegistry(GetProfile(0))->enabled_extensions().size(); WebApplicationInfo web_app_info; - web_app_info.app_url = GURL("http://www.chromium.org"); + web_app_info.app_url = GURL("http://www.chromium.org/"); + web_app_info.scope = GURL("http://www.chromium.org/"); web_app_info.title = base::UTF8ToUTF16("Test name"); web_app_info.description = base::UTF8ToUTF16("Test description"); ++num_extensions; @@ -401,6 +402,36 @@ } } +IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkAppMinimal) { + ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(AllProfilesHaveSameApps()); + + size_t num_extensions = + GetExtensionRegistry(GetProfile(0))->enabled_extensions().size(); + + WebApplicationInfo web_app_info; + web_app_info.app_url = GURL("http://www.chromium.org/"); + web_app_info.title = base::UTF8ToUTF16("Test name"); + ++num_extensions; + { + content::WindowedNotificationObserver windowed_observer( + extensions::NOTIFICATION_CRX_INSTALLER_DONE, + content::NotificationService::AllSources()); + extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)), + &web_app_info); + windowed_observer.Wait(); + EXPECT_EQ(num_extensions, + GetExtensionRegistry(GetProfile(0))->enabled_extensions().size()); + } + { + // Wait for the synced app to install. + content::WindowedNotificationObserver windowed_observer( + extensions::NOTIFICATION_CRX_INSTALLER_DONE, + base::Bind(&AllProfilesHaveSameApps)); + windowed_observer.Wait(); + } +} + // TODO(akalin): Add tests exercising: // - Offline installation/uninstallation behavior // - App-specific properties
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index b4405a80..f7cacafa 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -124,6 +124,23 @@ ExtensionRegistry::TERMINATED); } +bool IsAllowedToOverrideURL(const extensions::Extension* extension, + const GURL& override_url) { + if (extension->web_extent().MatchesURL(override_url)) + return true; + + if (override_url.GetOrigin() == extension->url()) + return true; + + if (extension->from_bookmark() && + extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin() == + override_url.GetOrigin()) { + return true; + } + + return false; +} + // Get the launch URL for a given extension, with optional override/fallback. // |override_url|, if non-empty, will be preferred over the extension's // launch url. @@ -134,8 +151,7 @@ GURL url; if (!override_url.is_empty()) { - DCHECK(extension->web_extent().MatchesURL(override_url) || - override_url.GetOrigin() == extension->url()); + DCHECK(IsAllowedToOverrideURL(extension, override_url)); url = override_url; } else { url = extensions::AppLaunchInfo::GetFullLaunchURL(extension);
diff --git a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc index 55cc8da..abcf4e7 100644 --- a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc +++ b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/prerender/prerender_origin.h" #include "chrome/browser/prerender/prerender_tab_helper.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/instant_unittest_base.h" @@ -187,12 +188,25 @@ InstantSearchPrerendererTest() {} protected: + using RestorePrerenderMode = prerender::test_utils::RestorePrerenderMode; + void SetUp() override { ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", "Group1 strk:20")); + + // Prerender mode is stored in a few static variables. Remember the default + // mode to restore it later in TearDown() to avoid affecting other tests. + restore_prerender_mode_ = base::MakeUnique<RestorePrerenderMode>(); + PrerenderManager::SetInstantMode(PrerenderManager::PRERENDER_MODE_ENABLED); + InstantUnitTestBase::SetUp(); } + void TearDown() override { + InstantUnitTestBase::TearDown(); + restore_prerender_mode_.reset(); + } + void Init(bool prerender_search_results_base_page, bool call_did_finish_load) { AddTab(browser(), GURL(url::kAboutBlankURL)); @@ -250,6 +264,7 @@ private: MockEmbeddedSearchClient mock_embedded_search_client_; + std::unique_ptr<RestorePrerenderMode> restore_prerender_mode_; }; TEST_F(InstantSearchPrerendererTest, GetSearchTermsFromPrerenderedPage) {
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json index dbb6b7d..de4250f 100644 --- a/chrome/common/extensions/api/_manifest_features.json +++ b/chrome/common/extensions/api/_manifest_features.json
@@ -259,6 +259,6 @@ }, "url_handlers": { "channel": "stable", - "extension_types": ["platform_app"] + "extension_types": ["hosted_app", "platform_app"] } }
diff --git a/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc b/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc index 4f971b9..90bf29d6 100644 --- a/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc +++ b/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc
@@ -134,6 +134,11 @@ } bool UrlHandlersParser::Parse(Extension* extension, base::string16* error) { + if (extension->GetType() == Manifest::TYPE_HOSTED_APP && + !extension->from_bookmark()) { + *error = base::ASCIIToUTF16(merrors::kUrlHandlersInHostedApps); + return false; + } std::unique_ptr<UrlHandlers> info(new UrlHandlers); const base::DictionaryValue* all_handlers = NULL; if (!extension->manifest()->GetDictionary( @@ -142,7 +147,7 @@ return false; } - DCHECK(extension->is_platform_app()); + DCHECK(extension->is_platform_app() || extension->from_bookmark()); for (base::DictionaryValue::Iterator iter(*all_handlers); !iter.IsAtEnd(); iter.Advance()) {
diff --git a/chrome/common/web_application_info.h b/chrome/common/web_application_info.h index 5fa31ef1..4083eb5a 100644 --- a/chrome/common/web_application_info.h +++ b/chrome/common/web_application_info.h
@@ -45,6 +45,9 @@ // The launch URL for the app. GURL app_url; + // Scope for the app. Dictates what URLs will be opened in the app. + GURL scope; + // Set of available icons. std::vector<IconInfo> icons;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4853a9b..06d7529 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1905,6 +1905,7 @@ "../browser/extensions/background_scripts_apitest.cc", "../browser/extensions/background_xhr_browsertest.cc", "../browser/extensions/bookmark_app_helper_browsertest.cc", + "../browser/extensions/bookmark_app_url_redirector_browsertest.cc", "../browser/extensions/browsertest_util.cc", "../browser/extensions/browsertest_util.h", "../browser/extensions/browsertest_util_browsertest.cc",
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html b/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html b/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html b/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html
diff --git a/components/sync/protocol/app_specifics.proto b/components/sync/protocol/app_specifics.proto index a7234e6..52440cf 100644 --- a/components/sync/protocol/app_specifics.proto +++ b/components/sync/protocol/app_specifics.proto
@@ -91,4 +91,7 @@ // This is information about linked icons (that is, icons that are downloaded // from outside the app's bundle of files. repeated LinkedAppIconInfo linked_app_icons = 9; + + // This is the scope of the bookmark app. + optional string bookmark_app_scope = 10; }
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 3cd5a423..8ffaca5 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -124,6 +124,7 @@ VISIT(bookmark_app_description); VISIT(bookmark_app_icon_color); VISIT_REP(linked_app_icons); + VISIT(bookmark_app_scope); } VISIT_PROTO_FIELDS(const sync_pb::ArcPackageSpecifics& proto) {
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc index f7fb38a..e858ea85 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -80,62 +80,62 @@ void RecordEQTAccuracy(base::TimeDelta queueing_time, base::TimeDelta expected_queueing_time) { - float expected_queueing_time_ms = expected_queueing_time.InMillisecondsF(); + float queueing_time_ms = queueing_time.InMillisecondsF(); - if (expected_queueing_time_ms < 10) { + if (queueing_time_ms < 10) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.10ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms", + expected_queueing_time); } - if (expected_queueing_time_ms < 150) { + if (queueing_time_ms < 150) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.150ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms", + expected_queueing_time); } - if (expected_queueing_time_ms < 300) { + if (queueing_time_ms < 300) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.300ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms", + expected_queueing_time); } - if (expected_queueing_time_ms < 450) { + if (queueing_time_ms < 450) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.450ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms", + expected_queueing_time); } - if (expected_queueing_time_ms > 10) { + if (queueing_time_ms > 10) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.10ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms", + expected_queueing_time); } - if (expected_queueing_time_ms > 150) { + if (queueing_time_ms > 150) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.150ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms", + expected_queueing_time); } - if (expected_queueing_time_ms > 300) { + if (queueing_time_ms > 300) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.300ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms", + expected_queueing_time); } - if (expected_queueing_time_ms > 450) { + if (queueing_time_ms > 450) { UMA_HISTOGRAM_TIMES( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.450ms", - queueing_time); + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms", + expected_queueing_time); } }
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc index ca8efa8a..459fac3 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -1300,11 +1300,15 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ExpectedQueueingTimeAccuracy) { // These numbers are sensitive to where the histogram buckets are. - int event_timestamps_ms[] = {11, 25, 35}; + base::TimeTicks event_timestamp = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(11); + int expected_queueing_time_ms = 1; + base::TimeDelta expected_queueing_time = + base::TimeDelta::FromMilliseconds(expected_queueing_time_ms); - for (float expected_queueing_time_ms : {2, 15, 200, 400}) { - base::TimeDelta expected_queueing_time = - base::TimeDelta::FromMilliseconds(expected_queueing_time_ms); + for (float queueing_time_ms : {2, 15, 200, 400}) { + base::TimeDelta queueing_time = + base::TimeDelta::FromMilliseconds(queueing_time_ms); SyntheticWebTouchEvent event; // Touch start. event.PressPoint(1, 1); @@ -1319,22 +1323,15 @@ fake_latency.set_source_event_type(ui::SourceEventType::TOUCH); fake_latency.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, - tracker()->latency_component_id(), 0, - base::TimeTicks() + - base::TimeDelta::FromMilliseconds(event_timestamps_ms[0]), - 1); + tracker()->latency_component_id(), 0, event_timestamp, 1); fake_latency.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0, - base::TimeTicks() + - base::TimeDelta::FromMilliseconds(event_timestamps_ms[1]), - 1); + event_timestamp + queueing_time, 1); fake_latency.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0, - base::TimeTicks() + - base::TimeDelta::FromMilliseconds(event_timestamps_ms[2]), - 1); + event_timestamp + queueing_time, 1); // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck // overwriting components. @@ -1346,51 +1343,44 @@ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); } - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.10ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 1))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.150ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 2))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.300ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 3))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_LessThan.450ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 4))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.10ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 3))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.150ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 2))); - - EXPECT_THAT( - histogram_tester().GetAllSamples( - "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.300ms"), - ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 1))); + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 1))); EXPECT_THAT(histogram_tester().GetAllSamples( "RendererScheduler." - "QueueingDurationWhenExpectedQueueingTime_GreaterThan.450ms"), + "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 2))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 3))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 4))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 3))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 2))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms"), + ElementsAre(Bucket(expected_queueing_time_ms, 1))); + + EXPECT_THAT(histogram_tester().GetAllSamples( + "RendererScheduler." + "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms"), ElementsAre()); }
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index f03ad79..3bd1ec7 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -745,6 +745,8 @@ const char kUnrecognizedManifestKey[] = "Unrecognized manifest key '*'."; const char kUnrecognizedManifestProperty[] = "Unrecognized property '*' of manifest key '*'."; +const char kUrlHandlersInHostedApps[] = + "'url_handlers' cannot be used in Hosted Apps."; const char kWebRequestConflictsWithLazyBackground[] = "The 'webRequest' API cannot be used with event pages."; #if defined(OS_CHROMEOS)
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index 03d20a6..7ec835b 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -496,6 +496,7 @@ extern const char kRulesFileIsInvalid[]; extern const char kUnrecognizedManifestKey[]; extern const char kUnrecognizedManifestProperty[]; +extern const char kUrlHandlersInHostedApps[]; extern const char kWebRequestConflictsWithLazyBackground[]; #if defined(OS_CHROMEOS) extern const char kDuplicateActionHandlerFound[];
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index 1ecf4cc..cc8ae9b 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -21,6 +21,7 @@ #include "base/strings/string_number_conversions.h" #include "base/task_scheduler/post_task.h" #include "content/public/app/content_main.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" #include "headless/app/headless_shell.h" #include "headless/app/headless_shell_switches.h" @@ -31,6 +32,7 @@ #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/http/http_util.h" +#include "ui/base/ui_base_switches.h" #include "ui/gfx/geometry/size.h" #if defined(OS_WIN) @@ -83,6 +85,11 @@ browser_->CreateBrowserContextBuilder(); // TODO(eseckler): These switches should also affect BrowserContexts that // are created via DevTools later. + if (base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kLang)) { + context_builder.SetAcceptLanguage( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + ::switches::kLang)); + } DeterministicHttpProtocolHandler* http_handler = nullptr; DeterministicHttpProtocolHandler* https_handler = nullptr; if (base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -153,6 +160,10 @@ web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get()); } } + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDeterministicFetch)) { + devtools_client_->GetNetwork()->GetExperimental()->RemoveObserver(this); + } web_contents_->RemoveObserver(this); web_contents_ = nullptr; browser_context_->Close(); @@ -160,6 +171,7 @@ } void HeadlessShell::DevToolsTargetReady() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get()); devtools_client_->GetInspector()->GetExperimental()->AddObserver(this); devtools_client_->GetPage()->GetExperimental()->AddObserver(this); @@ -169,6 +181,7 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDeterministicFetch)) { + devtools_client_->GetNetwork()->GetExperimental()->AddObserver(this); devtools_client_->GetNetwork() ->GetExperimental() ->SetRequestInterceptionEnabled( @@ -250,6 +263,7 @@ } void HeadlessShell::PollReadyState() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // We need to check the current location in addition to the ready state to // be sure the expected page is ready. devtools_client_->GetRuntime()->Evaluate( @@ -293,10 +307,11 @@ // network::Observer implementation: void HeadlessShell::OnRequestIntercepted( const headless::network::RequestInterceptedParams& params) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (params.GetIsNavigationRequest()) { deterministic_dispatcher_->NavigationRequested( base::MakeUnique<ShellNavigationRequest>(weak_factory_.GetWeakPtr(), - params)); + params.GetInterceptionId())); return; } devtools_client_->GetNetwork()->GetExperimental()->ContinueInterceptedRequest( @@ -329,6 +344,7 @@ } void HeadlessShell::FetchDom() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); devtools_client_->GetRuntime()->Evaluate( "document.body.outerHTML", base::Bind(&HeadlessShell::OnDomFetched, weak_factory_.GetWeakPtr())); @@ -349,6 +365,7 @@ } void HeadlessShell::InputExpression() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Note that a real system should read user input asynchronously, because // otherwise all other browser activity is suspended (e.g., page loading). printf(">>> "); @@ -379,6 +396,7 @@ } void HeadlessShell::CaptureScreenshot() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); devtools_client_->GetPage()->GetExperimental()->CaptureScreenshot( page::CaptureScreenshotParams::Builder().Build(), base::Bind(&HeadlessShell::OnScreenshotCaptured, @@ -397,6 +415,7 @@ } void HeadlessShell::PrintToPDF() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); devtools_client_->GetPage()->GetExperimental()->PrintToPDF( page::PrintToPDFParams::Builder() .SetDisplayHeaderFooter(true) @@ -418,6 +437,7 @@ void HeadlessShell::WriteFile(const std::string& file_path_switch, const std::string& default_file_name, const std::string& base64_data) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::FilePath file_name = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( file_path_switch); @@ -437,6 +457,7 @@ void HeadlessShell::OnFileOpened(const std::string& base64_data, const base::FilePath file_name, base::File::Error error_code) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!file_proxy_->IsValid()) { LOG(ERROR) << "Writing to file " << file_name.value() << " was unsuccessful, could not open file: " @@ -469,6 +490,7 @@ const size_t length, base::File::Error error_code, int write_result) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (write_result < static_cast<int>(length)) { // TODO(eseckler): Support recovering from partial writes. LOG(ERROR) << "Writing to file " << file_name.value()
diff --git a/headless/app/shell_navigation_request.cc b/headless/app/shell_navigation_request.cc index b63ba4e..64d5840 100644 --- a/headless/app/shell_navigation_request.cc +++ b/headless/app/shell_navigation_request.cc
@@ -4,38 +4,73 @@ #include "headless/app/shell_navigation_request.h" +#include "content/public/browser/browser_thread.h" #include "headless/app/headless_shell.h" namespace headless { ShellNavigationRequest::ShellNavigationRequest( base::WeakPtr<HeadlessShell> headless_shell, - const network::RequestInterceptedParams& params) - : headless_shell_(headless_shell), - interception_id_(params.GetInterceptionId()) {} + const std::string& interception_id) + : headless_shell_( + base::MakeUnique<base::WeakPtr<HeadlessShell>>(headless_shell)), + interception_id_(interception_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} ShellNavigationRequest::~ShellNavigationRequest() {} void ShellNavigationRequest::StartProcessing(base::Closure done_callback) { - if (!headless_shell_) + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // The devtools bindings can only be called on the UI thread. + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ShellNavigationRequest::StartProcessingOnUiThread, + base::Passed(std::move(headless_shell_)), interception_id_, + std::move(done_callback))); +} + +// static +void ShellNavigationRequest::StartProcessingOnUiThread( + std::unique_ptr<base::WeakPtr<HeadlessShell>> headless_shell, + std::string interception_id, + base::Closure done_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!headless_shell) return; // Allow the navigation to proceed. - headless_shell_->devtools_client() + (*headless_shell) + ->devtools_client() ->GetNetwork() ->GetExperimental() ->ContinueInterceptedRequest( headless::network::ContinueInterceptedRequestParams::Builder() - .SetInterceptionId(interception_id_) + .SetInterceptionId(interception_id) .Build(), base::Bind(&ShellNavigationRequest::ContinueInterceptedRequestResult, - done_callback)); + std::move(done_callback))); } // static void ShellNavigationRequest::ContinueInterceptedRequestResult( base::Closure done_callback, std::unique_ptr<network::ContinueInterceptedRequestResult>) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // The |done_callback| must be fired on the IO thread. + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind( + &ShellNavigationRequest::ContinueInterceptedRequestResultOnIoThread, + std::move(done_callback))); +} + +// static +void ShellNavigationRequest::ContinueInterceptedRequestResultOnIoThread( + base::Closure done_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); done_callback.Run(); }
diff --git a/headless/app/shell_navigation_request.h b/headless/app/shell_navigation_request.h index 1199f28..1abad6e 100644 --- a/headless/app/shell_navigation_request.h +++ b/headless/app/shell_navigation_request.h
@@ -19,20 +19,31 @@ class ShellNavigationRequest : public NavigationRequest { public: ShellNavigationRequest(base::WeakPtr<HeadlessShell> headless_shell, - const network::RequestInterceptedParams& params); + const std::string& interception_id); ~ShellNavigationRequest() override; void StartProcessing(base::Closure done_callback) override; private: + static void StartProcessingOnUiThread( + std::unique_ptr<base::WeakPtr<HeadlessShell>> headless_shell, + std::string interception_id, + base::Closure done_callback); + // Note the navigation likely isn't done when this is called, however we // expect it will have been committed and the initial resource load requested. static void ContinueInterceptedRequestResult( base::Closure done_callback, std::unique_ptr<network::ContinueInterceptedRequestResult>); - base::WeakPtr<HeadlessShell> headless_shell_; + static void ContinueInterceptedRequestResultOnIoThread( + base::Closure done_callback); + + // Yuck we need to post a weak pointer from the IO -> UI threads but WeakPtr + // is super finicky about which threads it's touched on. By boxing this up in + // a unique_ptr we can pass it about and only touch it on the UI thread. + std::unique_ptr<base::WeakPtr<HeadlessShell>> headless_shell_; std::string interception_id_; };
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc index 9debdd07..bdcaad176 100644 --- a/headless/lib/browser/headless_browser_context_impl.cc +++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -92,6 +92,13 @@ HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Inform observers that we're going away. + { + base::AutoLock lock(observers_lock_); + for (auto& observer : observers_) + observer.OnHeadlessBrowserContextDestruct(); + } + // Destroy all web contents before shutting down storage partitions. web_contents_map_.clear();
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc index 0b24e77..f528710 100644 --- a/headless/lib/browser/headless_content_browser_client.cc +++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -28,6 +28,7 @@ #include "headless/lib/browser/headless_devtools_manager_delegate.h" #include "headless/lib/browser/headless_quota_permission_context.h" #include "headless/lib/headless_macros.h" +#include "net/base/url_util.h" #include "storage/browser/quota/quota_settings.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" @@ -254,8 +255,18 @@ bool expired_previous_decision, const base::Callback<void(content::CertificateRequestResultType)>& callback) { - if (!callback.is_null()) + if (!callback.is_null()) { + // If --allow-insecure-localhost is specified, and the request + // was for localhost, then the error was not fatal. + bool allow_localhost = base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kAllowInsecureLocalhost); + if (allow_localhost && net::IsLocalhost(request_url.host())) { + callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE); + return; + } + callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY); + } } void HeadlessContentBrowserClient::ResourceDispatcherHostCreated() {
diff --git a/headless/lib/browser/headless_network_delegate.cc b/headless/lib/browser/headless_network_delegate.cc index d6722a6..c99c015 100644 --- a/headless/lib/browser/headless_network_delegate.cc +++ b/headless/lib/browser/headless_network_delegate.cc
@@ -21,9 +21,17 @@ HeadlessNetworkDelegate::HeadlessNetworkDelegate( HeadlessBrowserContextImpl* headless_browser_context) - : headless_browser_context_(headless_browser_context) {} + : headless_browser_context_(headless_browser_context) { + base::AutoLock lock(lock_); + if (headless_browser_context_) + headless_browser_context_->AddObserver(this); +} -HeadlessNetworkDelegate::~HeadlessNetworkDelegate() {} +HeadlessNetworkDelegate::~HeadlessNetworkDelegate() { + base::AutoLock lock(lock_); + if (headless_browser_context_) + headless_browser_context_->RemoveObserver(this); +} int HeadlessNetworkDelegate::OnBeforeURLRequest( net::URLRequest* request, @@ -62,7 +70,8 @@ void HeadlessNetworkDelegate::OnCompleted(net::URLRequest* request, bool started, int net_error) { - if (net_error != net::OK) + base::AutoLock lock(lock_); + if (headless_browser_context_ && net_error != net::OK) headless_browser_context_->NotifyUrlRequestFailed(request, net_error); } @@ -98,4 +107,9 @@ return true; } +void HeadlessNetworkDelegate::OnHeadlessBrowserContextDestruct() { + base::AutoLock lock(lock_); + headless_browser_context_ = nullptr; +} + } // namespace headless
diff --git a/headless/lib/browser/headless_network_delegate.h b/headless/lib/browser/headless_network_delegate.h index fc11b76..ccfb5f6 100644 --- a/headless/lib/browser/headless_network_delegate.h +++ b/headless/lib/browser/headless_network_delegate.h
@@ -7,6 +7,8 @@ #include "base/macros.h" +#include "base/synchronization/lock.h" +#include "headless/public/headless_browser_context.h" #include "net/base/network_delegate_impl.h" namespace headless { @@ -14,13 +16,15 @@ // We use the HeadlessNetworkDelegate to remove DevTools request headers before // requests are actually fetched and for reporting failed network requests. -class HeadlessNetworkDelegate : public net::NetworkDelegateImpl { +class HeadlessNetworkDelegate : public net::NetworkDelegateImpl, + public HeadlessBrowserContext::Observer { public: explicit HeadlessNetworkDelegate( HeadlessBrowserContextImpl* headless_browser_context); ~HeadlessNetworkDelegate() override; private: + // net::NetworkDelegateImpl implementation: int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) override; @@ -69,6 +73,10 @@ const base::FilePath& original_path, const base::FilePath& absolute_path) const override; + // HeadlessBrowserContext::Observer implementation: + void OnHeadlessBrowserContextDestruct() override; + + base::Lock lock_; // Protects |headless_browser_context_|. HeadlessBrowserContextImpl* headless_browser_context_; // Not owned. DISALLOW_COPY_AND_ASSIGN(HeadlessNetworkDelegate);
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc index 49cb38e..a2dbb0d 100644 --- a/headless/lib/browser/headless_url_request_context_getter.cc +++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/task_scheduler/post_task.h" #include "content/public/browser/browser_thread.h" +#include "headless/lib/browser/headless_browser_context_impl.h" #include "headless/lib/browser/headless_browser_context_options.h" #include "headless/lib/browser/headless_network_delegate.h" #include "net/dns/mapped_host_resolver.h" @@ -56,9 +57,15 @@ proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService(io_task_runner_); } + base::AutoLock lock(lock_); + headless_browser_context_->AddObserver(this); } -HeadlessURLRequestContextGetter::~HeadlessURLRequestContextGetter() {} +HeadlessURLRequestContextGetter::~HeadlessURLRequestContextGetter() { + base::AutoLock lock(lock_); + if (headless_browser_context_) + headless_browser_context_->RemoveObserver(this); +} net::URLRequestContext* HeadlessURLRequestContextGetter::GetURLRequestContext() { @@ -76,8 +83,12 @@ } else { builder.set_proxy_config_service(std::move(proxy_config_service_)); } - builder.set_network_delegate( - base::MakeUnique<HeadlessNetworkDelegate>(headless_browser_context_)); + + { + base::AutoLock lock(lock_); + builder.set_network_delegate( + base::MakeUnique<HeadlessNetworkDelegate>(headless_browser_context_)); + } if (!host_resolver_rules_.empty()) { std::unique_ptr<net::HostResolver> host_resolver( @@ -111,4 +122,9 @@ return url_request_context_->host_resolver(); } +void HeadlessURLRequestContextGetter::OnHeadlessBrowserContextDestruct() { + base::AutoLock lock(lock_); + headless_browser_context_ = nullptr; +} + } // namespace headless
diff --git a/headless/lib/browser/headless_url_request_context_getter.h b/headless/lib/browser/headless_url_request_context_getter.h index 5afab88..92341b3 100644 --- a/headless/lib/browser/headless_url_request_context_getter.h +++ b/headless/lib/browser/headless_url_request_context_getter.h
@@ -30,7 +30,9 @@ class HeadlessBrowserContextOptions; class HeadlessBrowserContextImpl; -class HeadlessURLRequestContextGetter : public net::URLRequestContextGetter { +class HeadlessURLRequestContextGetter + : public net::URLRequestContextGetter, + public HeadlessBrowserContext::Observer { public: HeadlessURLRequestContextGetter( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, @@ -48,6 +50,9 @@ net::HostResolver* host_resolver() const; + // HeadlessBrowserContext::Observer implementation: + void OnHeadlessBrowserContextDestruct() override; + protected: ~HeadlessURLRequestContextGetter() override; @@ -66,7 +71,9 @@ std::unique_ptr<net::URLRequestContext> url_request_context_; content::ProtocolHandlerMap protocol_handlers_; content::URLRequestInterceptorScopedVector request_interceptors_; - net::NetLog* net_log_; // Not owned. + net::NetLog* net_log_; // Not owned + + base::Lock lock_; // Protects |headless_browser_context_|. HeadlessBrowserContextImpl* headless_browser_context_; // Not owned. DISALLOW_COPY_AND_ASSIGN(HeadlessURLRequestContextGetter);
diff --git a/headless/lib/headless_browser_browsertest.cc b/headless/lib/headless_browser_browsertest.cc index 1206725..7bb186f 100644 --- a/headless/lib/headless_browser_browsertest.cc +++ b/headless/lib/headless_browser_browsertest.cc
@@ -13,6 +13,8 @@ #include "base/threading/thread_restrictions.h" #include "content/public/browser/permission_manager.h" #include "content/public/browser/permission_type.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test.h" #include "headless/lib/browser/headless_browser_context_impl.h" @@ -913,4 +915,26 @@ EvaluateScript(web_contents, "window.print()")->HasExceptionDetails()); } +IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, AllowInsecureLocalhostFlag) { + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); + https_server.ServeFilesFromSourceDirectory("headless/test/data"); + ASSERT_TRUE(https_server.Start()); + GURL test_url = https_server.GetURL("/hello.html"); + + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kAllowInsecureLocalhost); + + HeadlessBrowserContext* browser_context = + browser()->CreateBrowserContextBuilder().Build(); + + HeadlessWebContentsImpl* web_contents = + HeadlessWebContentsImpl::From(browser_context->CreateWebContentsBuilder() + .SetInitialURL(test_url) + .Build()); + + // If the certificate fails to validate, this should fail. + EXPECT_TRUE(WaitForLoad(web_contents)); +} + } // namespace headless
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index b6291622..5557274 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -459,11 +459,7 @@ } }; -#if defined(OS_WIN) -DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateAndDeletePageTest); -#else HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateAndDeletePageTest); -#endif class TargetDomainCreateAndDeleteBrowserContextTest : public HeadlessAsyncDevTooledBrowserTest { @@ -531,12 +527,7 @@ std::string browser_context_id_; }; -#if defined(OS_WIN) -DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_F( - TargetDomainCreateAndDeleteBrowserContextTest); -#else HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateAndDeleteBrowserContextTest); -#endif class TargetDomainDisposeContextFailsIfInUse : public HeadlessAsyncDevTooledBrowserTest { @@ -612,13 +603,7 @@ std::string page_id_; }; -// Test is flaky on Linux debug (https://crbug.com/751180) -#if defined(OS_WIN) || defined(OS_LINUX) -DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_F( - TargetDomainDisposeContextFailsIfInUse); -#else HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainDisposeContextFailsIfInUse); -#endif class TargetDomainCreateTwoContexts : public HeadlessAsyncDevTooledBrowserTest, public target::ExperimentalObserver, @@ -890,11 +875,7 @@ int context_closed_count_ = 0; }; -#if defined(OS_WIN) -DISABLED_HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateTwoContexts); -#else HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateTwoContexts); -#endif class HeadlessDevToolsNavigationControlTest : public HeadlessAsyncDevTooledBrowserTest, @@ -1448,6 +1429,8 @@ } void OnLoadEventFired(const page::LoadEventFiredParams&) override { + browser_context_->RemoveObserver(this); + base::AutoLock lock(lock_); EXPECT_EQ("iframe.html", url_that_failed_to_load_); FinishAsynchronousTest();
diff --git a/headless/lib/headless_web_contents_browsertest.cc b/headless/lib/headless_web_contents_browsertest.cc index 0f2ed053..8403fce 100644 --- a/headless/lib/headless_web_contents_browsertest.cc +++ b/headless/lib/headless_web_contents_browsertest.cc
@@ -117,6 +117,8 @@ EXPECT_EQ(expected_bounds.size(), child->web_contents()->GetContainerBounds().size()); #endif // !defined(OS_MACOSX) + + browser_context->RemoveObserver(&observer); } class HeadlessWindowOpenTabSocketTest : public HeadlessBrowserTest, @@ -239,6 +241,8 @@ RunAsynchronousTest(); EXPECT_EQ("Embedder sent us: One", message_); + + browser_context->RemoveObserver(this); } class HeadlessNoDevToolsTabSocketTest : public HeadlessBrowserTest,
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h index a2cc3b1a..6cb289f2 100644 --- a/headless/public/headless_browser_context.h +++ b/headless/public/headless_browser_context.h
@@ -88,6 +88,9 @@ // thread. virtual void UrlRequestFailed(net::URLRequest* request, int net_error) {} + // Indicates the HeadlessBrowserContext is about to be deleted. + virtual void OnHeadlessBrowserContextDestruct() {} + protected: virtual ~Observer() {} };
diff --git a/ios/chrome/browser/content_suggestions/BUILD.gn b/ios/chrome/browser/content_suggestions/BUILD.gn index c0fe0e0..e4c37000 100644 --- a/ios/chrome/browser/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/content_suggestions/BUILD.gn
@@ -40,6 +40,7 @@ "//ios/chrome/browser/ntp_snippets", "//ios/chrome/browser/ntp_tiles", "//ios/chrome/browser/reading_list", + "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/collection_view/cells",
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm index 70069b59..4517196 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_coordinator.mm
@@ -10,7 +10,6 @@ #include "base/metrics/user_metrics_action.h" #include "base/strings/sys_string_conversions.h" #include "components/ntp_snippets/content_suggestions_service.h" -#include "components/ntp_snippets/ntp_snippets_constants.h" #include "components/ntp_snippets/remote/remote_suggestions_scheduler.h" #include "components/ntp_tiles/metrics.h" #include "components/ntp_tiles/most_visited_sites.h" @@ -28,6 +27,7 @@ #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h" #include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#include "ios/chrome/browser/tabs/tab_constants.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" @@ -196,7 +196,7 @@ // Use a referrer with a specific URL to mark this entry as coming from // ContentSuggestions. web::Referrer referrer; - referrer.url = GURL(ntp_snippets::kContentSuggestionsApiScope); + referrer.url = GURL(tab_constants::kDoNotConsiderForMostVisited); [self.URLLoader loadURL:suggestionItem.URL referrer:referrer
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index e579a27..608365a 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -78,16 +78,6 @@ <key>Type</key> <string>PSToggleSwitchSpecifier</string> <key>Title</key> - <string>Fake Cloud Policy Type</string> - <key>Key</key> - <string>FakeCloudPolicyType</string> - <key>DefaultValue</key> - <false/> - </dict> - <dict> - <key>Type</key> - <string>PSToggleSwitchSpecifier</string> - <key>Title</key> <string>Force First Run</string> <key>Key</key> <string>FirstRunForceEnabled</string>
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index ad2aa9e..06514de 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -6,6 +6,7 @@ sources = [ "legacy_tab_helper.h", "tab.h", + "tab_constants.h", "tab_delegate.h", "tab_dialog_delegate.h", "tab_headers_delegate.h", @@ -39,6 +40,7 @@ "legacy_tab_helper.mm", "tab.h", "tab.mm", + "tab_constants.cc", "tab_helper_util.mm", "tab_model.mm", "tab_model_closing_web_state_observer.h",
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index f0bc0c1..774a17e 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -73,6 +73,7 @@ #import "ios/chrome/browser/snapshots/snapshot_overlay_provider.h" #import "ios/chrome/browser/snapshots/web_controller_snapshot_helper.h" #import "ios/chrome/browser/tabs/legacy_tab_helper.h" +#include "ios/chrome/browser/tabs/tab_constants.h" #import "ios/chrome/browser/tabs/tab_delegate.h" #import "ios/chrome/browser/tabs/tab_dialog_delegate.h" #import "ios/chrome/browser/tabs/tab_headers_delegate.h" @@ -163,10 +164,6 @@ const char kRendererTerminationStateHistogram[] = "Tab.StateAtRendererTermination"; -// Referrer used for clicks on article suggestions on the NTP. -const char kChromeContentSuggestionsReferrer[] = - "https://www.googleapis.com/auth/chrome-content-suggestions"; - // Enum corresponding to UMA's TabForegroundState, for // Tab.StateAtRendererTermination. Must be kept in sync with the UMA enum. enum class RendererTerminationTabState { @@ -882,7 +879,7 @@ // Clicks on content suggestions on the NTP should not contribute to the // Most Visited tiles in the NTP. const bool considerForNTPMostVisited = - referrer.url != GURL(kChromeContentSuggestionsReferrer); + referrer.url != GURL(tab_constants::kDoNotConsiderForMostVisited); history::HistoryAddPageArgs args( url, item->GetTimestamp(), &_tabHistoryContext, item->GetUniqueID(), referrer.url, redirects, item->GetTransitionType(),
diff --git a/ios/chrome/browser/tabs/tab_constants.cc b/ios/chrome/browser/tabs/tab_constants.cc new file mode 100644 index 0000000..c8b967f --- /dev/null +++ b/ios/chrome/browser/tabs/tab_constants.cc
@@ -0,0 +1,10 @@ +// 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 "ios/chrome/browser/tabs/tab_constants.h" + +namespace tab_constants { +const char kDoNotConsiderForMostVisited[] = + "chrome://do_not_consider_for_most_visited"; +}
diff --git a/ios/chrome/browser/tabs/tab_constants.h b/ios/chrome/browser/tabs/tab_constants.h new file mode 100644 index 0000000..a591a0cb --- /dev/null +++ b/ios/chrome/browser/tabs/tab_constants.h
@@ -0,0 +1,14 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_TABS_TAB_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_TABS_TAB_CONSTANTS_H_ + +namespace tab_constants { +// URL used in referrer to signal that the navigation should not be taken into +// consideration when computing the Most Visited sites. +extern const char kDoNotConsiderForMostVisited[]; +} // namespace tab_constants + +#endif // IOS_CHROME_BROWSER_TABS_TAB_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm index 18ee041..5edcfca6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -162,7 +162,6 @@ _promoAdded = NO; _dataSource = dataSource; _dataSource.dataSink = self; - _sectionIdentifiersFromContentSuggestions = [[NSMutableSet alloc] init]; } return self; } @@ -588,6 +587,7 @@ - (void)resetModels { [self.collectionViewController loadModel]; self.sectionInfoBySectionIdentifier = [[NSMutableDictionary alloc] init]; + self.sectionIdentifiersFromContentSuggestions = [[NSMutableSet alloc] init]; } // Runs the additional action for the section identified by |sectionInfo|.
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index 7d6b9be..2bcb6572 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -34,6 +34,7 @@ "//ios/chrome/browser/favicon", "//ios/chrome/browser/feature_engagement", "//ios/chrome/browser/reading_list", + "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/favicon",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm index f97210f..d3d3cffa 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -18,6 +18,7 @@ #include "ios/chrome/browser/reading_list/reading_list_download_service.h" #include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#include "ios/chrome/browser/tabs/tab_constants.h" #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h" @@ -251,8 +252,13 @@ [readingListCollectionViewController willBeDismissed]; + // Use a referrer with a specific URL to signal that this entry should not be + // taken into account for the Most Visited tiles. + web::Referrer referrer; + referrer.url = GURL(tab_constants::kDoNotConsiderForMostVisited); + [self.URLLoader loadURL:entry->URL() - referrer:web::Referrer() + referrer:referrer transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK rendererInitiated:NO];
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8ba7ea4f..6066f78 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1457,6 +1457,30 @@ ] } ], + "NTPCondensedLayout": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "CondensedLayoutWithSmallLogo", + "params": { + "condensed_layout_logo_height": "50", + "condensed_layout_show_logo": "true", + "condensed_tile_layout_for_small_screens_enabled": "true" + }, + "enable_features": [ + "NTPCondensedLayout", + "NTPCondensedTileLayout" + ], + "disable_features": [ + "NTPShowGoogleGInOmnibox" + ] + } + ] + } + ], "NTPFaviconsFromNewServer": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 527b1d9..01c8bfd 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -612,11 +612,27 @@ # ====== DevTools test migration failures from here ====== # Temporary failures (these tests are moves from html to js) # See crbug.com/667560 for details +crbug.com/667560 http/tests/devtools/console/console-bind-fake.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-call-getter-on-proto.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-command-clear.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-control-characters.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-correct-suggestions.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-css-unterminated-comment.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-dir-deprecated.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-dir-global.js [ Skip ] +crbug.com/667560 http/tests/devtools/console/console-edit-property-value.js [ Skip ] ### virtual/mojo-loading/http/tests/devtools - -### Manually fix after migration -crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-dir.js [ NeedsManualRebaseline ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-bind-fake.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-call-getter-on-proto.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-command-clear.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-control-characters.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-correct-suggestions.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-css-unterminated-comment.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-dir-deprecated.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-dir-global.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-dir.js [ Skip ] +crbug.com/667560 virtual/mojo-loading/http/tests/devtools/console/console-edit-property-value.js [ Skip ] # ====== DevTools test migration failures until here ====== @@ -3086,6 +3102,4 @@ crbug.com/750310 [ Win7 Debug ] virtual/off-main-thread-fetch/http/tests/inspector/network/network-blocked-reason.html [ Timeout ] # Sheriff failures 2017-08-03 -crbug.com/751906 http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ] -crbug.com/751906 virtual/mojo-loading/http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ] crbug.com/751955 external/wpt/webusb/idlharness.https.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html b/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html index e4ca2d39..60f3b6b29 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html
@@ -25,8 +25,8 @@ }; var styleInvalidTests = { - 'weight': ['100 400'], - 'stretch': ['100% 110%', '0%', '100% 150%'] + 'weight': ['100 400', 'calc(0 - 100)', 'calc(200 + 801)'], + 'stretch': ['100% 110%', '0%', '100% 150%', 'calc(1 + 10%)'] }; function testParseStyle() { @@ -64,6 +64,9 @@ ['100%', '100%'], ['110%', '110%'], ['111.5%', '111.5%'], + [ "50% 200%", "50% 200%" ], + [ "0.1% 1%", "0.1% 1%" ], + [ "900% 901%", "900% 901%" ], ['ultra-condensed', 'ultra-condensed'], ['ultra-expanded', 'ultra-expanded'], ], @@ -82,8 +85,8 @@ 'a b c', ], 'stretch': [ - '0%', '60% 70% 80%', 'a%', 'a b c', '0.1', '-60% 80%', 'ultra-expannnned', - '50% 0' + '-0.5%', '-1%', '0%', 'calc(0% - 10%)', '60% 70% 80%', 'a%', 'a b c', '0.1', + '-60% 80%', 'ultra-expannnned', '50% 0' ], };
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-bind-fake.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-bind-fake.js index acb0e308..cb3a0046 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-bind-fake.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-bind-fake.js
@@ -1,22 +1,29 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> +var foo = 'fooValue'; -(async function() { - TestRunner.addResult(`Tests that overriding Function.prototype.bind does not break inspector.\n`); +Function.prototype.bind = function () { throw ":P"; }; - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); +function test() +{ + InspectorTest.evaluateInConsole("foo", step1); - await TestRunner.evaluateInPagePromise(` - var foo = 'fooValue'; - Function.prototype.bind = function () { throw ":P"; }; - `); + function step1() + { + InspectorTest.dumpConsoleMessages(); + InspectorTest.completeTest(); + } +} +</script> +</head> - ConsoleTestRunner.evaluateInConsole('foo', step1); +<body onload="runTest()"> +<p> +Tests that overriding Function.prototype.bind does not break inspector. +</p> - function step1() { - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } -})(); +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto-expected.txt index ad4c2dcb..c7870da 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto-expected.txt
@@ -1,6 +1,7 @@ +CONSOLE MESSAGE: line 21: [object Object] Tests that calling getter on prototype will call it on the object. -console-call-getter-on-proto.js:27 B {value: 239} +console-call-getter-on-proto.html:21 B {value: 239} foo: 239 value: 239 __proto__: A
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto.js index 5fba12f..327cb864 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-call-getter-on-proto.js
@@ -1,54 +1,58 @@ -// 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. - -(async function() { - TestRunner.addResult(`Tests that calling getter on prototype will call it on the object.\n`); - - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); - - await TestRunner.evaluateInPagePromise(` - function logObject() - { - var A = function() { this.value = 239; } - A.prototype = { - constructor: A, - get foo() - { - return this.value; - } +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> +function logObject() +{ + var A = function() { this.value = 239; } + A.prototype = { + constructor: A, + get foo() + { + return this.value; } - var B = function() { A.call(this); } - B.prototype = { - constructor: B, - __proto__: A.prototype - } - console.log(new B()); } - `); + var B = function() { A.call(this); } + B.prototype = { + constructor: B, + __proto__: A.prototype + } + console.log(new B()); +} - TestRunner.evaluateInPage('logObject()', step2); +function test() +{ + InspectorTest.evaluateInPage("logObject()", step2); + function step2() + { + InspectorTest.expandConsoleMessages(step3); + } + function expandTreeElementFilter(treeElement) + { + var name = treeElement.nameElement && treeElement.nameElement.textContent; + return name === "__proto__"; + } + function step3() + { + InspectorTest.expandConsoleMessages(step4, expandTreeElementFilter); + } + function step4() + { + InspectorTest.expandGettersInConsoleMessages(step5); + } + function step5() + { + InspectorTest.dumpConsoleMessages(false, false, InspectorTest.textContentWithLineBreaks); + InspectorTest.completeTest(); + } +} +</script> +</head> - function step2() { - ConsoleTestRunner.expandConsoleMessages(step3); - } - - function expandTreeElementFilter(treeElement) { - var name = treeElement.nameElement && treeElement.nameElement.textContent; - return name === '__proto__'; - } - - function step3() { - ConsoleTestRunner.expandConsoleMessages(step4, expandTreeElementFilter); - } - - function step4() { - ConsoleTestRunner.expandGettersInConsoleMessages(step5); - } - - function step5() { - ConsoleTestRunner.dumpConsoleMessages(false, false, TestRunner.textContentWithLineBreaks); - TestRunner.completeTest(); - } -})(); +<body onload="runTest()"> +<p> +Tests that calling getter on prototype will call it on the object. +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear-expected.txt index 5636c991..dc9c35e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear-expected.txt
@@ -1,9 +1,12 @@ +CONSOLE MESSAGE: line 9: one +CONSOLE MESSAGE: line 10: two +CONSOLE MESSAGE: line 11: three Tests that console is cleared upon clear() eval in console. === Before clear === -console-command-clear.js:14 one -console-command-clear.js:15 two -console-command-clear.js:16 three +console-command-clear.html:9 one +console-command-clear.html:10 two +console-command-clear.html:11 three === After clear === VM:1 Console was cleared
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear.js index 5b704d56..ed79daa 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-command-clear.js
@@ -1,31 +1,40 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> -(async function() { - TestRunner.addResult(`Tests that console is cleared upon clear() eval in console.\n`); +function log() { + // Fill console. + console.log("one"); + console.log("two"); + console.log("three"); +} - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); +log(); - await TestRunner.evaluateInPagePromise(` - function log() { - // Fill console. - console.log("one"); - console.log("two"); - console.log("three"); +function test() +{ + + InspectorTest.addResult("=== Before clear ==="); + InspectorTest.dumpConsoleMessages(); + + function callback() + { + InspectorTest.addResult("=== After clear ==="); + InspectorTest.dumpConsoleMessages(); + InspectorTest.completeTest(); } - log(); - `); + InspectorTest.evaluateInConsole("clear()", callback); +} - TestRunner.addResult('=== Before clear ==='); - ConsoleTestRunner.dumpConsoleMessages(); +</script> +</head> - function callback() { - TestRunner.addResult('=== After clear ==='); - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } +<body onload="runTest()"> +<p> + Tests that console is cleared upon clear() eval in console. +</p> - ConsoleTestRunner.evaluateInConsole('clear()', callback); -})(); +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-control-characters.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-control-characters.js index ce574d1..afdc95a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-control-characters.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-control-characters.js
@@ -1,17 +1,28 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> -(async function() { - TestRunner.addResult(`Verify that control characters are substituted with printable characters.\n`); +function test() +{ + // The following command has control character. + InspectorTest.evaluateInConsole("var\u001D i = 0;", onEvaluated); - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); + function onEvaluated() + { + InspectorTest.dumpConsoleMessages(); + InspectorTest.completeTest(); + } +} - ConsoleTestRunner.evaluateInConsole('var\u001d i = 0;', onEvaluated); +</script> +</head> - function onEvaluated() { - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } -})(); +<body onload="runTest()"> +<p> + Verify that control characters are substituted with printable characters. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-correct-suggestions.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-correct-suggestions.js index f68a830..b13a31f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-correct-suggestions.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-correct-suggestions.js
@@ -1,127 +1,123 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> +function templateString() +{ + console.log("The template string should not run and you should not see this log"); + return { + shouldNotFindThis:56 + }; +} -(async function() { - TestRunner.addResult(`Tests that console correctly finds suggestions in complicated cases.\n`); +function shouldNotFindThisFunction() { } +function shouldFindThisFunction() { } +window["should not find this"] = true; - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); - - await TestRunner.evaluateInPagePromise(` - function templateString() +var myMap = new Map([['first', 1], ['second', 2], ['third', 3], ['shouldNotFindThis', 4]]); +var complicatedObject = { + 'foo-bar': true, + '"double-qouted"': true, + "'single-qouted'": true, + "notDangerous();": true +} +function test() +{ + var consoleEditor; + function testCompletions(text, expected, force) { - console.log("The template string should not run and you should not see this log"); - return { - shouldNotFindThis:56 - }; - } - function shouldNotFindThisFunction() { } - function shouldFindThisFunction() { } - window["should not find this"] = true; - var myMap = new Map([['first', 1], ['second', 2], ['third', 3], ['shouldNotFindThis', 4]]); - var complicatedObject = { - 'foo-bar': true, - '"double-qouted"': true, - "'single-qouted'": true, - "notDangerous();": true - } - `); + var cursorPosition = text.indexOf('|'); + if (cursorPosition < 0) + cursorPosition = Infinity; + consoleEditor.setText(text.replace('|', '')); + consoleEditor.setSelection(TextUtils.TextRange.createFromLocation(0, cursorPosition)); + consoleEditor._autocompleteController.autocomplete(force); + return InspectorTest.addSnifferPromise(consoleEditor._autocompleteController, "_onSuggestionsShownForTest").then(checkExpected); - var consoleEditor; - - function testCompletions(text, expected, force) { - var cursorPosition = text.indexOf('|'); - - if (cursorPosition < 0) - cursorPosition = Infinity; - - consoleEditor.setText(text.replace('|', '')); - consoleEditor.setSelection(TextUtils.TextRange.createFromLocation(0, cursorPosition)); - consoleEditor._autocompleteController.autocomplete(force); - return TestRunner.addSnifferPromise(consoleEditor._autocompleteController, '_onSuggestionsShownForTest').then(checkExpected); - - function checkExpected(suggestions) { - var completions = new Map(suggestions.map(suggestion => [suggestion.text, suggestion])); - var message = 'Checking \'' + text.replace('\n', '\\n').replace('\r', '\\r') + '\''; - - if (force) - message += ' forcefully'; - - TestRunner.addResult(message); - - for (var i = 0; i < expected.length; i++) { - if (completions.has(expected[i])) { - if (completions.get(expected[i]).title) - TestRunner.addResult('Found: ' + expected[i] + ', displayed as ' + completions.get(expected[i]).title); - else - TestRunner.addResult('Found: ' + expected[i]); - } else { - TestRunner.addResult('Not Found: ' + expected[i]); + function checkExpected(suggestions) + { + var completions = new Map(suggestions.map(suggestion => [suggestion.text, suggestion])); + var message = "Checking '" + text.replace('\n', '\\n').replace('\r', '\\r') + "'"; + if (force) + message += " forcefully"; + InspectorTest.addResult(message); + for (var i = 0; i < expected.length; i++) { + if (completions.has(expected[i])) { + if (completions.get(expected[i]).title) + InspectorTest.addResult("Found: " + expected[i] + ", displayed as " + completions.get(expected[i]).title); + else + InspectorTest.addResult("Found: " + expected[i]); + } else { + InspectorTest.addResult("Not Found: " + expected[i]); + } + } + InspectorTest.addResult(""); } - } - - TestRunner.addResult(''); } - } + function sequential(tests) + { + var promise = Promise.resolve(); + for (var i = 0; i < tests.length; i++) + promise = promise.then(tests[i]); + return promise; + } - function sequential(tests) { - var promise = Promise.resolve(); + sequential([ + InspectorTest.waitUntilConsoleEditorLoaded().then(e => consoleEditor = e), + () => testCompletions("window.do", ["document"]), + () => testCompletions("win", ["window"]), + () => testCompletions('window["doc', ['"document"]']), + () => testCompletions('window["document"].bo', ["body"]), + () => testCompletions('window["document"]["body"].textC', ["textContent"]), + () => testCompletions('document.body.inner', ["innerText", "innerHTML"]), + () => testCompletions('document["body"][window.do', ["document"]), + () => testCompletions('document["body"][window["document"].body.childNodes[0].text', ["textContent"]), + () => testCompletions("templateString`asdf`should", ["shouldNotFindThis"]), + () => testCompletions("window.document.BODY", ["body"]), + () => testCompletions("window.dOcUmE", ["document"]), + () => testCompletions("window.node", ["NodeList", "AudioNode", "GainNode"]), + () => testCompletions("32", ["Float32Array", "Int32Array"]), + () => testCompletions("window.32", ["Float32Array", "Int32Array"]), + () => testCompletions("", ["window"], false), + () => testCompletions("", ["window"], true), + () => testCompletions('"string g', ["getComputedStyle"], false), + () => testCompletions("`template string docu", ["document"], false), + () => testCompletions("`${do", ["document"], false), + () => testCompletions("// do", ["document"], false), + () => testCompletions('["should', ["shouldNotFindThisFunction"]), + () => testCompletions("shou", ["should not find this"]), + () => testCompletions('myMap.get(', ['"first")', '"second")', '"third")']), + () => testCompletions('myMap.get(\'', ['\'first\')', '\'second\')', '\'third\')']), + () => testCompletions('myMap.set(\'firs', ['\'first\', ']), + () => testCompletions('myMap.set(should', ['shouldFindThisFunction', 'shouldNotFindThis', '\"shouldNotFindThis\")']), + () => testCompletions('myMap.delete(\'', ['\'first\')', '\'second\')', '\'third\')']), + () => testCompletions("document. bo", ["body"]), + () => testCompletions("document.\tbo", ["body"]), + () => testCompletions("document.\nbo", ["body"]), + () => testCompletions("document.\r\nbo", ["body"]), + () => testCompletions("document [ 'bo", ["'body']"]), + () => testCompletions("function hey(should", ["shouldNotFindThisFunction"]), + () => testCompletions("var should", ["shouldNotFindThisFunction"]), + () => testCompletions("document[[win", ["window"]), + () => testCompletions("document[ [win", ["window"]), + () => testCompletions("document[ [ win", ["window"]), + () => testCompletions('I|mag', ['Image', 'Infinity']), + () => testCompletions('var x = (do|);', ['document']), + () => testCompletions('complicatedObject["foo', ['"foo-bar"]']), + () => testCompletions('complicatedObject["foo-', ['"foo-bar"]']), + () => testCompletions('complicatedObject["foo-bar', ['"foo-bar"]']), + () => testCompletions('complicatedObject["\'sing', ['"\'single-qouted\'"]']), + () => testCompletions('complicatedObject[\'\\\'sing', ['\'\\\'single-qouted\\\'\']']), + () => testCompletions('complicatedObject["\'single-qou', ['"\'single-qouted\'"]']), + () => testCompletions('complicatedObject["\\"double-qouted\\"', ['"\\"double-qouted\\""]']), + () => testCompletions('complicatedObject["notDangerous();', ['"notDangerous();"]']), + ]).then(InspectorTest.completeTest); - for (var i = 0; i < tests.length; i++) - promise = promise.then(tests[i]); - - return promise; - } - - sequential([ - () => ConsoleTestRunner.waitUntilConsoleEditorLoaded().then(e => consoleEditor = e), - () => testCompletions('window.do', ['document']), - () => testCompletions('win', ['window']), - () => testCompletions('window["doc', ['"document"]']), - () => testCompletions('window["document"].bo', ['body']), - () => testCompletions('window["document"]["body"].textC', ['textContent']), - () => testCompletions('document.body.inner', ['innerText', 'innerHTML']), - () => testCompletions('document["body"][window.do', ['document']), - () => testCompletions('document["body"][window["document"].body.childNodes[0].text', ['textContent']), - () => testCompletions('templateString`asdf`should', ['shouldNotFindThis']), - () => testCompletions('window.document.BODY', ['body']), - () => testCompletions('window.dOcUmE', ['document']), - () => testCompletions('window.node', ['NodeList', 'AudioNode', 'GainNode']), - () => testCompletions('32', ['Float32Array', 'Int32Array']), - () => testCompletions('window.32', ['Float32Array', 'Int32Array']), - () => testCompletions('', ['window'], false), - () => testCompletions('', ['window'], true), - () => testCompletions('"string g', ['getComputedStyle'], false), - () => testCompletions('`template string docu', ['document'], false), - () => testCompletions('`${do', ['document'], false), - () => testCompletions('// do', ['document'], false), - () => testCompletions('["should', ['shouldNotFindThisFunction']), - () => testCompletions('shou', ['should not find this']), - () => testCompletions('myMap.get(', ['"first")', '"second")', '"third")']), - () => testCompletions('myMap.get(\'', ['\'first\')', '\'second\')', '\'third\')']), - () => testCompletions('myMap.set(\'firs', ['\'first\', ']), - () => testCompletions('myMap.set(should', ['shouldFindThisFunction', 'shouldNotFindThis', '"shouldNotFindThis")']), - () => testCompletions('myMap.delete(\'', ['\'first\')', '\'second\')', '\'third\')']), - () => testCompletions('document. bo', ['body']), - () => testCompletions('document.\tbo', ['body']), - () => testCompletions('document.\nbo', ['body']), - () => testCompletions('document.\r\nbo', ['body']), - () => testCompletions('document [ \'bo', ['\'body\']']), - () => testCompletions('function hey(should', ['shouldNotFindThisFunction']), - () => testCompletions('var should', ['shouldNotFindThisFunction']), - () => testCompletions('document[[win', ['window']), - () => testCompletions('document[ [win', ['window']), - () => testCompletions('document[ [ win', ['window']), - () => testCompletions('I|mag', ['Image', 'Infinity']), - () => testCompletions('var x = (do|);', ['document']), - () => testCompletions('complicatedObject["foo', ['"foo-bar"]']), - () => testCompletions('complicatedObject["foo-', ['"foo-bar"]']), - () => testCompletions('complicatedObject["foo-bar', ['"foo-bar"]']), - () => testCompletions('complicatedObject["\'sing', ['"\'single-qouted\'"]']), - () => testCompletions('complicatedObject[\'\\\'sing', ['\'\\\'single-qouted\\\'\']']), - () => testCompletions('complicatedObject["\'single-qou', ['"\'single-qouted\'"]']), - () => testCompletions('complicatedObject["\\"double-qouted\\"', ['"\\"double-qouted\\""]']), - () => testCompletions('complicatedObject["notDangerous();', ['"notDangerous();"]']) - ]).then(TestRunner.completeTest); -})(); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests that console correctly finds suggestions in complicated cases.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment-expected.txt new file mode 100644 index 0000000..3343832 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment-expected.txt
@@ -0,0 +1 @@ +Tests that unterminated comment in CSS generates a warning.
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment.js new file mode 100644 index 0000000..28d47c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-css-unterminated-comment.js
@@ -0,0 +1,30 @@ +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> + +<style>/* unterminated comment </style> +<style>/*</style> + +<style>/* terminated comment */</style> +<style>/* terminated comment *//*</style> + +<script> + +function test() +{ + InspectorTest.consoleModel.messages().forEach(function(message) + { + InspectorTest.addResult(message.message + " (line " + message.line + ")"); + }); + + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p id="p">Tests that unterminated comment in CSS generates a warning.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated-expected.txt index 0cb9383..159fd40 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated-expected.txt
@@ -1,5 +1,7 @@ +CONSOLE MESSAGE: line 9: [object Window] +CONSOLE MESSAGE: line 10: [object ShadowRoot] Tests that console does not log deprecated warning messages while dir-dumping objects. -console-dir-deprecated.js:17 Window -console-dir-deprecated.js:18 #document-fragment +console-dir-deprecated.html:9 Window +console-dir-deprecated.html:10 #document-fragment
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated.js index c52ed56..d672dc0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-deprecated.js
@@ -1,28 +1,33 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> -(async function() { - TestRunner.addResult(`Tests that console does not log deprecated warning messages while dir-dumping objects.\n`); +function logObjects() +{ + console.dir(window); + console.dir(document.getElementById("foo").createShadowRoot()); +} - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); - - await TestRunner.loadHTML(` - <div id="foo"></div> - `); - await TestRunner.evaluateInPagePromise(` - function logObjects() +function test() +{ + InspectorTest.evaluateInPage("logObjects()", step2); + function step2() { - console.dir(window); - console.dir(document.getElementById("foo").createShadowRoot()); + InspectorTest.dumpConsoleMessages(); + InspectorTest.completeTest(); } - `); +} - TestRunner.evaluateInPage('logObjects()', step2); +</script> +</head> - function step2() { - ConsoleTestRunner.dumpConsoleMessages(); - TestRunner.completeTest(); - } -})(); +<body onload="runTest()"> +<div id="foo"></div> +<p> +Tests that console does not log deprecated warning messages while dir-dumping objects. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global-expected.txt index 4111acf..e221eb1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE MESSAGE: line 9: [object Window] Tests that console dumps global object with properties. {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global.js index 9183a1d..c3ce2fa5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir-global.js
@@ -1,58 +1,53 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> -(async function() { - TestRunner.addResult(`Tests that console dumps global object with properties.\n`); +function doit() +{ + console.dir(window); + runTest(); +} - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); +function test() +{ + InspectorTest.RuntimeAgent.evaluate("window", "console", false).then(evalCallback); - await TestRunner.evaluateInPagePromise(` - function doit() + function evalCallback(result) { - console.dir(window); - }; - `); - - TestRunner.RuntimeAgent.evaluate('window', 'console', false).then(evalCallback); - - function evalCallback(result) { - if (!result) { - testController.notifyDone('Exception'); - return; + if (!result) { + testController.notifyDone("Exception"); + return; + } + if (result.type === "error") + testController.notifyDone("Exception:" + result); + var objectProxy = InspectorTest.runtimeModel.createRemoteObject(result); + objectProxy.getOwnProperties(false, getPropertiesCallback); } - if (result.type === 'error') - testController.notifyDone('Exception:' + result); - - var objectProxy = TestRunner.runtimeModel.createRemoteObject(result); - objectProxy.getOwnProperties(false, getPropertiesCallback); - } - - function getPropertiesCallback(properties) { - properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties); - - var golden = { - 'window': 1, - 'document': 1, - 'eval': 1, - 'console': 1, - 'frames': 1, - 'Array': 1, - 'doit': 1 - }; - - var result = {}; - - for (var i = 0; i < properties.length; ++i) { - var name = properties[i].name; - - if (golden[name]) - result[name] = 1; + function getPropertiesCallback(properties) + { + properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties); + var golden = { "window": 1, "document": 1, "eval": 1, "console": 1, "frames": 1, "Array": 1, "doit": 1 }; + var result = {}; + for (var i = 0; i < properties.length; ++i) { + var name = properties[i].name; + if (golden[name]) + result[name] = 1; + } + InspectorTest.addObject(result); + InspectorTest.completeTest(); } +} - TestRunner.addObject(result); - TestRunner.completeTest(); - } -})(); +</script> +</head> + +<body onload="doit()"> +<p> +Tests that console dumps global object with properties. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir.js index 6ad6c2a0..219ae2f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-dir.js
@@ -1,71 +1,83 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> -(async function() { - TestRunner.addResult(`Tests that console logging dumps proper messages.\n`); +<script> +function onload() +{ + console.dir(["test1", "test2"]); + console.dir(document.childNodes); + console.dir(document.evaluate("//head", document, null, XPathResult.ANY_TYPE, null)); - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); + // Object with properties containing whitespaces + var obj = { $foo5_: 0 }; + obj[" a b "] = " a b "; + obj["c d"] = "c d"; + obj[""] = ""; + obj[" "] = " "; + obj["a\n\nb\nc"] = "a\n\nb\nc"; + obj["negZero"] = -0; + console.dir(obj); - await TestRunner.evaluateInPagePromise(` - function onload() + // This should correctly display information about the function. + console.dir(function() {}); + + // Test function inferred name in prototype constructor. + var outer = { inner: function() {} }; + console.dir(new outer.inner()); + + // Test "No Properties" placeholder. + console.dir({ __proto__: null }); + console.dir({ foo: { __proto__: null }}); + // Test "No Scopes" placeholder. + console.dir(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get); + + // Test big typed array: should be no crash or timeout. + var bigTypedArray = new Uint8Array(new ArrayBuffer(400 * 1000 * 1000)); + bigTypedArray["FAIL"] = "FAIL: Object.getOwnPropertyNames() should not have been run"; + console.dir(bigTypedArray); + + // document.createEvent("Event") has a special property "isTrusted" flagged "Unforgeable". + var event = document.createEvent("Event"); + Object.defineProperty(event, "timeStamp", {value: 0}) + console.dir(event); + + runTest(); +} +//# sourceURL=console-dir.html +</script> + +<script> +function test() +{ + InspectorTest.expandConsoleMessages(step1, expandTreeElementFilter); + + function expandTreeElementFilter(treeElement) { - console.dir(["test1", "test2"]); - console.dir(document.childNodes); - console.dir(document.evaluate("//head", document, null, XPathResult.ANY_TYPE, null)); - - // Object with properties containing whitespaces - var obj = { $foo5_: 0 }; - obj[" a b "] = " a b "; - obj["c d"] = "c d"; - obj[""] = ""; - obj[" "] = " "; - obj["a\n\nb\nc"] = "a\n\nb\nc"; - obj["negZero"] = -0; - console.dir(obj); - - // This should correctly display information about the function. - console.dir(function() {}); - - // Test function inferred name in prototype constructor. - var outer = { inner: function() {} }; - console.dir(new outer.inner()); - - // Test "No Properties" placeholder. - console.dir({ __proto__: null }); - console.dir({ foo: { __proto__: null }}); - // Test "No Scopes" placeholder. - console.dir(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get); - - // Test big typed array: should be no crash or timeout. - var bigTypedArray = new Uint8Array(new ArrayBuffer(400 * 1000 * 1000)); - bigTypedArray["FAIL"] = "FAIL: Object.getOwnPropertyNames() should not have been run"; - console.dir(bigTypedArray); - - // document.createEvent("Event") has a special property "isTrusted" flagged "Unforgeable". - var event = document.createEvent("Event"); - Object.defineProperty(event, "timeStamp", {value: 0}) - console.dir(event); - - runTest(); + var name = treeElement.nameElement && treeElement.nameElement.textContent; + return name === "foo" || treeElement.title === "<function scope>"; } - //# sourceURL=console-dir.js - `); - ConsoleTestRunner.expandConsoleMessages(step1, expandTreeElementFilter); + function step1() + { + InspectorTest.expandConsoleMessages(dumpConsoleMessages, expandTreeElementFilter); + } - function expandTreeElementFilter(treeElement) { - var name = treeElement.nameElement && treeElement.nameElement.textContent; - return name === 'foo' || treeElement.title === '<function scope>'; - } + function dumpConsoleMessages() + { + InspectorTest.dumpConsoleMessagesIgnoreErrorStackFrames(); + InspectorTest.completeTest(); + } +} - function step1() { - ConsoleTestRunner.expandConsoleMessages(dumpConsoleMessages, expandTreeElementFilter); - } +</script> +</head> - function dumpConsoleMessages() { - ConsoleTestRunner.dumpConsoleMessagesIgnoreErrorStackFrames(); - TestRunner.completeTest(); - } -})(); +<body onload="onload()"> +<p> +Tests that console logging dumps proper messages. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value-expected.txt index 06548df6..ffc9ff9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE MESSAGE: line 10: [object Object] Tests that property values can be edited inline in the console via double click. Node was hidden after dblclick: true @@ -5,7 +6,7 @@ Node was hidden after dblclick: true Node was hidden after dblclick: true logToConsole() -console-edit-property-value.js:15 {a: 1, b: "foo", c: null, d: 2} +console-edit-property-value.html:10 {a: 1, b: "foo", c: null, d: 2} a: 3 b: "foo" c: (3) [1, 2, 3]
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value.js index b104647..f4fcc8b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-edit-property-value.js
@@ -1,69 +1,86 @@ -// 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. +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> -(async function() { - TestRunner.addResult(`Tests that property values can be edited inline in the console via double click.\n`); +function logToConsole() +{ + var obj = {a: 1, b: "foo", c: null, d: 2}; + console.log(obj); +} - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('console'); +var test = function() +{ + InspectorTest.evaluateInConsole("logToConsole()", step1); - await TestRunner.evaluateInPagePromise(` - function logToConsole() + function step1() { - var obj = {a: 1, b: "foo", c: null, d: 2}; - console.log(obj); + InspectorTest.expandConsoleMessages(step2); } - `); - ConsoleTestRunner.evaluateInConsole('logToConsole()', step1); + function step2() + { + var valueElements = getValueElements(); + doubleClickTypeAndEnter(valueElements[0], "1 + 2"); + InspectorTest.waitForRemoteObjectsConsoleMessages(step3); + } - function step1() { - ConsoleTestRunner.expandConsoleMessages(step2); - } + function step3() + { + var valueElements = getValueElements(); + doubleClickTypeAndEnter(valueElements[1], "nonExistingValue"); + InspectorTest.waitForRemoteObjectsConsoleMessages(step4); + } - function step2() { - var valueElements = getValueElements(); - doubleClickTypeAndEnter(valueElements[0], '1 + 2'); - ConsoleTestRunner.waitForRemoteObjectsConsoleMessages(step3); - } + function step4() + { + var valueElements = getValueElements(); + doubleClickTypeAndEnter(valueElements[2], "[1, 2, 3]"); + InspectorTest.waitForRemoteObjectsConsoleMessages(step5); + } - function step3() { - var valueElements = getValueElements(); - doubleClickTypeAndEnter(valueElements[1], 'nonExistingValue'); - ConsoleTestRunner.waitForRemoteObjectsConsoleMessages(step4); - } + function step5() + { + var valueElements = getValueElements(); + doubleClickTypeAndEnter(valueElements[3], "{x: 2}"); + InspectorTest.waitForRemoteObjectsConsoleMessages(step6); + } - function step4() { - var valueElements = getValueElements(); - doubleClickTypeAndEnter(valueElements[2], '[1, 2, 3]'); - ConsoleTestRunner.waitForRemoteObjectsConsoleMessages(step5); - } + function step6() + { + InspectorTest.dumpConsoleMessagesIgnoreErrorStackFrames(); + InspectorTest.completeTest(); + } - function step5() { - var valueElements = getValueElements(); - doubleClickTypeAndEnter(valueElements[3], '{x: 2}'); - ConsoleTestRunner.waitForRemoteObjectsConsoleMessages(step6); - } + function getValueElements() + { + var messageElement = Console.ConsoleView.instance()._visibleViewMessages[1].element(); + return messageElement.querySelector(".console-message-text *").shadowRoot.querySelectorAll(".value"); + } - function step6() { - ConsoleTestRunner.dumpConsoleMessagesIgnoreErrorStackFrames(); - TestRunner.completeTest(); - } + function doubleClickTypeAndEnter(node, text) + { + var event = document.createEvent("MouseEvent"); + event.initMouseEvent("dblclick", true, true, null, 2); + node.dispatchEvent(event); - function getValueElements() { - var messageElement = Console.ConsoleView.instance()._visibleViewMessages[1].element(); - return messageElement.querySelector('.console-message-text *').shadowRoot.querySelectorAll('.value'); - } + InspectorTest.addResult("Node was hidden after dblclick: " + node.classList.contains("hidden")); - function doubleClickTypeAndEnter(node, text) { - var event = document.createEvent('MouseEvent'); - event.initMouseEvent('dblclick', true, true, null, 2); - node.dispatchEvent(event); - TestRunner.addResult('Node was hidden after dblclick: ' + node.classList.contains('hidden')); - var messageElement = Console.ConsoleView.instance()._visibleViewMessages[1].element(); - var editPrompt = messageElement.querySelector('.console-message-text *').shadowRoot.querySelector('.text-prompt'); - editPrompt.textContent = text; - editPrompt.dispatchEvent(TestRunner.createKeyEvent('Enter')); - } -})(); + var messageElement = Console.ConsoleView.instance()._visibleViewMessages[1].element(); + var editPrompt = messageElement.querySelector(".console-message-text *").shadowRoot.querySelector(".text-prompt"); + editPrompt.textContent = text; + editPrompt.dispatchEvent(InspectorTest.createKeyEvent("Enter")); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that property values can be edited inline in the console via double click. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index c7aeee5..c71e1f2 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -581,9 +581,11 @@ "properties/CSSShorthandPropertyAPIFontVariant.cpp", "properties/CSSShorthandPropertyAPIGridArea.cpp", "properties/CSSShorthandPropertyAPIGridColumn.cpp", + "properties/CSSShorthandPropertyAPIGridGap.cpp", "properties/CSSShorthandPropertyAPIGridRow.cpp", "properties/CSSShorthandPropertyAPIListStyle.cpp", "properties/CSSShorthandPropertyAPIMargin.cpp", + "properties/CSSShorthandPropertyAPIMarker.cpp", "properties/CSSShorthandPropertyAPIOffset.cpp", "properties/CSSShorthandPropertyAPIOutline.cpp", "properties/CSSShorthandPropertyAPIOverflow.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index f8578fea..80d7367 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -3900,6 +3900,7 @@ name: "grid-gap", longhands: ["grid-row-gap", "grid-column-gap"], api_class: true, + api_methods: ["parseShorthand"], runtime_flag: "CSSGridLayout", }, { @@ -3931,6 +3932,7 @@ name: "marker", longhands: ["marker-start", "marker-mid", "marker-end"], api_class: true, + api_methods: ["parseShorthand"], }, { name: "offset",
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 86433e1..3f8479c 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -813,7 +813,8 @@ parsed_value = ConsumeFontDisplay(range_); break; case CSSPropertyFontStretch: - parsed_value = CSSPropertyFontUtils::ConsumeFontStretch(range_); + parsed_value = CSSPropertyFontUtils::ConsumeFontStretch( + range_, kCSSFontFaceRuleMode); break; case CSSPropertyFontStyle: parsed_value = CSSPropertyFontUtils::ConsumeFontStyle(range_); @@ -1378,18 +1379,6 @@ } switch (property) { - case CSSPropertyMarker: { - const CSSValue* marker = ParseSingleValue(CSSPropertyMarkerStart); - if (!marker || !range_.AtEnd()) - return false; - AddParsedProperty(CSSPropertyMarkerStart, CSSPropertyMarker, *marker, - important); - AddParsedProperty(CSSPropertyMarkerMid, CSSPropertyMarker, *marker, - important); - AddParsedProperty(CSSPropertyMarkerEnd, CSSPropertyMarker, *marker, - important); - return true; - } case CSSPropertyBorder: return ConsumeBorder(important); case CSSPropertyBackgroundRepeat: @@ -1414,23 +1403,6 @@ return ConsumeBackgroundShorthand(backgroundShorthand(), important); case CSSPropertyWebkitMask: return ConsumeBackgroundShorthand(webkitMaskShorthand(), important); - case CSSPropertyGridGap: { - DCHECK(RuntimeEnabledFeatures::CSSGridLayoutEnabled()); - DCHECK_EQ(shorthandForProperty(CSSPropertyGridGap).length(), 2u); - CSSValue* row_gap = ConsumeLengthOrPercent(range_, context_->Mode(), - kValueRangeNonNegative); - CSSValue* column_gap = ConsumeLengthOrPercent(range_, context_->Mode(), - kValueRangeNonNegative); - if (!row_gap || !range_.AtEnd()) - return false; - if (!column_gap) - column_gap = row_gap; - AddParsedProperty(CSSPropertyGridRowGap, CSSPropertyGridGap, *row_gap, - important); - AddParsedProperty(CSSPropertyGridColumnGap, CSSPropertyGridGap, - *column_gap, important); - return true; - } case CSSPropertyGridTemplate: return ConsumeGridTemplateShorthand(CSSPropertyGridTemplate, important); case CSSPropertyGrid:
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontStretch.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontStretch.cpp index 8b4dc7be..49734d64 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontStretch.cpp +++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontStretch.cpp
@@ -4,15 +4,16 @@ #include "core/css/properties/CSSPropertyAPIFontStretch.h" +#include "core/css/parser/CSSParserContext.h" #include "core/css/properties/CSSPropertyFontUtils.h" namespace blink { const CSSValue* CSSPropertyAPIFontStretch::parseSingleValue( CSSParserTokenRange& range, - const CSSParserContext&, + const CSSParserContext& context, const CSSParserLocalContext&) { - return CSSPropertyFontUtils::ConsumeFontStretch(range); + return CSSPropertyFontUtils::ConsumeFontStretch(range, context.Mode()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp index 1f5d23c..7a6b862 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp +++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
@@ -126,15 +126,28 @@ return value_list; } -CSSValue* CSSPropertyFontUtils::ConsumeFontStretch(CSSParserTokenRange& range) { +CSSValue* CSSPropertyFontUtils::ConsumeFontStretch( + CSSParserTokenRange& range, + const CSSParserMode& parser_mode) { CSSIdentifierValue* parsed_keyword = ConsumeFontStretchKeywordOnly(range); if (parsed_keyword) return parsed_keyword; - CSSPrimitiveValue* percent = + + CSSPrimitiveValue* start_percent = CSSPropertyParserHelpers::ConsumePercent(range, kValueRangeNonNegative); - if (!percent || percent->GetFloatValue() <= 0) + if (!start_percent || start_percent->GetFloatValue() <= 0) return nullptr; - return percent; + + // In a non-font-face context, more than one percentage is not allowed. + if (parser_mode != kCSSFontFaceRuleMode || range.AtEnd()) + return start_percent; + + CSSPrimitiveValue* end_percent = + CSSPropertyParserHelpers::ConsumePercent(range, kValueRangeNonNegative); + if (!end_percent || end_percent->GetFloatValue() <= 0) + return nullptr; + + return CombineToRangeListOrNull(start_percent, end_percent); } CSSValue* CSSPropertyFontUtils::ConsumeFontWeight( @@ -149,8 +162,7 @@ (token.NumericValue() < 1 || token.NumericValue() > 1000)) return nullptr; - CSSPrimitiveValue* start_weight = nullptr; - start_weight = + CSSPrimitiveValue* start_weight = CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeNonNegative); if (!start_weight || start_weight->GetFloatValue() < 1 || start_weight->GetFloatValue() > 1000) @@ -159,22 +171,16 @@ // In a non-font-face context, more than one number is not allowed. Return // what we have. If there is trailing garbage, the AtEnd() check in // CSSPropertyParser::ParseValueStart will catch that. - if (parser_mode != kCSSFontFaceRuleMode) + if (parser_mode != kCSSFontFaceRuleMode || range.AtEnd()) return start_weight; - CSSPrimitiveValue* end_weight = nullptr; - if (!range.AtEnd()) { - end_weight = - CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeNonNegative); - if (!end_weight || end_weight->GetFloatValue() < 1 || - end_weight->GetFloatValue() > 1000) - return nullptr; - } + CSSPrimitiveValue* end_weight = + CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeNonNegative); + if (!end_weight || end_weight->GetFloatValue() < 1 || + end_weight->GetFloatValue() > 1000) + return nullptr; - if (end_weight) - return CombineToRangeListOrNull(start_weight, end_weight); - - return start_weight; + return CombineToRangeListOrNull(start_weight, end_weight); } // TODO(bugsnash): move this to the FontFeatureSettings API when it is no longer
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h index 44f98e5..9eb2accb 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h +++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
@@ -35,7 +35,8 @@ static CSSIdentifierValue* ConsumeFontStretchKeywordOnly( CSSParserTokenRange&); - static CSSValue* ConsumeFontStretch(CSSParserTokenRange&); + static CSSValue* ConsumeFontStretch(CSSParserTokenRange&, + const CSSParserMode&); static CSSValue* ConsumeFontStyle(CSSParserTokenRange&); static CSSValue* ConsumeFontWeight(CSSParserTokenRange&, const CSSParserMode&);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIGridGap.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIGridGap.cpp new file mode 100644 index 0000000..3cddfba9 --- /dev/null +++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIGridGap.cpp
@@ -0,0 +1,39 @@ +// 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 "core/css/properties/CSSShorthandPropertyAPIGridGap.h" + +#include "core/StylePropertyShorthand.h" +#include "core/css/parser/CSSParserContext.h" +#include "core/css/parser/CSSPropertyParserHelpers.h" +#include "platform/RuntimeEnabledFeatures.h" + +namespace blink { + +bool CSSShorthandPropertyAPIGridGap::parseShorthand( + bool important, + CSSParserTokenRange& range, + const CSSParserContext& context, + bool use_legacy_parsing, + HeapVector<CSSProperty, 256>& properties) { + DCHECK(RuntimeEnabledFeatures::CSSGridLayoutEnabled()); + DCHECK_EQ(shorthandForProperty(CSSPropertyGridGap).length(), 2u); + CSSValue* row_gap = CSSPropertyParserHelpers::ConsumeLengthOrPercent( + range, context.Mode(), kValueRangeNonNegative); + CSSValue* column_gap = CSSPropertyParserHelpers::ConsumeLengthOrPercent( + range, context.Mode(), kValueRangeNonNegative); + if (!row_gap || !range.AtEnd()) + return false; + if (!column_gap) + column_gap = row_gap; + CSSPropertyParserHelpers::AddProperty( + CSSPropertyGridRowGap, CSSPropertyGridGap, *row_gap, important, + CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties); + CSSPropertyParserHelpers::AddProperty( + CSSPropertyGridColumnGap, CSSPropertyGridGap, *column_gap, important, + CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties); + return true; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIMarker.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIMarker.cpp new file mode 100644 index 0000000..ff22dc04 --- /dev/null +++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIMarker.cpp
@@ -0,0 +1,38 @@ +// 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 "core/css/properties/CSSShorthandPropertyAPIMarker.h" + +#include "core/css/parser/CSSPropertyParserHelpers.h" + +namespace blink { + +bool CSSShorthandPropertyAPIMarker::parseShorthand( + bool important, + CSSParserTokenRange& range, + const CSSParserContext& context, + bool use_legacy_parsing, + HeapVector<CSSProperty, 256>& properties) { + bool needs_legacy_parsing = false; + const CSSValue* marker = CSSPropertyParserHelpers::ParseLonghandViaAPI( + CSSPropertyMarkerStart, CSSPropertyMarker, context, range, + needs_legacy_parsing); + if (!marker || !range.AtEnd()) + return false; + + DCHECK(!needs_legacy_parsing); + + CSSPropertyParserHelpers::AddProperty( + CSSPropertyMarkerStart, CSSPropertyMarker, *marker, important, + CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties); + CSSPropertyParserHelpers::AddProperty( + CSSPropertyMarkerMid, CSSPropertyMarker, *marker, important, + CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties); + CSSPropertyParserHelpers::AddProperty( + CSSPropertyMarkerEnd, CSSPropertyMarker, *marker, important, + CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties); + return true; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js index d00e6e6..cef7ac9 100644 --- a/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js
@@ -217,7 +217,7 @@ }; /** - * @param {function(!Element):string|undefined} messageFormatter + * @param {function(!Element):string} messageFormatter * @param {!Element} node * @return {string} */ @@ -261,7 +261,7 @@ printOriginatingCommand, dumpClassNames, messageFormatter) { TestRunner.addResults(ConsoleTestRunner.dumpConsoleMessagesIntoArray( printOriginatingCommand, dumpClassNames, - ConsoleTestRunner.formatterIgnoreStackFrameUrls.bind(this, messageFormatter))); + messageFormatter ? ConsoleTestRunner.formatterIgnoreStackFrameUrls.bind(this, messageFormatter) : undefined)); }; ConsoleTestRunner.dumpConsoleMessagesWithStyles = function() { @@ -410,11 +410,11 @@ ConsoleTestRunner.waitUntilConsoleEditorLoaded = function() { var fulfill; var promise = new Promise(x => (fulfill = x)); - var prompt = Console.ConsoleView.instance()._prompt; - if (prompt._editor) - fulfill(prompt._editor); + var editor = Console.ConsoleView.instance()._prompt._editor; + if (editor) + fulfill(editor); else - TestRunner.addSniffer(Console.ConsolePrompt.prototype, '_editorSetForTest', _ => fulfill(prompt._editor)); + TestRunner.addSniffer(Console.ConsolePrompt.prototype, '_editorSetForTest', _ => fulfill(editor)); return promise; };
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js index f9face9..4c52bd49 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js
@@ -56,13 +56,9 @@ helperScripts.push(filename); }); - const testsPath = path.resolve(__dirname, 'tests.txt'); - const newToOldTests = new Map(fs.readFileSync(testsPath, 'utf-8').split('\n').map(line => line.split(' ').reverse())); - const originalTestPath = path.resolve( - __dirname, '..', '..', '..', '..', 'LayoutTests', newToOldTests.get(inputPath.slice(inputPath.indexOf('http/')))); - - const srcResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(originalTestPath), s)); - const destResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(inputPath), s)); + const outPath = migrateUtils.getOutPath(inputPath); + const srcResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(inputPath), s)); + const destResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(outPath), s)); const relativeResourcePaths = destResourcePaths.map(p => p.slice(p.indexOf('/http/tests') + '/http/tests'.length)); let outputCode; @@ -90,9 +86,16 @@ console.log(outputCode); if (!DRY_RUN) { - fs.writeFileSync(inputPath, outputCode); + mkdirp.sync(path.dirname(outPath)); + + fs.writeFileSync(outPath, outputCode); + const expectationsPath = inputPath.replace('.html', '-expected.txt'); + copyExpectations(expectationsPath, outPath); copyResourceScripts(srcResourcePaths, destResourcePaths); - console.log('Migrated: ', inputPath); + + fs.unlinkSync(inputPath); + fs.unlinkSync(expectationsPath); + console.log('Migrated to: ', outPath); } } @@ -176,11 +179,12 @@ * Create test header based on extracted data */ const headerLines = []; - headerLines.push(createExpressionNode(`TestRunner.addResult(\`${bodyText}\\n\`);`)); + headerLines.push(createExpressionNode(`TestRunner.addResult('${bodyText}\\n');`)); headerLines.push(createNewLineNode()); for (const helper of allTestHelpers) { headerLines.push(createAwaitExpressionNode(`await TestRunner.loadModule('${helper}');`)); } + headerLines.push(createAwaitExpressionNode(`await TestRunner.loadPanel('${panel}');`)); headerLines.push(createAwaitExpressionNode(`await TestRunner.showPanel('${panel}');`)); if (domFixture) {
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/tests.txt b/third_party/WebKit/Source/devtools/scripts/migrate_test/tests.txt index a45b311d..a7acb6b 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/tests.txt +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/tests.txt
@@ -1,8 +1,18 @@ inspector/console/alert-toString-exception.html inspector/console/console-api-on-call-frame.html +inspector/console/console-bind-fake.html http/tests/devtools/console/console-bind-fake.js +inspector/console/console-call-getter-on-proto.html http/tests/devtools/console/console-call-getter-on-proto.js inspector/console/console-clear-function.html +inspector/console/console-command-clear.html http/tests/devtools/console/console-command-clear.js inspector/console/console-command-copy.html inspector/console/console-context-selector.html +inspector/console/console-control-characters.html http/tests/devtools/console/console-control-characters.js inspector/console/console-copy-treeoutline.html inspector/console/console-copy-truncated-text.html +inspector/console/console-correct-suggestions.html http/tests/devtools/console/console-correct-suggestions.js +inspector/console/console-css-unterminated-comment.html http/tests/devtools/console/console-css-unterminated-comment.js +inspector/console/console-dir-deprecated.html http/tests/devtools/console/console-dir-deprecated.js +inspector/console/console-dir-global.html http/tests/devtools/console/console-dir-global.js +inspector/console/console-dir.html http/tests/devtools/console/console-dir.js +inspector/console/console-edit-property-value.html http/tests/devtools/console/console-edit-property-value.js inspector/console/console-error-on-call-frame.html \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js deleted file mode 100644 index 2cf305b..0000000 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js +++ /dev/null
@@ -1,89 +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. - -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -const childProcess = require('child_process'); - -const utils = require('../utils'); - -const MIGRATE_SCRIPT_PATH = path.resolve(__dirname, 'migrate_test.js'); -const TESTS_PATH = path.resolve(__dirname, 'tests.txt'); -const TEST_EXPECTATIONS_PATH = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'TestExpectations'); -const FLAG_EXPECTATIONS_PATH = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'FlagExpectations'); - -function main() { - const tests = fs.readFileSync(TESTS_PATH, 'utf-8').split('\n').map(line => line.split(' ')); - const oldToNewTests = new Map(tests); - const testCount = oldToNewTests.size; - const migratedTests = new Set(); - - for (const [_, testPath] of tests) { - if (!testPath) - continue; - const fullTestPath = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', testPath); - try { - childProcess.execSync(`node ${MIGRATE_SCRIPT_PATH} ${fullTestPath}`) - } catch (err) { - console.log(err.stdout.toString()); - continue; - } - - for (const [oldTest, newTest] of oldToNewTests) { - if (testPath === newTest) - oldToNewTests.delete(oldTest); - } - migratedTests.add(testPath); - } - - console.log(`Successfully migrated: ${migratedTests.size} of ${testCount}`); - - const updatedTests = Array.from(oldToNewTests.entries()).map(line => line.join(' ')).join('\n'); - console.log(updatedTests); - - // Update TestExpectations - const testExpectations = fs.readFileSync(TEST_EXPECTATIONS_PATH, 'utf-8'); - const updatedTestExpecationLines = []; - let seenStartSentinel = false; - let seenEndSentinel = false; - for (const line of testExpectations.split('\n')) { - if (line === '# ====== DevTools test migration failures from here ======') { - seenStartSentinel = true; - updatedTestExpecationLines.push(line); - continue; - } - if (line === '# ====== DevTools test migration failures until here ======') { - seenEndSentinel = true; - updatedTestExpecationLines.push(line); - continue; - } - if (seenEndSentinel) { - updatedTestExpecationLines.push(line); - continue; - } - if (!seenStartSentinel) { - updatedTestExpecationLines.push(line); - continue; - } - let skipLine = false; - for (const test of migratedTests) { - if (line.indexOf(test) !== -1) { - skipLine = true; - break; - } - } - if (!skipLine) - updatedTestExpecationLines.push(line); - } - - fs.writeFileSync(TEST_EXPECTATIONS_PATH, updatedTestExpecationLines.join('\n')); - - // Update tests.txt - fs.writeFileSync(TESTS_PATH, updatedTests); -} - -main();
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaClientImpl.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaClientImpl.cpp index 7d451af6..731d7bd 100644 --- a/third_party/WebKit/Source/modules/mediastream/UserMediaClientImpl.cpp +++ b/third_party/WebKit/Source/modules/mediastream/UserMediaClientImpl.cpp
@@ -45,6 +45,8 @@ void UserMediaClientImpl::RequestUserMedia(UserMediaRequest* request) { if (client_) client_->RequestUserMedia(request); + else + request->FailUASpecific("NotSupportedError", String(), String()); } void UserMediaClientImpl::CancelUserMediaRequest(UserMediaRequest* request) {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py index 0372145..a01d46ba 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
@@ -66,6 +66,10 @@ assert not self.filesystem.isabs(start_directory) directory = self.finder.path_from_chromium_base(start_directory) external_root = self.finder.path_from_layout_tests('external') + # Changes to LayoutTests/TestExpectations itself should be skipped and + # not raise an assertion. + if directory == self.finder.layout_tests_dir(): + return None, None assert directory.startswith(external_root) while directory != external_root: owners_file = self.filesystem.join(directory, 'OWNERS')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py index 10f9214..91911a51 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
@@ -83,6 +83,8 @@ def test_find_and_extract_owners_out_of_tree(self): with self.assertRaises(AssertionError): self.extractor.find_and_extract_owners('third_party/WebKit/LayoutTests/other') + self.assertEqual(self.extractor.find_and_extract_owners('third_party/WebKit/LayoutTests'), + (None, None)) def test_extract_owners(self): self.filesystem.files = {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3a1426f..5f698a1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -63231,6 +63231,18 @@ </summary> </histogram> +<histogram name="RendererScheduler.ExpectedQueueingTimeWhenQueueingTime" + units="ms"> + <owner>tdresser@chromium.org</owner> + <summary> + Expected queueing time for events which were queued on the main thread + longer or shorter than a threshold, given by the QueueingTimeThreshold + suffix. + + Team: input-dev@chromium.org. + </summary> +</histogram> + <histogram name="RendererScheduler.ExpectedTaskQueueingDuration" units="ms"> <owner>tdresser@chromium.org</owner> <summary> @@ -63326,6 +63338,10 @@ <histogram name="RendererScheduler.QueueingDurationWhenExpectedQueueingTime" units="ms"> + <obsolete> + Deprecated as of 08/2017. Replaced with + RendererScheduler.ExpectedQueueingTimeWhenQueueingTime. + </obsolete> <owner>tdresser@chromium.org</owner> <summary> Time between sending an event to the renderer main thread and when the @@ -92400,6 +92416,9 @@ </histogram_suffixes> <histogram_suffixes name="ExpectedQueueingDurationThreshold" separator="_"> + <obsolete> + Deprecated as of 08/2017. Replaced with ExpectedQueueingDurationThreshold. + </obsolete> <suffix name="GreaterThan.10ms" label="Expected Queueing Time greater than 10ms."/> <suffix name="GreaterThan.150ms" @@ -97827,6 +97846,19 @@ <affected-histogram name="ShortcutsProvider.QueryIndexTime"/> </histogram_suffixes> +<histogram_suffixes name="QueueingTimeThreshold" separator="_"> + <suffix name="GreaterThan.10ms" label="Queueing Time greater than 10ms."/> + <suffix name="GreaterThan.150ms" label="Queueing Time greater than 150ms."/> + <suffix name="GreaterThan.300ms" label="Queueing Time greater than 300ms."/> + <suffix name="GreaterThan.450ms" label="Queueing Time greater than 450ms."/> + <suffix name="LessThan.10ms" label="Queueing Time less than 10ms."/> + <suffix name="LessThan.150ms" label="Queueing Time less than 150ms."/> + <suffix name="LessThan.300ms" label="Queueing Time less than 300ms."/> + <suffix name="LessThan.450ms" label="Queueing Time less than 450ms."/> + <affected-histogram + name="RendererScheduler.ExpectedQueueingTimeWhenQueueingTime"/> +</histogram_suffixes> + <histogram_suffixes name="QuicConnectionType" separator=""> <owner>rch@chromium.org</owner> <suffix name="ForHTTP" label="Only insecure HTTP connections are counted.">
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index dded329..96cfede 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -28,7 +28,6 @@ deps = [ "//base", "//ui/base", - "//ui/strings", "//url", ] @@ -48,6 +47,7 @@ "//ui/gfx/geometry", "//ui/native_theme", "//ui/resources", + "//ui/strings", ] configs += [
diff --git a/ui/message_center/fake_message_center.cc b/ui/message_center/fake_message_center.cc index b1e67185..1900b0e6 100644 --- a/ui/message_center/fake_message_center.cc +++ b/ui/message_center/fake_message_center.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "ui/message_center/fake_message_center.h" -#include "base/strings/string_util.h" #include "ui/message_center/notification_list.h" namespace message_center { @@ -143,13 +142,6 @@ void FakeMessageCenter::PausePopupTimers() {} -const base::string16& FakeMessageCenter::GetProductOSName() const { - return base::EmptyString16(); -} - -void FakeMessageCenter::SetProductOSName( - const base::string16& product_os_name) {} - void FakeMessageCenter::DisableTimersForTest() {} void FakeMessageCenter::EnableChangeQueueForTest(bool enabled) {}
diff --git a/ui/message_center/fake_message_center.h b/ui/message_center/fake_message_center.h index c489f67..7a8766a 100644 --- a/ui/message_center/fake_message_center.h +++ b/ui/message_center/fake_message_center.h
@@ -68,8 +68,6 @@ bool IsMessageCenterVisible() const override; void RestartPopupTimers() override; void PausePopupTimers() override; - const base::string16& GetProductOSName() const override; - void SetProductOSName(const base::string16& product_os_name) override; protected: void DisableTimersForTest() override;
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h index 2eebf0ff..55697cb 100644 --- a/ui/message_center/message_center.h +++ b/ui/message_center/message_center.h
@@ -193,11 +193,6 @@ // example, after the mouse leaves the popup.) virtual void RestartPopupTimers() = 0; - // "Chromium OS" or "Chrome OS" in the current locale. - // Return empty string if not on these platforms. - virtual const base::string16& GetProductOSName() const = 0; - virtual void SetProductOSName(const base::string16& product_os_name) = 0; - protected: friend class ::DownloadNotification; friend class ::DownloadNotificationTestBase;
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index e2369ca..c4396746 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -15,7 +15,6 @@ #include "base/memory/ptr_util.h" #include "base/observer_list.h" #include "base/stl_util.h" -#include "base/strings/string_util.h" #include "build/build_config.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/message_center_switches.h" @@ -944,15 +943,6 @@ popup_timers_controller_->PauseAll(); } -const base::string16& MessageCenterImpl::GetProductOSName() const { - return product_os_name_; -} - -void MessageCenterImpl::SetProductOSName( - const base::string16& product_os_name) { - product_os_name_ = product_os_name; -} - void MessageCenterImpl::DisableTimersForTest() { popup_timers_controller_.reset(); }
diff --git a/ui/message_center/message_center_impl.h b/ui/message_center/message_center_impl.h index ea4348a3..3dd9c7f 100644 --- a/ui/message_center/message_center_impl.h +++ b/ui/message_center/message_center_impl.h
@@ -84,8 +84,6 @@ void EnterQuietModeWithExpire(const base::TimeDelta& expires_in) override; void RestartPopupTimers() override; void PausePopupTimers() override; - const base::string16& GetProductOSName() const override; - void SetProductOSName(const base::string16& product_os_name) override; void ForceNotificationFlush(const std::string& id) override; // NotificationBlocker::Observer overrides: @@ -139,8 +137,6 @@ // center is visible. std::unique_ptr<internal::ChangeQueue> notification_queue_; - base::string16 product_os_name_; - DISALLOW_COPY_AND_ASSIGN(MessageCenterImpl); };
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h index 15102b9..be5acf24 100644 --- a/ui/message_center/message_center_style.h +++ b/ui/message_center/message_center_style.h
@@ -9,7 +9,6 @@ #include "build/build_config.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/size.h" #include "ui/message_center/message_center_export.h" @@ -101,15 +100,6 @@ const SkColor kControlButtonBackgroundColor = SkColorSetA(SK_ColorWHITE, 0.9 * 0xff); -// Accent colors of system notifications. -const SkColor kSystemNotificationColorNormal = SkColorSetRGB(0x33, 0x67, 0xd6); -const SkColor kSystemNotificationColorWarning = SkColorSetRGB(0xea, 0x61, 0x0); -const SkColor kSystemNotificationColorCriticalWarning = - SkColorSetRGB(0xc5, 0x39, 0x29); - -// Default accent color of notifications that are not generated by system. -const SkColor kNotificationDefaultAccentColor = gfx::kChromeIconGrey; - // Limits. // Given the size of an image, returns the size of the properly scaled-up image
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc index 1d5a222..c7a7389 100644 --- a/ui/message_center/notification.cc +++ b/ui/message_center/notification.cc
@@ -5,15 +5,8 @@ #include "ui/message_center/notification.h" #include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/gfx/vector_icon_types.h" -#include "ui/message_center/message_center.h" -#include "ui/message_center/message_center_style.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" -#include "ui/strings/grit/ui_strings.h" namespace message_center { @@ -61,9 +54,7 @@ vibration_pattern(other.vibration_pattern), renotify(other.renotify), silent(other.silent), - accessible_name(other.accessible_name), - accent_color(other.accent_color) { -} + accessible_name(other.accessible_name) {} RichNotificationData::~RichNotificationData() = default; @@ -179,58 +170,14 @@ const gfx::Image& icon, const std::string& system_component_id, const base::Closure& click_callback) { - std::unique_ptr<Notification> notification = CreateSystemNotification( + std::unique_ptr<Notification> notification(new Notification( NOTIFICATION_TYPE_SIMPLE, notification_id, title, message, icon, base::string16() /* display_source */, GURL(), NotifierId(NotifierId::SYSTEM_COMPONENT, system_component_id), RichNotificationData(), - new HandleNotificationClickedDelegate(click_callback), gfx::kNoneIcon, - SystemNotificationWarningLevel::CRITICAL_WARNING); + new HandleNotificationClickedDelegate(click_callback))); notification->SetSystemPriority(); return notification; } -// static -std::unique_ptr<Notification> Notification::CreateSystemNotification( - NotificationType type, - const std::string& id, - const base::string16& title, - const base::string16& message, - const gfx::Image& icon, - const base::string16& display_source, - const GURL& origin_url, - const NotifierId& notifier_id, - const RichNotificationData& optional_fields, - scoped_refptr<NotificationDelegate> delegate, - const gfx::VectorIcon& small_image, - SystemNotificationWarningLevel color_type) { - SkColor color = message_center::kSystemNotificationColorNormal; - switch (color_type) { - case SystemNotificationWarningLevel::NORMAL: - color = message_center::kSystemNotificationColorNormal; - break; - case SystemNotificationWarningLevel::WARNING: - color = message_center::kSystemNotificationColorWarning; - break; - case SystemNotificationWarningLevel::CRITICAL_WARNING: - color = message_center::kSystemNotificationColorCriticalWarning; - break; - } - base::string16 display_source_or_default = display_source; - if (display_source_or_default.empty()) { - display_source_or_default = l10n_util::GetStringFUTF16( - IDS_MESSAGE_CENTER_NOTIFICATION_CHROMEOS_SYSTEM, - MessageCenter::Get()->GetProductOSName()); - } - std::unique_ptr<Notification> notification = base::MakeUnique<Notification>( - type, id, title, message, icon, display_source_or_default, origin_url, - notifier_id, optional_fields, delegate); - notification->set_accent_color(color); - notification->set_small_image( - small_image.is_empty() - ? gfx::Image() - : gfx::Image(gfx::CreateVectorIcon(small_image, color))); - return notification; -} - } // namespace message_center
diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h index 8101cad..d08a48a8 100644 --- a/ui/message_center/notification.h +++ b/ui/message_center/notification.h
@@ -15,19 +15,13 @@ #include "base/time/time.h" #include "base/values.h" #include "mojo/public/cpp/bindings/struct_traits.h" // nogncheck -#include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" -#include "ui/gfx/skia_util.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" #include "ui/message_center/notifier_settings.h" #include "url/gurl.h" -namespace gfx { -struct VectorIcon; -} // namespace gfx - namespace message_center { namespace mojom { @@ -51,8 +45,6 @@ TEXT }; -enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING }; - // Represents a button to be shown as part of a notification. struct MESSAGE_CENTER_EXPORT ButtonInfo { explicit ButtonInfo(const base::string16& title); @@ -149,12 +141,6 @@ // An accessible description of the notification's contents. base::string16 accessible_name; - - // Unified theme color used in new style notification. - // Usually, it should not be set directly. - // For system notification, CreateSystemNotification with - // SystemNotificationWarningLevel should be used. - SkColor accent_color = SK_ColorTRANSPARENT; }; class MESSAGE_CENTER_EXPORT Notification { @@ -359,11 +345,6 @@ return optional_fields_.accessible_name; } - SkColor accent_color() const { return optional_fields_.accent_color; } - void set_accent_color(SkColor accent_color) { - optional_fields_.accent_color = accent_color; - } - NotificationDelegate* delegate() const { return delegate_.get(); } const RichNotificationData& rich_notification_data() const { @@ -383,13 +364,6 @@ // Helper method to create a simple system notification. |click_callback| // will be invoked when the notification is clicked. - // - // It should only be used for critical notification, as SetSystemPriority and - // CRITICAL_WARNING color are set inside, which means the notification would - // not go away without user interaction. - // - // TODO(tetsui): Add a function parameter |small_image| of gfx::VectorIcon, so - // display source of critical system notification is illustrated by icon. static std::unique_ptr<Notification> CreateSystemNotification( const std::string& notification_id, const base::string16& title, @@ -398,25 +372,6 @@ const std::string& system_component_id, const base::Closure& click_callback); - // Factory method to create all kinds of notifications generated by system, - // from normal priority ones to critical priority ones. - // |small_image| is a small icon show on the upper left header to illustrate - // |display_source| of the notification. - // One specified in the |optional_fields| is overridden. - static std::unique_ptr<Notification> CreateSystemNotification( - NotificationType type, - const std::string& id, - const base::string16& title, - const base::string16& message, - const gfx::Image& icon, - const base::string16& display_source, - const GURL& origin_url, - const NotifierId& notifier_id, - const RichNotificationData& optional_fields, - scoped_refptr<NotificationDelegate> delegate, - const gfx::VectorIcon& small_image, - SystemNotificationWarningLevel color_type); - protected: // The type of notification we'd like displayed. NotificationType type_;
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc index 5a26331..a43e6eaa 100644 --- a/ui/message_center/views/notification_header_view.cc +++ b/ui/message_center/views/notification_header_view.cc
@@ -68,6 +68,8 @@ }; ExpandButton::ExpandButton() { + SetImage(gfx::CreateVectorIcon(kNotificationExpandMoreIcon, kExpandIconSize, + gfx::kChromeIconGrey)); focus_painter_ = views::Painter::CreateSolidFocusPainter( kFocusBorderColor, gfx::Insets(1, 2, 2, 2)); SetFocusBehavior(FocusBehavior::ALWAYS); @@ -157,7 +159,6 @@ app_name_view_ = new views::Label(base::string16()); app_name_view_->SetFontList(font_list); app_name_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - app_name_view_->SetEnabledColor(accent_color_); app_info_container->AddChildView(app_name_view_); // Summary text divider @@ -192,7 +193,6 @@ // Expand button view expand_button_ = new ExpandButton(); - SetExpanded(is_expanded_); app_info_container->AddChildView(expand_button_); // Spacer between left-aligned views and right-aligned views @@ -224,10 +224,6 @@ app_icon_view_->SetImage(img); } -void NotificationHeaderView::ClearAppIcon() { - app_icon_view_->SetImage(gfx::CreateVectorIcon(kProductIcon, accent_color_)); -} - void NotificationHeaderView::SetAppName(const base::string16& name) { app_name_view_->SetText(name); } @@ -281,10 +277,10 @@ } void NotificationHeaderView::SetExpanded(bool expanded) { - is_expanded_ = expanded; - expand_button_->SetImage(gfx::CreateVectorIcon( - expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon, - kExpandIconSize, accent_color_)); + expand_button_->SetImage( + gfx::CreateVectorIcon( + expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon, + kExpandIconSize, gfx::kChromeIconGrey)); } void NotificationHeaderView::SetSettingsButtonEnabled(bool enabled) { @@ -308,12 +304,6 @@ } } -void NotificationHeaderView::SetAccentColor(SkColor color) { - accent_color_ = color; - app_name_view_->SetEnabledColor(accent_color_); - SetExpanded(is_expanded_); -} - bool NotificationHeaderView::IsExpandButtonEnabled() { return expand_button_->visible(); }
diff --git a/ui/message_center/views/notification_header_view.h b/ui/message_center/views/notification_header_view.h index d196eb5a..2471c67a 100644 --- a/ui/message_center/views/notification_header_view.h +++ b/ui/message_center/views/notification_header_view.h
@@ -6,7 +6,6 @@ #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_ #include "base/macros.h" -#include "ui/message_center/message_center_style.h" #include "ui/message_center/views/padded_button.h" #include "ui/views/controls/button/custom_button.h" @@ -31,10 +30,6 @@ void SetSettingsButtonEnabled(bool enabled); void SetCloseButtonEnabled(bool enabled); void SetControlButtonsVisible(bool visible); - // Set the unified theme color used among the app icon, app name, and expand - // button. - void SetAccentColor(SkColor color); - void ClearAppIcon(); void ClearProgress(); void ClearOverflowIndicator(); void ClearTimestamp(); @@ -58,8 +53,6 @@ // Update visibility for both |summary_text_view_| and |timestamp_view_|. void UpdateSummaryTextVisibility(); - SkColor accent_color_ = message_center::kNotificationDefaultAccentColor; - views::Label* app_name_view_ = nullptr; views::Label* summary_text_divider_ = nullptr; views::Label* summary_text_view_ = nullptr; @@ -76,7 +69,6 @@ bool has_progress_ = false; bool has_overflow_indicator_ = false; bool has_timestamp_ = false; - bool is_expanded_ = false; DISALLOW_COPY_AND_ASSIGN(NotificationHeaderView); };
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 37a6d2e..3251a9ba1 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -12,6 +12,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/text_elider.h" @@ -55,6 +56,10 @@ constexpr gfx::Size kActionButtonMinSize(88, 32); constexpr gfx::Size kIconViewSize(30, 30); +// Foreground of small icon image. +constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE; +// Background of small icon image. +const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43); // Background of inline actions area. const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); // Base ink drop color of action buttons. @@ -78,6 +83,37 @@ message_center::kNotificationWidth - kIconViewSize.width() - kContentRowPadding.left() - kContentRowPadding.right(); +const gfx::ImageSkia CreateSolidColorImage(int width, + int height, + SkColor color) { + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + bitmap.eraseColor(color); + return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); +} + +// Take the alpha channel of icon, mask it with the foreground, +// then add the masked foreground on top of the background +const gfx::ImageSkia GetMaskedIcon(const gfx::ImageSkia& icon) { + int width = icon.width(); + int height = icon.height(); + + // Background color grey + const gfx::ImageSkia background = CreateSolidColorImage( + width, height, message_center::kSmallImageBackgroundColor); + // Foreground color white + const gfx::ImageSkia foreground = + CreateSolidColorImage(width, height, message_center::kSmallImageColor); + const gfx::ImageSkia masked_small_image = + gfx::ImageSkiaOperations::CreateMaskedImage(foreground, icon); + return gfx::ImageSkiaOperations::CreateSuperimposedImage(background, + masked_small_image); +} + +const gfx::ImageSkia GetProductIcon() { + return gfx::CreateVectorIcon(kProductIcon, kSmallImageColor); +} + // ItemView //////////////////////////////////////////////////////////////////// // ItemViews are responsible for drawing each list notification item's title and @@ -468,10 +504,6 @@ void NotificationViewMD::CreateOrUpdateContextTitleView( const Notification& notification) { header_row_->SetAppName(notification.display_source()); - header_row_->SetAccentColor( - notification.accent_color() == SK_ColorTRANSPARENT - ? message_center::kNotificationDefaultAccentColor - : notification.accent_color()); header_row_->SetTimestamp(notification.timestamp()); } @@ -655,10 +687,11 @@ void NotificationViewMD::CreateOrUpdateSmallIconView( const Notification& notification) { - if (notification.small_image().IsEmpty()) - header_row_->ClearAppIcon(); - else - header_row_->SetAppIcon(notification.small_image().AsImageSkia()); + gfx::ImageSkia icon = + notification.small_image().IsEmpty() + ? GetProductIcon() + : GetMaskedIcon(notification.small_image().AsImageSkia()); + header_row_->SetAppIcon(icon); } void NotificationViewMD::CreateOrUpdateImageView( @@ -727,12 +760,6 @@ action_buttons_[i]->SchedulePaint(); action_buttons_[i]->Layout(); } - - // Change action button color to the accent color. - action_buttons_[i]->SetEnabledTextColors(notification.accent_color() == - SK_ColorTRANSPARENT - ? kActionButtonTextColor - : notification.accent_color()); } // Inherit mouse hover state when action button views reset.