diff --git a/AUTHORS b/AUTHORS index c191f2e..c3382cc 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -481,6 +481,7 @@ Paweł Hajdan jr <phajdan.jr@gmail.com> Pawel Forysiuk <p.forysiuk@samsung.com> Peng Jiang <leiyi.jp@gmail.com> +Peng Xinchao <pxinchao@gmail.com> Petar Jovanovic <petarj@mips.com> Peter Beverloo <peter@chromium.org> Peter Bright <drpizza@quiscalusmexicanus.org>
diff --git a/DEPS b/DEPS index 15ea04a..1fc4361b 100644 --- a/DEPS +++ b/DEPS
@@ -39,11 +39,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'ed330c8755044822ec536ce8eb0a98a8627302bd', + 'skia_revision': '063ece71848fadc963cbac5c978cd48262138131', # 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': '09c6e1a2fe05b24e34ba8829a760a90c085fe59e', + 'v8_revision': '9e87a245fce674a540231fba9a5ebba64269cd42', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -59,7 +59,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '47bcd4c5c56cdc2d63a0c2ed4e7f68e6ccf523f6', + 'pdfium_revision': '2fad11a8d9d2704cd9ee28b02373ad7ce19c65e3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -220,7 +220,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' + '@' + '896b6c55361f898df240e684a1820b0cb457d62e', # commit position 13176 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'b3f05f40409ca9cfa7986b6b5eb98fb826623939', # commit position 13192 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 23fa5d27..6b29ad4 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -16,6 +16,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/shelf/shelf_model.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/volume_control_delegate.h" #include "ash/common/wm/mru_window_tracker.h" @@ -44,7 +45,6 @@ #include "ash/system/brightness_control_delegate.h" #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h" #include "ash/system/status_area_widget.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/web_notification/web_notification_tray.h"
diff --git a/ash/ash.gyp b/ash/ash.gyp index ec9a855..988ed0d9 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -96,6 +96,20 @@ 'common/shelf/wm_shelf_util.h', 'common/shell_window_ids.cc', 'common/shell_window_ids.h', + 'common/system/chromeos/devicetype_utils.cc', + 'common/system/chromeos/devicetype_utils.h', + 'common/system/chromeos/power/battery_notification.cc', + 'common/system/chromeos/power/battery_notification.h', + 'common/system/chromeos/power/dual_role_notification.cc', + 'common/system/chromeos/power/dual_role_notification.h', + 'common/system/chromeos/power/power_status.cc', + 'common/system/chromeos/power/power_status.h', + 'common/system/chromeos/power/power_status_view.cc', + 'common/system/chromeos/power/power_status_view.h', + 'common/system/chromeos/power/tray_power.cc', + 'common/system/chromeos/power/tray_power.h', + 'common/system/chromeos/settings/tray_settings.cc', + 'common/system/chromeos/settings/tray_settings.h', 'common/system/chromeos/shutdown_policy_observer.h', 'common/system/chromeos/system_clock_observer.cc', 'common/system/chromeos/system_clock_observer.h', @@ -108,6 +122,8 @@ 'common/system/date/tray_date.h', 'common/system/networking_config_delegate.cc', 'common/system/networking_config_delegate.h', + 'common/system/system_notifier.cc', + 'common/system/system_notifier.h', 'common/system/tray/actionable_view.cc', 'common/system/tray/actionable_view.h', 'common/system/tray/default_system_tray_delegate.cc', @@ -486,8 +502,6 @@ 'system/chromeos/brightness/brightness_controller_chromeos.h', 'system/chromeos/brightness/tray_brightness.cc', 'system/chromeos/brightness/tray_brightness.h', - 'system/chromeos/devicetype_utils.cc', - 'system/chromeos/devicetype_utils.h', 'system/chromeos/enterprise/enterprise_domain_observer.h', 'system/chromeos/enterprise/tray_enterprise.cc', 'system/chromeos/enterprise/tray_enterprise.h', @@ -514,18 +528,8 @@ 'system/chromeos/network/vpn_delegate.h', 'system/chromeos/network/vpn_list_view.cc', 'system/chromeos/network/vpn_list_view.h', - 'system/chromeos/power/battery_notification.cc', - 'system/chromeos/power/battery_notification.h', - 'system/chromeos/power/dual_role_notification.cc', - 'system/chromeos/power/dual_role_notification.h', 'system/chromeos/power/power_event_observer.cc', 'system/chromeos/power/power_event_observer.h', - 'system/chromeos/power/power_status.cc', - 'system/chromeos/power/power_status.h', - 'system/chromeos/power/power_status_view.cc', - 'system/chromeos/power/power_status_view.h', - 'system/chromeos/power/tray_power.cc', - 'system/chromeos/power/tray_power.h', 'system/chromeos/power/video_activity_notifier.cc', 'system/chromeos/power/video_activity_notifier.h', 'system/chromeos/rotation/tray_rotation_lock.cc', @@ -551,8 +555,6 @@ 'system/chromeos/session/session_length_limit_observer.h', 'system/chromeos/session/tray_session_length_limit.cc', 'system/chromeos/session/tray_session_length_limit.h', - 'system/chromeos/settings/tray_settings.cc', - 'system/chromeos/settings/tray_settings.h', 'system/chromeos/supervised/custodian_info_tray_observer.h', 'system/chromeos/supervised/tray_supervised_user.cc', 'system/chromeos/supervised/tray_supervised_user.h', @@ -577,8 +579,6 @@ 'system/status_area_widget.h', 'system/status_area_widget_delegate.cc', 'system/status_area_widget_delegate.h', - 'system/system_notifier.cc', - 'system/system_notifier.h', 'system/toast/toast_data.cc', 'system/toast/toast_data.h', 'system/toast/toast_manager.cc', @@ -895,6 +895,9 @@ 'autoclick/autoclick_unittest.cc', 'common/material_design/material_design_controller_unittest.cc', 'common/shelf/shelf_model_unittest.cc', + 'common/system/chromeos/power/power_status_unittest.cc', + 'common/system/chromeos/power/power_status_view_unittest.cc', + 'common/system/chromeos/power/tray_power_unittest.cc', 'common/system/date/date_view_unittest.cc', 'common/system/update/tray_update_unittest.cc', 'content/display/screen_orientation_controller_chromeos_unittest.cc', @@ -954,9 +957,6 @@ 'system/chromeos/brightness/tray_brightness_unittest.cc', 'system/chromeos/multi_user/user_switch_util_unittest.cc', 'system/chromeos/power/power_event_observer_unittest.cc', - 'system/chromeos/power/power_status_unittest.cc', - 'system/chromeos/power/power_status_view_unittest.cc', - 'system/chromeos/power/tray_power_unittest.cc', 'system/chromeos/rotation/tray_rotation_lock_unittest.cc', 'system/chromeos/screen_security/screen_tray_item_unittest.cc', 'system/chromeos/session/logout_confirmation_controller_unittest.cc',
diff --git a/ash/common/DEPS b/ash/common/DEPS index 1412c1f7..8d45fdc 100644 --- a/ash/common/DEPS +++ b/ash/common/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "-ash", "+ash/ash_export.h", + "+ash/ash_switches.h", "+ash/common", "+ui", "-ui/aura",
diff --git a/ash/common/material_design/material_design_controller.cc b/ash/common/material_design/material_design_controller.cc index f458402..711aafa2 100644 --- a/ash/common/material_design/material_design_controller.cc +++ b/ash/common/material_design/material_design_controller.cc
@@ -52,16 +52,6 @@ } // static -bool MaterialDesignController::IsMaterial() { - return IsMaterialExperimental() || GetMode() == Mode::MATERIAL_NORMAL; -} - -// static -bool MaterialDesignController::IsMaterialExperimental() { - return GetMode() == Mode::MATERIAL_EXPERIMENTAL; -} - -// static MaterialDesignController::Mode MaterialDesignController::GetMode() { DCHECK_NE(mode_, Mode::UNINITIALIZED); return mode_; @@ -69,7 +59,7 @@ // static bool MaterialDesignController::IsOverviewMaterial() { - return MaterialDesignController::IsMaterialExperimental(); + return MaterialDesignController::IsMaterial(); } // static @@ -88,8 +78,23 @@ } // static +bool MaterialDesignController::IsMaterial() { + return IsMaterialExperimental() || IsMaterialNormal(); +} + +// static +bool MaterialDesignController::IsMaterialNormal() { + return GetMode() == Mode::MATERIAL_NORMAL; +} + +// static +bool MaterialDesignController::IsMaterialExperimental() { + return GetMode() == Mode::MATERIAL_EXPERIMENTAL; +} + +// static MaterialDesignController::Mode MaterialDesignController::DefaultMode() { - return Mode::NON_MATERIAL; + return Mode::MATERIAL_NORMAL; } // static
diff --git a/ash/common/material_design/material_design_controller.h b/ash/common/material_design/material_design_controller.h index 98f8c44..803b671 100644 --- a/ash/common/material_design/material_design_controller.h +++ b/ash/common/material_design/material_design_controller.h
@@ -30,18 +30,9 @@ }; // Initializes |mode_|. Must be called before calling IsMaterial(), - // IsMaterialExperimental(), or GetMode(). + // IsMaterialExperimental(), IsMaterialNormal(), or GetMode(). static void Initialize(); - // Returns true if Material Design is enabled in Chrome OS system UI. - // Maps to "ash-md" flag "enabled" or "experimental" values. - static bool IsMaterial(); - - // Returns true if Material Design experimental features are enabled in - // Chrome OS system UI. - // Maps to "--ash-md=experimental" command line switch value. - static bool IsMaterialExperimental(); - // Returns the currently initialized MaterialDesignController::Mode type for // Chrome OS system UI. static Mode GetMode(); @@ -66,6 +57,19 @@ // Material Design |Mode| for Chrome OS system UI. Used only by tests. static Mode mode(); + // Returns true if Material Design is enabled in Chrome OS system UI. + // Maps to "ash-md" flag "enabled" or "experimental" values. + static bool IsMaterial(); + + // Returns true if Material Design normal features are enabled in Chrome OS + // system UI. Maps to "--ash-md=enabled" command line switch value. + static bool IsMaterialNormal(); + + // Returns true if Material Design experimental features are enabled in + // Chrome OS system UI. Maps to "--ash-md=experimental" command line switch + // value. + static bool IsMaterialExperimental(); + // Returns the per-platform default material design variant. static Mode DefaultMode();
diff --git a/ash/common/material_design/material_design_controller_unittest.cc b/ash/common/material_design/material_design_controller_unittest.cc index b9a6772..5935b264 100644 --- a/ash/common/material_design/material_design_controller_unittest.cc +++ b/ash/common/material_design/material_design_controller_unittest.cc
@@ -99,28 +99,28 @@ MaterialDesignController::Mode::MATERIAL_NORMAL || test::MaterialDesignControllerTestAPI::DefaultMode() == MaterialDesignController::Mode::MATERIAL_EXPERIMENTAL, - MaterialDesignController::IsMaterial()); + test::MaterialDesignControllerTestAPI::IsMaterial()); } // Verify that MaterialDesignController::IsMaterial() will be false when // initialized with command line flag "disabled". TEST_F(MaterialDesignControllerTestNonMaterial, CommandLineValue) { - EXPECT_FALSE(MaterialDesignController::IsMaterial()); - EXPECT_FALSE(MaterialDesignController::IsMaterialExperimental()); + EXPECT_FALSE(test::MaterialDesignControllerTestAPI::IsMaterial()); + EXPECT_FALSE(test::MaterialDesignControllerTestAPI::IsMaterialExperimental()); } // Verify that MaterialDesignController::IsMaterial() will be true when // initialized with command line flag "enabled". TEST_F(MaterialDesignControllerTestMaterial, CommandLineValue) { - EXPECT_TRUE(MaterialDesignController::IsMaterial()); - EXPECT_FALSE(MaterialDesignController::IsMaterialExperimental()); + EXPECT_TRUE(test::MaterialDesignControllerTestAPI::IsMaterial()); + EXPECT_FALSE(test::MaterialDesignControllerTestAPI::IsMaterialExperimental()); } // Verify that MaterialDesignController::IsMaterialexperimental() will be true // when initialized with command line flag "experimental". TEST_F(MaterialDesignControllerTestExperimental, CommandLineValue) { - EXPECT_TRUE(MaterialDesignController::IsMaterial()); - EXPECT_TRUE(MaterialDesignController::IsMaterialExperimental()); + EXPECT_TRUE(test::MaterialDesignControllerTestAPI::IsMaterial()); + EXPECT_TRUE(test::MaterialDesignControllerTestAPI::IsMaterialExperimental()); } // Verify an invalid command line value uses the default mode. @@ -129,7 +129,7 @@ MaterialDesignController::Mode::MATERIAL_NORMAL || test::MaterialDesignControllerTestAPI::DefaultMode() == MaterialDesignController::Mode::MATERIAL_EXPERIMENTAL, - MaterialDesignController::IsMaterial()); + test::MaterialDesignControllerTestAPI::IsMaterial()); } } // namespace ash
diff --git a/ash/common/shelf/shelf_constants.cc b/ash/common/shelf/shelf_constants.cc index e9aa5c2..b2819f2 100644 --- a/ash/common/shelf/shelf_constants.cc +++ b/ash/common/shelf/shelf_constants.cc
@@ -22,10 +22,10 @@ const SkColor kShelfIconColor = SK_ColorWHITE; int GetShelfConstant(ShelfConstant shelf_constant) { - const int kShelfBackgroundAlpha[] = {204, 153, 153}; - const int kShelfSize[] = {47, 48, 48}; - const int kShelfButtonSpacing[] = {10, 16, 16}; - const int kShelfButtonSize[] = {44, 48, 48}; + const int kShelfBackgroundAlpha[] = {204, 204, 153}; + const int kShelfSize[] = {47, 47, 48}; + const int kShelfButtonSpacing[] = {10, 10, 16}; + const int kShelfButtonSize[] = {44, 44, 48}; const int mode = MaterialDesignController::GetMode(); DCHECK(mode >= MaterialDesignController::NON_MATERIAL &&
diff --git a/ash/system/chromeos/devicetype_utils.cc b/ash/common/system/chromeos/devicetype_utils.cc similarity index 94% rename from ash/system/chromeos/devicetype_utils.cc rename to ash/common/system/chromeos/devicetype_utils.cc index 7f31a388..920b50d 100644 --- a/ash/system/chromeos/devicetype_utils.cc +++ b/ash/common/system/chromeos/devicetype_utils.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "chromeos/system/devicetype.h" #include "grit/ash_strings.h"
diff --git a/ash/system/chromeos/devicetype_utils.h b/ash/common/system/chromeos/devicetype_utils.h similarity index 82% rename from ash/system/chromeos/devicetype_utils.h rename to ash/common/system/chromeos/devicetype_utils.h index bcdc04f..a84fd87 100644 --- a/ash/system/chromeos/devicetype_utils.h +++ b/ash/common/system/chromeos/devicetype_utils.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_ -#define ASH_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_ #include "ash/ash_export.h" #include "base/strings/string16.h" @@ -23,4 +23,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_DEVICETYPE_UTILS_H_
diff --git a/ash/system/chromeos/power/battery_notification.cc b/ash/common/system/chromeos/power/battery_notification.cc similarity index 95% rename from ash/system/chromeos/power/battery_notification.cc rename to ash/common/system/chromeos/power/battery_notification.cc index ba522453..67cf3959 100644 --- a/ash/system/chromeos/power/battery_notification.cc +++ b/ash/common/system/chromeos/power/battery_notification.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/battery_notification.h" +#include "ash/common/system/chromeos/power/battery_notification.h" -#include "ash/system/chromeos/power/power_status.h" -#include "ash/system/system_notifier.h" +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/system_notifier.h" #include "base/i18n/message_formatter.h" #include "base/i18n/time_formatting.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/system/chromeos/power/battery_notification.h b/ash/common/system/chromeos/power/battery_notification.h similarity index 76% rename from ash/system/chromeos/power/battery_notification.h rename to ash/common/system/chromeos/power/battery_notification.h index 24284d19..fa698320 100644 --- a/ash/system/chromeos/power/battery_notification.h +++ b/ash/common/system/chromeos/power/battery_notification.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_ -#define ASH_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_ #include "ash/ash_export.h" -#include "ash/system/chromeos/power/tray_power.h" +#include "ash/common/system/chromeos/power/tray_power.h" #include "base/macros.h" namespace message_center { @@ -33,4 +33,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_POWER_BATTERY_NOTIFICATION_H_
diff --git a/ash/system/chromeos/power/dual_role_notification.cc b/ash/common/system/chromeos/power/dual_role_notification.cc similarity index 96% rename from ash/system/chromeos/power/dual_role_notification.cc rename to ash/common/system/chromeos/power/dual_role_notification.cc index 58e6aec..1b90278 100644 --- a/ash/system/chromeos/power/dual_role_notification.cc +++ b/ash/common/system/chromeos/power/dual_role_notification.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/dual_role_notification.h" +#include "ash/common/system/chromeos/power/dual_role_notification.h" #include <set> +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" -#include "ash/system/chromeos/power/power_status.h" -#include "ash/system/system_notifier.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h"
diff --git a/ash/system/chromeos/power/dual_role_notification.h b/ash/common/system/chromeos/power/dual_role_notification.h similarity index 80% rename from ash/system/chromeos/power/dual_role_notification.h rename to ash/common/system/chromeos/power/dual_role_notification.h index d990093..a648783 100644 --- a/ash/system/chromeos/power/dual_role_notification.h +++ b/ash/common/system/chromeos/power/dual_role_notification.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_ -#define ASH_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_ #include <stddef.h> #include <memory> #include "ash/ash_export.h" -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "base/macros.h" namespace message_center { @@ -45,4 +45,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_POWER_DUAL_ROLE_NOTIFICATION_H_
diff --git a/ash/system/chromeos/power/power_status.cc b/ash/common/system/chromeos/power/power_status.cc similarity index 98% rename from ash/system/chromeos/power/power_status.cc rename to ash/common/system/chromeos/power/power_status.cc index 5b2a0ad..806db34 100644 --- a/ash/system/chromeos/power/power_status.cc +++ b/ash/common/system/chromeos/power/power_status.cc
@@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include <algorithm> #include <cmath> -#include "ash/shell.h" -#include "ash/shell_delegate.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/system/chromeos/power/power_status.h b/ash/common/system/chromeos/power/power_status.h similarity index 97% rename from ash/system/chromeos/power/power_status.h rename to ash/common/system/chromeos/power/power_status.h index 7fb94d72..26c4b19 100644 --- a/ash/system/chromeos/power/power_status.h +++ b/ash/common/system/chromeos/power/power_status.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_ -#define ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_ #include <string> #include <vector> @@ -220,4 +220,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_H_
diff --git a/ash/system/chromeos/power/power_status_unittest.cc b/ash/common/system/chromeos/power/power_status_unittest.cc similarity index 98% rename from ash/system/chromeos/power/power_status_unittest.cc rename to ash/common/system/chromeos/power/power_status_unittest.cc index a747e5d..5115828f 100644 --- a/ash/system/chromeos/power/power_status_unittest.cc +++ b/ash/common/system/chromeos/power/power_status_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include <memory>
diff --git a/ash/system/chromeos/power/power_status_view.cc b/ash/common/system/chromeos/power/power_status_view.cc similarity index 95% rename from ash/system/chromeos/power/power_status_view.cc rename to ash/common/system/chromeos/power/power_status_view.cc index ec472cc..a30ce2c4 100644 --- a/ash/system/chromeos/power/power_status_view.cc +++ b/ash/common/system/chromeos/power/power_status_view.cc
@@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/power_status_view.h" +#include "ash/common/system/chromeos/power/power_status_view.h" +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/tray_power.h" #include "ash/common/system/tray/fixed_sized_image_view.h" #include "ash/common/system/tray/tray_constants.h" -#include "ash/shell.h" -#include "ash/shell_delegate.h" -#include "ash/system/chromeos/power/power_status.h" -#include "ash/system/chromeos/power/tray_power.h" #include "base/i18n/message_formatter.h" #include "base/i18n/time_formatting.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/system/chromeos/power/power_status_view.h b/ash/common/system/chromeos/power/power_status_view.h similarity index 86% rename from ash/system/chromeos/power/power_status_view.h rename to ash/common/system/chromeos/power/power_status_view.h index c050d4d..5d92e1e 100644 --- a/ash/system/chromeos/power/power_status_view.h +++ b/ash/common/system/chromeos/power/power_status_view.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_ -#define ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_ #include "ash/ash_export.h" -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "base/macros.h" #include "ui/views/view.h" @@ -60,4 +60,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_POWER_POWER_STATUS_VIEW_H_
diff --git a/ash/system/chromeos/power/power_status_view_unittest.cc b/ash/common/system/chromeos/power/power_status_view_unittest.cc similarity index 97% rename from ash/system/chromeos/power/power_status_view_unittest.cc rename to ash/common/system/chromeos/power/power_status_view_unittest.cc index 67b9941..c2d4964 100644 --- a/ash/system/chromeos/power/power_status_view_unittest.cc +++ b/ash/common/system/chromeos/power/power_status_view_unittest.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/power_status_view.h" +#include "ash/common/system/chromeos/power/power_status_view.h" -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "ash/test/ash_test_base.h" #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "grit/ash_strings.h"
diff --git a/ash/system/chromeos/power/tray_power.cc b/ash/common/system/chromeos/power/tray_power.cc similarity index 97% rename from ash/system/chromeos/power/tray_power.cc rename to ash/common/system/chromeos/power/tray_power.cc index ecfaa85..22e8ec1 100644 --- a/ash/system/chromeos/power/tray_power.cc +++ b/ash/common/system/chromeos/power/tray_power.cc
@@ -2,21 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/tray_power.h" +#include "ash/common/system/chromeos/power/tray_power.h" #include <utility> #include "ash/ash_switches.h" #include "ash/common/accessibility_delegate.h" +#include "ash/common/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/power/battery_notification.h" +#include "ash/common/system/chromeos/power/dual_role_notification.h" #include "ash/common/system/date/date_view.h" +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_utils.h" -#include "ash/shell.h" -#include "ash/system/chromeos/devicetype_utils.h" -#include "ash/system/chromeos/power/battery_notification.h" -#include "ash/system/chromeos/power/dual_role_notification.h" -#include "ash/system/system_notifier.h" #include "base/command_line.h" #include "base/logging.h" #include "base/metrics/histogram.h"
diff --git a/ash/system/chromeos/power/tray_power.h b/ash/common/system/chromeos/power/tray_power.h similarity index 93% rename from ash/system/chromeos/power/tray_power.h rename to ash/common/system/chromeos/power/tray_power.h index 4f47be8..9ad7516 100644 --- a/ash/system/chromeos/power/tray_power.h +++ b/ash/common/system/chromeos/power/tray_power.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_ -#define ASH_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_ #include <memory> +#include "ash/common/system/chromeos/power/power_status.h" #include "ash/common/system/tray/system_tray_item.h" -#include "ash/system/chromeos/power/power_status.h" #include "base/macros.h" class SkBitmap; @@ -121,4 +121,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_POWER_TRAY_POWER_H_
diff --git a/ash/system/chromeos/power/tray_power_unittest.cc b/ash/common/system/chromeos/power/tray_power_unittest.cc similarity index 99% rename from ash/system/chromeos/power/tray_power_unittest.cc rename to ash/common/system/chromeos/power/tray_power_unittest.cc index 5423631..d2d102f 100644 --- a/ash/system/chromeos/power/tray_power_unittest.cc +++ b/ash/common/system/chromeos/power/tray_power_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/power/tray_power.h" +#include "ash/common/system/chromeos/power/tray_power.h" #include <map> #include <memory>
diff --git a/ash/system/chromeos/settings/tray_settings.cc b/ash/common/system/chromeos/settings/tray_settings.cc similarity index 86% rename from ash/system/chromeos/settings/tray_settings.cc rename to ash/common/system/chromeos/settings/tray_settings.cc index 5c1ce9b7..33cf711 100644 --- a/ash/system/chromeos/settings/tray_settings.cc +++ b/ash/common/system/chromeos/settings/tray_settings.cc
@@ -2,17 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/settings/tray_settings.h" +#include "ash/common/system/chromeos/settings/tray_settings.h" #include "ash/common/session/session_state_delegate.h" +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status_view.h" #include "ash/common/system/tray/actionable_view.h" #include "ash/common/system/tray/fixed_sized_image_view.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/wm_shell.h" -#include "ash/shell.h" -#include "ash/system/chromeos/power/power_status.h" -#include "ash/system/chromeos/power/power_status_view.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h" @@ -40,12 +39,11 @@ ash::kTrayPopupPaddingBetweenItems)); bool power_view_right_align = false; - bool userAddingRunning = ash::Shell::GetInstance() - ->session_state_delegate() - ->IsInSecondaryLoginScreen(); - if (login_status_ != LoginStatus::NOT_LOGGED_IN && - login_status_ != LoginStatus::LOCKED && !userAddingRunning) { + login_status_ != LoginStatus::LOCKED && + !WmShell::Get() + ->GetSessionStateDelegate() + ->IsInSecondaryLoginScreen()) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); views::ImageView* icon = new ash::FixedSizedImageView(0, ash::kTrayPopupItemHeight); @@ -73,12 +71,9 @@ // Overridden from ash::ActionableView. bool PerformAction(const ui::Event& event) override { - bool adding_user = Shell::GetInstance() - ->session_state_delegate() - ->IsInSecondaryLoginScreen(); - if (login_status_ == LoginStatus::NOT_LOGGED_IN || - login_status_ == LoginStatus::LOCKED || adding_user) { + login_status_ == LoginStatus::LOCKED || + WmShell::Get()->GetSessionStateDelegate()->IsInSecondaryLoginScreen()) { return false; } @@ -157,15 +152,13 @@ return NULL; } -void TraySettings::DestroyTrayView() { -} +void TraySettings::DestroyTrayView() {} void TraySettings::DestroyDefaultView() { default_view_ = NULL; } -void TraySettings::DestroyDetailedView() { -} +void TraySettings::DestroyDetailedView() {} void TraySettings::UpdateAfterLoginStatusChange(LoginStatus status) {}
diff --git a/ash/system/chromeos/settings/tray_settings.h b/ash/common/system/chromeos/settings/tray_settings.h similarity index 83% rename from ash/system/chromeos/settings/tray_settings.h rename to ash/common/system/chromeos/settings/tray_settings.h index 5f5e0f891..2a46942b 100644 --- a/ash/system/chromeos/settings/tray_settings.h +++ b/ash/common/system/chromeos/settings/tray_settings.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_ -#define ASH_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_ +#ifndef ASH_COMMON_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_ #include "ash/common/system/tray/system_tray_item.h" #include "base/macros.h" @@ -35,4 +35,4 @@ } // namespace ash -#endif // ASH_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_ +#endif // ASH_COMMON_SYSTEM_CHROMEOS_SETTINGS_TRAY_SETTINGS_H_
diff --git a/ash/system/system_notifier.cc b/ash/common/system/system_notifier.cc similarity index 98% rename from ash/system/system_notifier.cc rename to ash/common/system/system_notifier.cc index 76875de..1d35d4f 100644 --- a/ash/system/system_notifier.cc +++ b/ash/common/system/system_notifier.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "base/logging.h"
diff --git a/ash/system/system_notifier.h b/ash/common/system/system_notifier.h similarity index 93% rename from ash/system/system_notifier.h rename to ash/common/system/system_notifier.h index 8febc9f..a43484b 100644 --- a/ash/system/system_notifier.h +++ b/ash/common/system/system_notifier.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_SYSTEM_NOTIFIER_H_ -#define ASH_SYSTEM_SYSTEM_NOTIFIER_H_ +#ifndef ASH_COMMON_SYSTEM_SYSTEM_NOTIFIER_H_ +#define ASH_COMMON_SYSTEM_SYSTEM_NOTIFIER_H_ #include <string> @@ -48,4 +48,4 @@ } // namespace system_notifier } // namespace ash -#endif // ASH_SYSTEM_SYSTEM_NOTIFIER_H_ +#endif // ASH_COMMON_SYSTEM_SYSTEM_NOTIFIER_H_
diff --git a/ash/common/system/tray/tray_constants.cc b/ash/common/system/tray/tray_constants.cc index 4c719ad..667e952 100644 --- a/ash/common/system/tray/tray_constants.cc +++ b/ash/common/system/tray/tray_constants.cc
@@ -90,8 +90,8 @@ const int kShelfItemSizeMD = 32; int GetTrayConstant(TrayConstant constant) { - const int kTraySpacing[] = {4, 8, 8}; - const int kTrayPaddingFromEdgeOfShelf[] = {3, 8, 8}; + const int kTraySpacing[] = {4, 4, 8}; + const int kTrayPaddingFromEdgeOfShelf[] = {3, 3, 8}; const int mode = MaterialDesignController::GetMode(); DCHECK(mode >= MaterialDesignController::NON_MATERIAL &&
diff --git a/ash/display/display_util.cc b/ash/display/display_util.cc index ec36ab2..dd62d4b4 100644 --- a/ash/display/display_util.cc +++ b/ash/display/display_util.cc
@@ -6,12 +6,12 @@ #include <algorithm> +#include "ash/common/system/system_notifier.h" #include "ash/display/display_info.h" #include "ash/display/display_manager.h" #include "ash/host/ash_window_tree_host.h" #include "ash/new_window_delegate.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "base/strings/string_number_conversions.h" #include "grit/ash_resources.h" #include "ui/aura/env.h"
diff --git a/ash/display/resolution_notification_controller.cc b/ash/display/resolution_notification_controller.cc index f740ea4..9d66bc80 100644 --- a/ash/display/resolution_notification_controller.cc +++ b/ash/display/resolution_notification_controller.cc
@@ -6,10 +6,10 @@ #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/display/display_info.h" #include "ash/display/display_manager.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h"
diff --git a/ash/shell.cc b/ash/shell.cc index e17a8da..e1260682 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -127,6 +127,7 @@ #include "ash/accelerators/magnifier_key_scroller.h" #include "ash/accelerators/spoken_feedback_toggler.h" #include "ash/common/ash_constants.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "ash/display/display_change_observer_chromeos.h" #include "ash/display/display_color_manager_chromeos.h" #include "ash/display/display_error_observer_chromeos.h" @@ -137,7 +138,6 @@ #include "ash/system/chromeos/bluetooth/bluetooth_notification_controller.h" #include "ash/system/chromeos/brightness/brightness_controller_chromeos.h" #include "ash/system/chromeos/power/power_event_observer.h" -#include "ash/system/chromeos/power/power_status.h" #include "ash/system/chromeos/power/video_activity_notifier.h" #include "ash/system/chromeos/session/last_window_closed_logout_reminder.h" #include "ash/system/chromeos/session/logout_confirmation_controller.h"
diff --git a/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc index 1864a1cf..d4985d9 100644 --- a/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc +++ b/ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc
@@ -7,7 +7,7 @@ #include <memory> #include <utility> -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "base/bind.h" #include "base/callback.h" #include "base/logging.h"
diff --git a/ash/system/chromeos/screen_security/screen_capture_tray_item.cc b/ash/system/chromeos/screen_security/screen_capture_tray_item.cc index cfa538b..fe0dc5ad 100644 --- a/ash/system/chromeos/screen_security/screen_capture_tray_item.cc +++ b/ash/system/chromeos/screen_security/screen_capture_tray_item.cc
@@ -6,9 +6,9 @@ #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/chromeos/screen_security/screen_share_tray_item.cc b/ash/system/chromeos/screen_security/screen_share_tray_item.cc index d04a04fc..2c8bd67 100644 --- a/ash/system/chromeos/screen_security/screen_share_tray_item.cc +++ b/ash/system/chromeos/screen_security/screen_share_tray_item.cc
@@ -6,8 +6,8 @@ #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/chromeos/session/tray_session_length_limit.cc b/ash/system/chromeos/session/tray_session_length_limit.cc index 5588718..0dec056 100644 --- a/ash/system/chromeos/session/tray_session_length_limit.cc +++ b/ash/system/chromeos/session/tray_session_length_limit.cc
@@ -8,11 +8,11 @@ #include <memory> #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" #include "ash/system/chromeos/label_tray_view.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_notifier.h" #include "base/logging.h"
diff --git a/ash/system/chromeos/supervised/tray_supervised_user.cc b/ash/system/chromeos/supervised/tray_supervised_user.cc index df6e92b..c694c7f5 100644 --- a/ash/system/chromeos/supervised/tray_supervised_user.cc +++ b/ash/system/chromeos/supervised/tray_supervised_user.cc
@@ -6,11 +6,11 @@ #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_notification_view.h" #include "ash/common/wm_shell.h" #include "ash/system/chromeos/label_tray_view.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/user/login_status.h" #include "base/callback.h"
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc index 9462d513..d2eba2a 100644 --- a/ash/system/chromeos/tray_display.cc +++ b/ash/system/chromeos/tray_display.cc
@@ -8,6 +8,8 @@ #include <utility> #include <vector> +#include "ash/common/system/chromeos/devicetype_utils.h" +#include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/actionable_view.h" #include "ash/common/system/tray/fixed_sized_image_view.h" #include "ash/common/system/tray/system_tray_delegate.h" @@ -18,8 +20,6 @@ #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/display/window_tree_host_manager.h" #include "ash/shell.h" -#include "ash/system/chromeos/devicetype_utils.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray.h" #include "base/bind.h" #include "base/strings/string_util.h"
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc index ce5a878..374d9d3 100644 --- a/ash/system/chromeos/tray_display_unittest.cc +++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -4,11 +4,11 @@ #include "ash/system/chromeos/tray_display.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "ash/display/display_manager.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/system/chromeos/devicetype_utils.h" #include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/display_manager_test_api.h"
diff --git a/ash/system/locale/locale_notification_controller.cc b/ash/system/locale/locale_notification_controller.cc index 174a662c..bc514d58 100644 --- a/ash/system/locale/locale_notification_controller.cc +++ b/ash/system/locale/locale_notification_controller.cc
@@ -6,8 +6,8 @@ #include <utility> +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray_notifier.h" #include "base/strings/string16.h" #include "grit/ash_resources.h"
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index eec513c..1fe6be7 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc
@@ -46,6 +46,9 @@ #include "ui/views/view.h" #if defined(OS_CHROMEOS) +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/tray_power.h" +#include "ash/common/system/chromeos/settings/tray_settings.h" #include "ash/system/chromeos/audio/tray_audio_chromeos.h" #include "ash/system/chromeos/bluetooth/tray_bluetooth.h" #include "ash/system/chromeos/brightness/tray_brightness.h" @@ -53,13 +56,10 @@ #include "ash/system/chromeos/network/tray_network.h" #include "ash/system/chromeos/network/tray_sms.h" #include "ash/system/chromeos/network/tray_vpn.h" -#include "ash/system/chromeos/power/power_status.h" -#include "ash/system/chromeos/power/tray_power.h" #include "ash/system/chromeos/rotation/tray_rotation_lock.h" #include "ash/system/chromeos/screen_security/screen_capture_tray_item.h" #include "ash/system/chromeos/screen_security/screen_share_tray_item.h" #include "ash/system/chromeos/session/tray_session_length_limit.h" -#include "ash/system/chromeos/settings/tray_settings.h" #include "ash/system/chromeos/supervised/tray_supervised_user.h" #include "ash/system/chromeos/tray_caps_lock.h" #include "ash/system/chromeos/tray_display.h"
diff --git a/ash/test/material_design_controller_test_api.cc b/ash/test/material_design_controller_test_api.cc index be221e7..7ce735ac 100644 --- a/ash/test/material_design_controller_test_api.cc +++ b/ash/test/material_design_controller_test_api.cc
@@ -18,6 +18,21 @@ } // static +bool MaterialDesignControllerTestAPI::IsMaterial() { + return MaterialDesignController::IsMaterial(); +} + +// static +bool MaterialDesignControllerTestAPI::IsMaterialNormal() { + return MaterialDesignController::IsMaterialNormal(); +} + +// static +bool MaterialDesignControllerTestAPI::IsMaterialExperimental() { + return MaterialDesignController::IsMaterialExperimental(); +} + +// static MaterialDesignController::Mode MaterialDesignControllerTestAPI::DefaultMode() { return MaterialDesignController::DefaultMode(); }
diff --git a/ash/test/material_design_controller_test_api.h b/ash/test/material_design_controller_test_api.h index c5603b0..109dd76 100644 --- a/ash/test/material_design_controller_test_api.h +++ b/ash/test/material_design_controller_test_api.h
@@ -20,6 +20,9 @@ ~MaterialDesignControllerTestAPI(); // Wrapper functions for MaterialDesignController internal functions. + static bool IsMaterial(); + static bool IsMaterialNormal(); + static bool IsMaterialExperimental(); static MaterialDesignController::Mode DefaultMode(); static void Uninitialize();
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py index a1ad7ef..544fbf0e 100644 --- a/build/android/pylib/local/device/local_device_test_run.py +++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -6,9 +6,13 @@ import functools import imp import logging +import signal +import thread +import threading from devil import base_error from devil.android import device_errors +from devil.utils import signal_handler from pylib import valgrind_tools from pylib.base import base_test_result from pylib.base import test_run @@ -67,8 +71,10 @@ except device_errors.DeviceUnreachableError: logging.exception('Shard died: %s(%s)', f.__name__, str(dev)) except base_error.BaseError: - logging.exception('Shard failed: %s(%s)', f.__name__, - str(dev)) + logging.exception('Shard failed: %s(%s)', f.__name__, str(dev)) + except SystemExit: + logging.exception('Shard killed: %s(%s)', f.__name__, str(dev)) + raise if on_failure: on_failure(dev, f.__name__) return None @@ -88,9 +94,14 @@ def RunTests(self): tests = self._GetTests() + exit_now = threading.Event() + @handle_shard_failures def run_tests_on_device(dev, tests, results): for test in tests: + if exit_now.isSet(): + thread.exit() + result = None try: result = self._RunTest(dev, test) @@ -112,34 +123,38 @@ logging.info('Finished running tests on this device.') - tries = 0 - results = [] - while tries < self._env.max_tries and tests: - logging.info('STARTING TRY #%d/%d', tries + 1, self._env.max_tries) - logging.info('Will run %d tests on %d devices: %s', - len(tests), len(self._env.devices), - ', '.join(str(d) for d in self._env.devices)) - for t in tests: - logging.debug(' %s', t) + def stop_tests(_signum, _frame): + exit_now.set() - try_results = base_test_result.TestRunResults() - if self._ShouldShard(): - tc = test_collection.TestCollection(self._CreateShards(tests)) - self._env.parallel_devices.pMap( - run_tests_on_device, tc, try_results).pGet(None) - else: - self._env.parallel_devices.pMap( - run_tests_on_device, tests, try_results).pGet(None) + with signal_handler.AddSignalHandler(signal.SIGTERM, stop_tests): + tries = 0 + results = [] + while tries < self._env.max_tries and tests: + logging.info('STARTING TRY #%d/%d', tries + 1, self._env.max_tries) + logging.info('Will run %d tests on %d devices: %s', + len(tests), len(self._env.devices), + ', '.join(str(d) for d in self._env.devices)) + for t in tests: + logging.debug(' %s', t) - results.append(try_results) - tries += 1 - tests = self._GetTestsToRetry(tests, try_results) + try_results = base_test_result.TestRunResults() + if self._ShouldShard(): + tc = test_collection.TestCollection(self._CreateShards(tests)) + self._env.parallel_devices.pMap( + run_tests_on_device, tc, try_results).pGet(None) + else: + self._env.parallel_devices.pMap( + run_tests_on_device, tests, try_results).pGet(None) - logging.info('FINISHED TRY #%d/%d', tries, self._env.max_tries) - if tests: - logging.info('%d failed tests remain.', len(tests)) - else: - logging.info('All tests completed.') + results.append(try_results) + tries += 1 + tests = self._GetTestsToRetry(tests, try_results) + + logging.info('FINISHED TRY #%d/%d', tries, self._env.max_tries) + if tests: + logging.info('%d failed tests remain.', len(tests)) + else: + logging.info('All tests completed.') return results
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index f21b815..ea75edb 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -60,6 +60,7 @@ ../../third_party/catapult/devil/devil/utils/parallelizer.py ../../third_party/catapult/devil/devil/utils/reraiser_thread.py ../../third_party/catapult/devil/devil/utils/run_tests_helper.py +../../third_party/catapult/devil/devil/utils/signal_handler.py ../../third_party/catapult/devil/devil/utils/timeout_retry.py ../../third_party/catapult/devil/devil/utils/watchdog_timer.py ../../third_party/catapult/devil/devil/utils/zip_utils.py
diff --git a/chrome/android/java/res/layout/most_visited_item.xml b/chrome/android/java/res/layout/most_visited_item.xml index cb036156..56e5ec9f 100644 --- a/chrome/android/java/res/layout/most_visited_item.xml +++ b/chrome/android/java/res/layout/most_visited_item.xml
@@ -29,7 +29,7 @@ android:visibility="gone" android:background="@drawable/offline_badge_background" android:contentDescription="@null" - chrome:tint="#4285f4" + chrome:tint="@color/most_visited_offline_badge_tint" android:src="@drawable/offline_bolt" /> <View @@ -49,7 +49,7 @@ android:gravity="center_horizontal" android:lines="2" android:lineSpacingMultiplier="1.17" - android:textColor="#787878" + android:textColor="@color/most_visited_text" android:textSize="12sp" /> </org.chromium.chrome.browser.ntp.MostVisitedItemView>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index ecdd61e..bb238f4d 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -112,6 +112,10 @@ <color name="snippets_list_header_text_color">#646464</color> <color name="snippets_headline_text_color">#333333</color> + <!-- Most Visited colors. --> + <color name="most_visited_text">#6f6f6f</color> + <color name="most_visited_offline_badge_tint">#4285f4</color> + <!-- Contextual Search colors --> <color name="contextual_search_promo_text_color">#333333</color> <color name="contextual_search_promo_background_color">#EEEEEE</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index f42bb67..09988fb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -30,6 +30,7 @@ import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.WebContents; import org.chromium.mojo.system.MojoException; +import org.chromium.mojom.payments.PaymentComplete; import org.chromium.mojom.payments.PaymentDetails; import org.chromium.mojom.payments.PaymentItem; import org.chromium.mojom.payments.PaymentMethodData; @@ -605,8 +606,8 @@ * Called when the merchant website has processed the payment. */ @Override - public void complete(boolean success) { - closeUI(success); + public void complete(int result) { + closeUI(PaymentComplete.FAIL != result); } /** @@ -699,9 +700,9 @@ /** * Closes the UI. If the client is still connected, then it's notified of UI hiding. */ - private void closeUI(boolean paymentSuccess) { + private void closeUI(boolean immediateClose) { if (mUI != null) { - mUI.close(paymentSuccess, new Runnable() { + mUI.close(immediateClose, new Runnable() { @Override public void run() { if (mClient != null) mClient.onComplete();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index ef8b5cb..8a972b23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -398,12 +398,13 @@ * * Should not be called multiple times. * - * @param paymentSuccess Whether the payment (if any) was successful. + * @param shouldCloseImmediately If true, this function will immediately dismiss the dialog + * without describing the error. * @param callback The callback to notify of finished animations. */ - public void close(boolean paymentSuccess, final Runnable callback) { + public void close(boolean shouldCloseImmediately, final Runnable callback) { mIsClientClosing = true; - mResultView.update(paymentSuccess, new Runnable() { + mResultView.update(shouldCloseImmediately, new Runnable() { @Override public void run() { dismissDialog(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentResultUIManager.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentResultUIManager.java index ebb171d..2ec9a11 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentResultUIManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentResultUIManager.java
@@ -63,12 +63,15 @@ /** * Updates the UI to display whether or not the payment request was successful. * - * @param paymentSuccess Whether or not the payment request was successful. - * @param callback Callback to run upon dismissal. + * @param shouldCloseImmediately If true, this function will immediately dismiss the dialog + * without describing the error. + * @param callback Callback to run upon dismissal. */ - public void update(boolean paymentSuccess, final Runnable callback) { - if (mResultLayout.getParent() == null || paymentSuccess) { - // Dismiss the dialog immediately. + public void update(boolean shouldCloseImmediately, final Runnable callback) { + if (mResultLayout.getParent() == null || shouldCloseImmediately) { + // The shouldCloseImmediately boolean is true when the merchant calls + // instrumentResponse.complete("success") or instrumentResponse.complete("") + // in JavaScript. callback.run(); } else { // Describe the error.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmImportSyncDataDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmImportSyncDataDialog.java index 50c850c..24d2336a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmImportSyncDataDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/ConfirmImportSyncDataDialog.java
@@ -106,6 +106,11 @@ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + // If the dialog is being recreated it won't have the listener set and so won't be + // functional. Therefore we dismiss, and the user will need to open the dialog again. + if (savedInstanceState != null) { + dismiss(); + } String oldAccountName = getArguments().getString(KEY_OLD_ACCOUNT_NAME); String newAccountName = getArguments().getString(KEY_NEW_ACCOUNT_NAME); ImportSyncType importSyncType =
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 45de8fe..e966ebd 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2008,6 +2008,12 @@ switches::kDisableFeatures); } +void RegisterAllFeatureVariationParameters( + flags_ui::FlagsStorage* flags_storage) { + FlagsStateSingleton::GetFlagsState()->RegisterAllFeatureVariationParameters( + flags_storage); +} + bool AreSwitchesIdenticalToCurrentCommandLine( const base::CommandLine& new_cmdline, const base::CommandLine& active_cmdline,
diff --git a/chrome/browser/about_flags.h b/chrome/browser/about_flags.h index c7d6a8e..91917421 100644 --- a/chrome/browser/about_flags.h +++ b/chrome/browser/about_flags.h
@@ -34,6 +34,11 @@ base::CommandLine* command_line, flags_ui::SentinelsMode sentinels); +// Registers variations parameter values stored in |flags_storage| (previously +// selected in about:flags). +void RegisterAllFeatureVariationParameters( + flags_ui::FlagsStorage* flags_storage); + // Compares a set of switches of the two provided command line objects and // returns true if they are the same and false otherwise. // If |out_difference| is not NULL, it's filled with set_symmetric_difference
diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc index 416c01f..3863e6c1 100644 --- a/chrome/browser/about_flags_unittest.cc +++ b/chrome/browser/about_flags_unittest.cc
@@ -168,7 +168,8 @@ } // Get all associated switches corresponding to defined about_flags.cc entries. -// Does not include information about FEATURE_VALUE entries. +// Does not include information about FEATURE_VALUE or +// FEATURE_WITH_VARIATIOSN_VALUE entries. std::set<std::string> GetAllSwitchesForTesting() { std::set<std::string> result; @@ -184,8 +185,8 @@ result.insert(entry.command_line_switch); break; case flags_ui::FeatureEntry::MULTI_VALUE: - for (int j = 0; j < entry.num_choices; ++j) { - result.insert(entry.choices[j].command_line_switch); + for (int j = 0; j < entry.num_options; ++j) { + result.insert(entry.ChoiceForOption(j).command_line_switch); } break; case flags_ui::FeatureEntry::ENABLE_DISABLE_VALUE: @@ -193,6 +194,7 @@ result.insert(entry.disable_command_line_switch); break; case flags_ui::FeatureEntry::FEATURE_VALUE: + case flags_ui::FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: break; } }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 3d200cec..c64ee2e1 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -720,6 +720,11 @@ metrics->AddSyntheticTrialObserver(provider); } + // Associate parameters chosen in about:flags and create trial/group for them. + flags_ui::PrefServiceFlagsStorage flags_storage( + g_browser_process->local_state()); + about_flags::RegisterAllFeatureVariationParameters(&flags_storage); + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); feature_list->InitializeFromCommandLine( command_line->GetSwitchValueASCII(switches::kEnableFeatures), @@ -972,9 +977,9 @@ { TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreadsImpl:ConvertFlags"); - flags_ui::PrefServiceFlagsStorage flags_storage_( + flags_ui::PrefServiceFlagsStorage flags_storage( g_browser_process->local_state()); - about_flags::ConvertFlagsToSwitches(&flags_storage_, + about_flags::ConvertFlagsToSwitches(&flags_storage, base::CommandLine::ForCurrentProcess(), flags_ui::kAddSentinels); }
diff --git a/chrome/browser/chrome_webusb_browser_client.cc b/chrome/browser/chrome_webusb_browser_client.cc index b966ace..187cd71 100644 --- a/chrome/browser/chrome_webusb_browser_client.cc +++ b/chrome/browser/chrome_webusb_browser_client.cc
@@ -6,7 +6,7 @@ #include <utility> -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chromeos/arc/OWNERS b/chrome/browser/chromeos/arc/OWNERS index 2797e0d..d7d81e7 100644 --- a/chrome/browser/chromeos/arc/OWNERS +++ b/chrome/browser/chromeos/arc/OWNERS
@@ -1,3 +1,4 @@ -yusukes@chromium.org +elijahtaylor@chromium.org hidehiko@chromium.org lhchavez@chromium.org +yusukes@chromium.org
diff --git a/chrome/browser/chromeos/arc/arc_auth_notification.cc b/chrome/browser/chromeos/arc/arc_auth_notification.cc index 98e7135..1617cf4 100644 --- a/chrome/browser/chromeos/arc/arc_auth_notification.cc +++ b/chrome/browser/chromeos/arc/arc_auth_notification.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/arc/arc_auth_notification.h" -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/arc/arc_auth_service.h"
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc new file mode 100644 index 0000000..1ed4915 --- /dev/null +++ b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
@@ -0,0 +1,192 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/arc/arc_navigation_throttle.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "components/arc/arc_bridge_service.h" +#include "components/arc/arc_service_manager.h" +#include "components/arc/intent_helper/arc_intent_helper_bridge.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_handle.h" + +namespace arc { + +namespace { + +constexpr int kMinInstanceVersion = 7; + +scoped_refptr<ActivityIconLoader> GetIconLoader() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + ArcServiceManager* arc_service_manager = ArcServiceManager::Get(); + if (!arc_service_manager) + return nullptr; + return arc_service_manager->icon_loader(); +} + +mojom::IntentHelperInstance* GetIntentHelper() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + ArcBridgeService* bridge_service = ArcBridgeService::Get(); + if (!bridge_service) { + VLOG(1) << "ARC bridge is not ready."; + return nullptr; + } + mojom::IntentHelperInstance* intent_helper_instance = + bridge_service->intent_helper_instance(); + if (!intent_helper_instance) { + VLOG(1) << "ARC intent helper instance is not ready."; + return nullptr; + } + if (bridge_service->intent_helper_version() < kMinInstanceVersion) { + VLOG(1) << "ARC intent helper instance is too old."; + return nullptr; + } + return intent_helper_instance; +} + +} // namespace + +ArcNavigationThrottle::ArcNavigationThrottle( + content::NavigationHandle* navigation_handle, + const ShowDisambigDialogCallback& show_disambig_dialog_cb) + : content::NavigationThrottle(navigation_handle), + show_disambig_dialog_callback_(show_disambig_dialog_cb), + weak_ptr_factory_(this) {} + +ArcNavigationThrottle::~ArcNavigationThrottle() = default; + +content::NavigationThrottle::ThrottleCheckResult +ArcNavigationThrottle::WillStartRequest() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!navigation_handle()->HasUserGesture()) + return content::NavigationThrottle::PROCEED; + + const GURL& url = navigation_handle()->GetURL(); + mojom::IntentHelperInstance* bridge_instance = GetIntentHelper(); + if (!bridge_instance) + return content::NavigationThrottle::PROCEED; + bridge_instance->RequestUrlHandlerList( + url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived, + weak_ptr_factory_.GetWeakPtr())); + return content::NavigationThrottle::DEFER; +} + +content::NavigationThrottle::ThrottleCheckResult +ArcNavigationThrottle::WillRedirectRequest() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return content::NavigationThrottle::PROCEED; +} + +// We received the array of app candidates to handle this URL (even the Chrome +// app is included). +void ArcNavigationThrottle::OnAppCandidatesReceived( + mojo::Array<mojom::UrlHandlerInfoPtr> handlers) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if ((handlers.size() == 1 && ArcIntentHelperBridge::IsIntentHelperPackage( + handlers[0]->package_name)) || + handlers.size() == 0) { + // This scenario shouldn't be accesed as ArcNavigationThrottle is created + // iff there are ARC apps which can actually handle the given URL. + DVLOG(1) << "There are no app candidates for this URL: " + << navigation_handle()->GetURL().spec(); + navigation_handle()->Resume(); + return; + } + + // If one of the apps is marked as preferred, use it right away without + // showing the UI. + for (size_t i = 0; i < handlers.size(); ++i) { + if (!handlers[i]->is_preferred) + continue; + if (ArcIntentHelperBridge::IsIntentHelperPackage( + handlers[i]->package_name)) { + // If Chrome browser was selected as the preferred app, we should't + // create a throttle. + DVLOG(1) + << "Chrome browser is selected as the preferred app for this URL: " + << navigation_handle()->GetURL().spec(); + } + OnDisambigDialogClosed(std::move(handlers), i, false); + return; + } + + scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader(); + if (!icon_loader) { + LOG(ERROR) << "Cannot get an instance of ActivityIconLoader"; + navigation_handle()->Resume(); + return; + } + std::vector<ActivityIconLoader::ActivityName> activities; + for (const auto& handler : handlers) { + activities.emplace_back(handler->package_name, handler->activity_name); + } + icon_loader->GetActivityIcons( + activities, + base::Bind(&ArcNavigationThrottle::OnAppIconsReceived, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers))); +} + +void ArcNavigationThrottle::OnAppIconsReceived( + mojo::Array<mojom::UrlHandlerInfoPtr> handlers, + std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::vector<NameAndIcon> app_info; + + for (const auto& handler : handlers) { + gfx::Image icon; + const ActivityIconLoader::ActivityName activity(handler->package_name, + handler->activity_name); + const auto it = icons->find(activity); + + if (it != icons->end()) { + app_info.emplace_back(handler->name, it->second.icon20); + } else { + app_info.emplace_back(handler->name, gfx::Image()); + } + } + + show_disambig_dialog_callback_.Run( + navigation_handle(), app_info, + base::Bind(&ArcNavigationThrottle::OnDisambigDialogClosed, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers))); +} + +void ArcNavigationThrottle::OnDisambigDialogClosed( + mojo::Array<mojom::UrlHandlerInfoPtr> handlers, + size_t selected_app_index, + bool always) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + const GURL& url = navigation_handle()->GetURL(); + content::NavigationHandle* handle = navigation_handle(); + + // TODO(djacobo): Record UMA + // If the user fails to select an option from the list then resume the + // navigation in Chrome. Otherwise check if the selected app was selected as + // "ALWAYS" so we can record this decision. + if (selected_app_index >= handlers.size()) { + DVLOG(1) << "User didn't select a valid option, resuming navigation."; + handle->Resume(); + return; + } + mojom::IntentHelperInstance* bridge = GetIntentHelper(); + if (!bridge) { + handle->Resume(); + return; + } + if (always) { + bridge->AddPreferredPackage(handlers[selected_app_index]->package_name); + } + if (ArcIntentHelperBridge::IsIntentHelperPackage( + handlers[selected_app_index]->package_name)) { + handle->Resume(); + return; + } + bridge->HandleUrl(url.spec(), handlers[selected_app_index]->package_name); + handle->CancelDeferredNavigation( + content::NavigationThrottle::CANCEL_AND_IGNORE); +} + +} // namespace arc
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.h b/chrome/browser/chromeos/arc/arc_navigation_throttle.h new file mode 100644 index 0000000..b2ab0cb --- /dev/null +++ b/chrome/browser/chromeos/arc/arc_navigation_throttle.h
@@ -0,0 +1,64 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_ARC_ARC_NAVIGATION_THROTTLE_H_ +#define CHROME_BROWSER_CHROMEOS_ARC_ARC_NAVIGATION_THROTTLE_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/arc/intent_helper/activity_icon_loader.h" +#include "content/public/browser/navigation_throttle.h" +#include "ui/gfx/image/image.h" + +namespace content { +class NavigationHandle; +} // namespace content + +namespace arc { + +// A class that allow us to retrieve ARC app's information and handle URL +// traffic initiated on Chrome browser, either on Chrome or an ARC's app. +class ArcNavigationThrottle : public content::NavigationThrottle { + public: + using NameAndIcon = std::pair<std::string, gfx::Image>; + using ShowDisambigDialogCallback = + base::Callback<void(content::NavigationHandle* handle, + const std::vector<NameAndIcon>& app_info, + const base::Callback<void(size_t, bool)>& cb)>; + ArcNavigationThrottle( + content::NavigationHandle* navigation_handle, + const ShowDisambigDialogCallback& show_disambig_dialog_cb); + ~ArcNavigationThrottle() override; + + private: + // content::Navigation implementation: + NavigationThrottle::ThrottleCheckResult WillStartRequest() override; + NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override; + + void OnAppCandidatesReceived(mojo::Array<mojom::UrlHandlerInfoPtr> handlers); + void OnAppIconsReceived( + mojo::Array<mojom::UrlHandlerInfoPtr> handlers, + std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons); + void OnDisambigDialogClosed(mojo::Array<mojom::UrlHandlerInfoPtr> handlers, + size_t selected_app_index, + bool always); + + // A callback object that allow us to display an IntentPicker when Run() is + // executed, it also allow us to report the user's selection back to + // OnDisambigDialogClosed(). + ShowDisambigDialogCallback show_disambig_dialog_callback_; + + base::WeakPtrFactory<ArcNavigationThrottle> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ArcNavigationThrottle); +}; + +} // namespace arc + +#endif // CHROME_BROWSER_CHROMEOS_ARC_ARC_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/chromeos/arc/arc_support_host.cc b/chrome/browser/chromeos/arc/arc_support_host.cc index 68c02fe..25c8cc01 100644 --- a/chrome/browser/chromeos/arc/arc_support_host.cc +++ b/chrome/browser/chromeos/arc/arc_support_host.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/arc/arc_support_host.h" -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/i18n/timezone.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h"
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller.cc b/chrome/browser/chromeos/hats/hats_notification_controller.cc index edf6000e2..fc2dc29 100644 --- a/chrome/browser/chromeos/hats/hats_notification_controller.cc +++ b/chrome/browser/chromeos/hats/hats_notification_controller.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/hats/hats_notification_controller.h" -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "base/feature_list.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/chromeos/net/network_portal_notification_controller.cc b/chrome/browser/chromeos/net/network_portal_notification_controller.cc index 0080161..f90253f4 100644 --- a/chrome/browser/chromeos/net/network_portal_notification_controller.cc +++ b/chrome/browser/chromeos/net/network_portal_notification_controller.cc
@@ -9,8 +9,8 @@ #include <memory> #include <vector> +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "ash/system/tray/system_tray_notifier.h" #include "base/command_line.h" #include "base/compiler_specific.h"
diff --git a/chrome/browser/chromeos/status/data_promo_notification.cc b/chrome/browser/chromeos/status/data_promo_notification.cc index 8b177bc..c50a0ed 100644 --- a/chrome/browser/chromeos/status/data_promo_notification.cc +++ b/chrome/browser/chromeos/status/data_promo_notification.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/status/data_promo_notification.h" -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc index 37a0da2..f00088f 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -53,7 +53,7 @@ #include "ui/gfx/range/range.h" #if defined(OS_CHROMEOS) -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h" #include "components/user_manager/user.h"
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc index ac98050..6b87899 100644 --- a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc +++ b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
@@ -30,7 +30,7 @@ #include "ui/base/webui/web_ui_util.h" #if defined(OS_CHROMEOS) -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #endif namespace extensions {
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 5fbc12ec6..2a6c428 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -47,7 +47,7 @@ #include "ui/base/resource/resource_bundle.h" #if defined(OS_CHROMEOS) -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "components/chrome_apps/grit/chrome_apps_resources.h" #include "components/user_manager/user_manager.h" #include "grit/keyboard_resources.h"
diff --git a/chrome/browser/extensions/extension_fullscreen_apitest.cc b/chrome/browser/extensions/extension_fullscreen_apitest.cc index 84de0a4f..57b2d428 100644 --- a/chrome/browser/extensions/extension_fullscreen_apitest.cc +++ b/chrome/browser/extensions/extension_fullscreen_apitest.cc
@@ -30,8 +30,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FocusWindowDoesNotExitFullscreen) { browser()->exclusive_access_manager()->context()->EnterFullscreen( - GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - false); + GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION); ASSERT_TRUE(browser()->window()->IsFullscreen()); ASSERT_TRUE(RunExtensionTest("window_update/focus")) << message_; ASSERT_TRUE(browser()->window()->IsFullscreen()); @@ -47,8 +46,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_UpdateWindowSizeExitsFullscreen) { browser()->exclusive_access_manager()->context()->EnterFullscreen( - GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - false); + GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION); ASSERT_TRUE(RunExtensionTest("window_update/sizing")) << message_; ASSERT_FALSE(browser()->window()->IsFullscreen()); }
diff --git a/chrome/browser/google/google_update_win.cc b/chrome/browser/google/google_update_win.cc index 238ce58b..02706b0 100644 --- a/chrome/browser/google/google_update_win.cc +++ b/chrome/browser/google/google_update_win.cc
@@ -234,7 +234,9 @@ void BeginUpdateCheck(); // Returns the result of initiating an update check. Sets |error_code| if the - // result is any kind of failure. + // result is any kind of failure. On failure, the instance is left in a + // consistent state so that this method can be invoked later to retry the + // steps that failed. HRESULT BeginUpdateCheckInternal(GoogleUpdateErrorCode* error_code); // Sets status_ to UPGRADE_ERROR, error_code_ to |error_code|, hresult_ to @@ -448,85 +450,125 @@ task_runner_->PostTask(FROM_HERE, base::Bind(&UpdateCheckDriver::PollGoogleUpdate, base::Unretained(this))); - } else { - // Return results immediately since the driver is not polling Google Update. - OnUpgradeError(error_code, hresult, -1, base::string16()); - result_runner_->DeleteSoon(FROM_HERE, this); + return; } + if (hresult == GOOPDATE_E_APP_USING_EXTERNAL_UPDATER) { + // This particular transient error is worth retrying. + if (allowed_retries_) { + --allowed_retries_; + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(&UpdateCheckDriver::BeginUpdateCheck, + base::Unretained(this)), + base::TimeDelta::FromSeconds(kGoogleRetryIntervalSeconds)); + return; + } + } + + DCHECK(FAILED(hresult)); + // Return results immediately since the driver is not polling Google Update. + OnUpgradeError(error_code, hresult, -1, base::string16()); + result_runner_->DeleteSoon(FROM_HERE, this); } HRESULT UpdateCheckDriver::BeginUpdateCheckInternal( GoogleUpdateErrorCode* error_code) { - base::FilePath chrome_exe; - if (!PathService::Get(base::DIR_EXE, &chrome_exe)) - NOTREACHED(); + HRESULT hresult = S_OK; + // Instantiate GoogleUpdate3Web{Machine,User}Class. + if (!google_update_) { + base::FilePath chrome_exe; + if (!PathService::Get(base::DIR_EXE, &chrome_exe)) + NOTREACHED(); - system_level_install_ = !InstallUtil::IsPerUserInstall(chrome_exe); + system_level_install_ = !InstallUtil::IsPerUserInstall(chrome_exe); - // Make sure ATL is initialized in this module. - ui::win::CreateATLModuleIfNeeded(); + // Make sure ATL is initialized in this module. + ui::win::CreateATLModuleIfNeeded(); - *error_code = CanUpdateCurrentChrome(chrome_exe, system_level_install_); - if (*error_code != GOOGLE_UPDATE_NO_ERROR) - return E_FAIL; + *error_code = CanUpdateCurrentChrome(chrome_exe, system_level_install_); + if (*error_code != GOOGLE_UPDATE_NO_ERROR) + return E_FAIL; - HRESULT hresult = CreateGoogleUpdate3WebClass( - system_level_install_, install_update_if_possible_, elevation_window_, - &google_update_); - if (FAILED(hresult)) { - *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; - return hresult; + hresult = CreateGoogleUpdate3WebClass(system_level_install_, + install_update_if_possible_, + elevation_window_, &google_update_); + if (FAILED(hresult)) { + *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND; + return hresult; + } + + ConfigureProxyBlanket(google_update_.get()); } - ConfigureProxyBlanket(google_update_.get()); - // The class was created, so all subsequent errors are reported as: *error_code = GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR; - base::string16 app_guid = - installer::GetAppGuidForUpdates(system_level_install_); - DCHECK(!app_guid.empty()); - { + // Create an app bundle. + if (!app_bundle_) { + base::win::ScopedComPtr<IAppBundleWeb> app_bundle; base::win::ScopedComPtr<IDispatch> dispatch; hresult = google_update_->createAppBundleWeb(dispatch.Receive()); if (FAILED(hresult)) return hresult; - hresult = dispatch.QueryInterface(app_bundle_.Receive()); + hresult = dispatch.QueryInterface(app_bundle.Receive()); if (FAILED(hresult)) return hresult; - } - ConfigureProxyBlanket(app_bundle_.get()); + dispatch.Release(); - if (!locale_.empty()) { - // Ignore the result of this since, while setting the display language is - // nice to have, a failure to do so does not affect the likelihood that the - // update check and/or install will succeed. - app_bundle_->put_displayLanguage( - base::win::ScopedBstr(base::UTF8ToUTF16(locale_).c_str())); + ConfigureProxyBlanket(app_bundle.get()); + + if (!locale_.empty()) { + // Ignore the result of this since, while setting the display language is + // nice to have, a failure to do so does not affect the likelihood that + // the update check and/or install will succeed. + app_bundle->put_displayLanguage( + base::win::ScopedBstr(base::UTF8ToUTF16(locale_).c_str())); + } + + hresult = app_bundle->initialize(); + if (FAILED(hresult)) + return hresult; + if (elevation_window_) { + // Likewise, a failure to set the parent window need not block an update + // check. + app_bundle->put_parentHWND( + reinterpret_cast<ULONG_PTR>(elevation_window_)); + } + app_bundle_.swap(app_bundle); } - hresult = app_bundle_->initialize(); - if (FAILED(hresult)) - return hresult; - if (elevation_window_) { - // Likewise, a failure to set the parent window need not block an update - // check. - app_bundle_->put_parentHWND(reinterpret_cast<ULONG_PTR>(elevation_window_)); + // Get a reference to the Chrome app in the bundle. + if (!app_) { + base::string16 app_guid = + installer::GetAppGuidForUpdates(system_level_install_); + DCHECK(!app_guid.empty()); + + base::win::ScopedComPtr<IDispatch> dispatch; + // It is common for this call to fail with APP_USING_EXTERNAL_UPDATER if + // an auto update is in progress. + hresult = app_bundle_->createInstalledApp( + base::win::ScopedBstr(app_guid.c_str())); + if (FAILED(hresult)) + return hresult; + // Move the IAppBundleWeb reference into a local now so that failures from + // this point onward result in it being released. + base::win::ScopedComPtr<IAppBundleWeb> app_bundle; + app_bundle.swap(app_bundle_); + hresult = app_bundle->get_appWeb(0, dispatch.Receive()); + if (FAILED(hresult)) + return hresult; + base::win::ScopedComPtr<IAppWeb> app; + hresult = dispatch.QueryInterface(app.Receive()); + if (FAILED(hresult)) + return hresult; + ConfigureProxyBlanket(app.get()); + hresult = app_bundle->checkForUpdate(); + if (FAILED(hresult)) + return hresult; + app_bundle_.swap(app_bundle); + app_.swap(app); } - base::win::ScopedComPtr<IDispatch> dispatch; - hresult = - app_bundle_->createInstalledApp(base::win::ScopedBstr(app_guid.c_str())); - if (FAILED(hresult)) - return hresult; - hresult = app_bundle_->get_appWeb(0, dispatch.Receive()); - if (FAILED(hresult)) - return hresult; - hresult = dispatch.QueryInterface(app_.Receive()); - if (FAILED(hresult)) - return hresult; - ConfigureProxyBlanket(app_.get()); - return app_bundle_->checkForUpdate(); + return hresult; } bool UpdateCheckDriver::GetCurrentState( @@ -722,19 +764,6 @@ base::string16()); } else if (IsErrorState(state, state_value, &error_code, &hresult, &installer_exit_code, &error_string)) { - // Some errors can be transient. Retry them after a short delay. - if (hresult == GOOPDATE_E_APP_USING_EXTERNAL_UPDATER) { - if (allowed_retries_ > 0) { - --allowed_retries_; - app_bundle_.Release(); - google_update_.Release(); - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&UpdateCheckDriver::BeginUpdateCheck, - base::Unretained(this)), - base::TimeDelta::FromSeconds(kGoogleRetryIntervalSeconds)); - return; - } - } OnUpgradeError(error_code, hresult, installer_exit_code, error_string); } else if (IsFinalState(state, state_value, &upgrade_status, &new_version)) { status_ = upgrade_status;
diff --git a/chrome/browser/google/google_update_win_unittest.cc b/chrome/browser/google/google_update_win_unittest.cc index 5bbe4b7..325a634f0 100644 --- a/chrome/browser/google/google_update_win_unittest.cc +++ b/chrome/browser/google/google_update_win_unittest.cc
@@ -914,40 +914,36 @@ TEST_P(GoogleUpdateWinTest, RetryAfterExternalUpdaterError) { static const HRESULT GOOPDATE_E_APP_USING_EXTERNAL_UPDATER = 0xa043081d; - CComObject<MockAppBundle>* mock_app_bundle1 = + CComObject<MockAppBundle>* mock_app_bundle = mock_google_update_factory_.MakeServerMock()->MakeAppBundle(); // The first attempt will fail in createInstalledApp indicating that an update // is already in progress. - EXPECT_CALL(*mock_app_bundle1, createInstalledApp(StrEq(kChromeBinariesGuid))) + Sequence bundle_seq; + EXPECT_CALL(*mock_app_bundle, createInstalledApp(StrEq(kChromeBinariesGuid))) + .InSequence(bundle_seq) .WillOnce(Return(GOOPDATE_E_APP_USING_EXTERNAL_UPDATER)); - // Retry with a second instance. - CComObject<MockAppBundle>* mock_app_bundle2 = nullptr; + // Expect a retry on the same instance. + EXPECT_CALL(*mock_app_bundle, createInstalledApp(StrEq(kChromeBinariesGuid))) + .InSequence(bundle_seq) + .WillOnce(Return(S_OK)); + + // See MakeApp() for an explanation of this: CComObject<MockApp>* mock_app = nullptr; - MakeGoogleUpdateMocks(&mock_app_bundle2, &mock_app); + EXPECT_EQ(S_OK, CComObject<MockApp>::CreateInstance(&mock_app)); + mock_app->AddRef(); + EXPECT_CALL(*mock_app_bundle, get_appWeb(0, _)) + .WillOnce(DoAll(SetArgPointee<1>(mock_app), Return(S_OK))); // Expect the bundle to be called on to start the update. - EXPECT_CALL(*mock_app_bundle2, checkForUpdate()) - .WillOnce(Return(S_OK)); + EXPECT_CALL(*mock_app_bundle, checkForUpdate()).WillOnce(Return(S_OK)); mock_app->PushState(STATE_INIT); mock_app->PushState(STATE_CHECKING_FOR_UPDATE); mock_app->PushState(STATE_NO_UPDATE); - // Until http://crbug.com/504516 is fixed, we expect the first update check - // to fail. - EXPECT_CALL(mock_update_check_delegate_, - OnError(GOOGLE_UPDATE_ONDEMAND_CLASS_REPORTED_ERROR, _, _)); - - // Run the first update check. When http://crbug.com/504516 is fixed, this - // update check will be subsumed in the one below. - BeginUpdateCheck(task_runner_, std::string(), true, 0, - mock_update_check_delegate_.AsWeakPtr()); - task_runner_->RunUntilIdle(); - - // Expect a second update check to succeed. When http://crbug.com/504516 is - // fixed, this will be the one and only update check. + // Expect the update check to succeed. EXPECT_CALL(mock_update_check_delegate_, OnUpdateCheckComplete(IsEmpty())); // new_version BeginUpdateCheck(task_runner_, std::string(), false, 0,
diff --git a/chrome/browser/media/DEPS b/chrome/browser/media/DEPS index 30abf7d6..dcd73c70 100644 --- a/chrome/browser/media/DEPS +++ b/chrome/browser/media/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+device/power_save_blocker", "+media/audio", "+media/base", "+media/cast",
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc index 49d8fd1..87080587 100644 --- a/chrome/browser/media/cast_transport_host_filter.cc +++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -9,7 +9,8 @@ #include "chrome/browser/browser_process.h" #include "chrome/common/cast_messages.h" #include "components/net_log/chrome_net_log.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/public/browser/browser_thread.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "media/cast/net/cast_transport.h" namespace { @@ -148,10 +149,14 @@ if (!power_save_blocker_) { DVLOG(1) << ("Preventing the application from being suspended while one or " "more transports are active for Cast Streaming."); - power_save_blocker_ = content::CreatePowerSaveBlocker( - content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - content::PowerSaveBlocker::kReasonOther, - "Cast is streaming content to a remote receiver"); + power_save_blocker_ = device::PowerSaveBlocker::CreateWithTaskRunners( + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, + "Cast is streaming content to a remote receiver", + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE)); } if (id_map_.Lookup(channel_id)) {
diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h index ad9818e0..fefde8b 100644 --- a/chrome/browser/media/cast_transport_host_filter.h +++ b/chrome/browser/media/cast_transport_host_filter.h
@@ -19,9 +19,9 @@ #include "media/cast/net/cast_transport.h" #include "media/cast/net/udp_transport.h" -namespace content { +namespace device { class PowerSaveBlocker; -} // namespace content +} // namespace device namespace cast { @@ -91,9 +91,9 @@ base::DefaultTickClock clock_; // While |id_map_| is non-empty, hold an instance of - // content::PowerSaveBlocker. This prevents Chrome from being suspended while + // device::PowerSaveBlocker. This prevents Chrome from being suspended while // remoting content. - std::unique_ptr<content::PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; base::WeakPtrFactory<CastTransportHostFilter> weak_factory_;
diff --git a/chrome/browser/notifications/fullscreen_notification_blocker.cc b/chrome/browser/notifications/fullscreen_notification_blocker.cc index c9831fc..a0c0a7b 100644 --- a/chrome/browser/notifications/fullscreen_notification_blocker.cc +++ b/chrome/browser/notifications/fullscreen_notification_blocker.cc
@@ -10,10 +10,10 @@ #include "content/public/browser/notification_service.h" #if defined(USE_ASH) +#include "ash/common/system/system_notifier.h" #include "ash/common/wm/window_state.h" #include "ash/root_window_controller.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "ash/wm/window_state_aura.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h"
diff --git a/chrome/browser/notifications/login_state_notification_blocker_chromeos.cc b/chrome/browser/notifications/login_state_notification_blocker_chromeos.cc index 6cd5fdb8..1caad4b 100644 --- a/chrome/browser/notifications/login_state_notification_blocker_chromeos.cc +++ b/chrome/browser/notifications/login_state_notification_blocker_chromeos.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/notifications/login_state_notification_blocker_chromeos.h" +#include "ash/common/system/system_notifier.h" #include "ash/common/wm_shell.h" #include "ash/root_window_controller.h" -#include "ash/system/system_notifier.h" #include "ash/wm/window_properties.h" #include "chrome/browser/chrome_notification_types.h" #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/notifications/login_state_notification_blocker_chromeos_browsertest.cc b/chrome/browser/notifications/login_state_notification_blocker_chromeos_browsertest.cc index 92cc81f..bd7b90d 100644 --- a/chrome/browser/notifications/login_state_notification_blocker_chromeos_browsertest.cc +++ b/chrome/browser/notifications/login_state_notification_blocker_chromeos_browsertest.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "base/command_line.h" #include "base/macros.h" #include "chrome/browser/chromeos/login/login_manager_test.h"
diff --git a/chrome/browser/notifications/login_state_notification_blocker_chromeos_unittest.cc b/chrome/browser/notifications/login_state_notification_blocker_chromeos_unittest.cc index dd52c0c..b5d3a1f 100644 --- a/chrome/browser/notifications/login_state_notification_blocker_chromeos_unittest.cc +++ b/chrome/browser/notifications/login_state_notification_blocker_chromeos_unittest.cc
@@ -6,8 +6,8 @@ #include <memory> +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "ash/test/ash_test_base.h" #include "base/command_line.h" #include "base/macros.h"
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc index 1e0dc01..8de630e 100644 --- a/chrome/browser/notifications/message_center_settings_controller.cc +++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -47,7 +47,7 @@ #include "ui/strings/grit/ui_strings.h" #if defined(OS_CHROMEOS) -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/notifications/arc_notifier_manager.h" #include "components/arc/arc_bridge_service.h"
diff --git a/chrome/browser/notifications/message_center_settings_controller_unittest.cc b/chrome/browser/notifications/message_center_settings_controller_unittest.cc index aed37ce..ea47722 100644 --- a/chrome/browser/notifications/message_center_settings_controller_unittest.cc +++ b/chrome/browser/notifications/message_center_settings_controller_unittest.cc
@@ -26,7 +26,7 @@ #include "ui/message_center/notifier_settings.h" #if defined(OS_CHROMEOS) -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #endif
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc index ad28739..0783595 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc +++ b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
@@ -10,6 +10,7 @@ #include "base/memory/singleton.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/suggestions/image_decoder_impl.h" #include "chrome/browser/search/suggestions/image_fetcher_impl.h" #include "chrome/browser/search/suggestions/suggestions_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" @@ -18,6 +19,7 @@ #include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" #include "components/browser_sync/browser/profile_sync_service.h" +#include "components/image_fetcher/image_decoder.h" #include "components/image_fetcher/image_fetcher.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/ntp_snippets/ntp_snippets_constants.h" @@ -41,6 +43,7 @@ #endif // OS_ANDROID using content::BrowserThread; +using suggestions::ImageDecoderImpl; using suggestions::ImageFetcherImpl; using suggestions::SuggestionsService; using suggestions::SuggestionsServiceFactory; @@ -115,6 +118,7 @@ base::Bind(&safe_json::SafeJsonParser::Parse), chrome::GetChannel() == version_info::Channel::STABLE)), base::WrapUnique(new ImageFetcherImpl(request_context.get())), + base::WrapUnique(new ImageDecoderImpl()), base::WrapUnique( new ntp_snippets::NTPSnippetsDatabase(database_dir, task_runner))); }
diff --git a/chrome/browser/resources/chromeos/arc_support/background.js b/chrome/browser/resources/chromeos/arc_support/background.js index 4b6e9ad..29ca078 100644 --- a/chrome/browser/resources/chromeos/arc_support/background.js +++ b/chrome/browser/resources/chromeos/arc_support/background.js
@@ -127,7 +127,7 @@ }; var onLearnMore = function(event) { - var url = 'https://support.google.com/chrome/answer/96817'; + var url = 'https://support.google.com/chromebook?p=playapps'; chrome.browser.openTab({'url': url}, function() {}); event.preventDefault(); };
diff --git a/chrome/browser/search/suggestions/image_fetcher_impl.cc b/chrome/browser/search/suggestions/image_fetcher_impl.cc index f2173a1..9d046f0a 100644 --- a/chrome/browser/search/suggestions/image_fetcher_impl.cc +++ b/chrome/browser/search/suggestions/image_fetcher_impl.cc
@@ -63,8 +63,13 @@ void ImageFetcherImpl::OnImageURLFetched(const GURL& image_url, const std::string& image_data) { - // TODO(markusheintz): Add a method OnImageDataFetched on the delegate and - // call that here. + // Inform the ImageFetcherDelegate. + if (delegate_) { + auto it = pending_net_requests_.find(image_url); + DCHECK(it != pending_net_requests_.end()); + delegate_->OnImageDataFetched(it->second.id, image_data); + } + image_decoder_->DecodeImage( image_data, base::Bind(&ImageFetcherImpl::OnImageDecoded,
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc index ed7eee6..b632fab8 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
@@ -15,7 +15,7 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #endif using proximity_auth::ScreenlockState;
diff --git a/chrome/browser/signin/signin_error_notifier_ash.cc b/chrome/browser/signin/signin_error_notifier_ash.cc index 85e1b94..bb17d7f 100644 --- a/chrome/browser/signin/signin_error_notifier_ash.cc +++ b/chrome/browser/signin/signin_error_notifier_ash.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/signin/signin_error_notifier_ash.h" +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" #include "ash/shell_delegate.h" -#include "ash/system/system_notifier.h" #include "base/logging.h" #include "base/macros.h" #include "base/strings/string16.h"
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc index 4e4f3e2..02ca4d3 100644 --- a/chrome/browser/sync/sync_error_notifier_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/sync/sync_error_notifier_ash.h" +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" #include "ash/shell_delegate.h" -#include "ash/system/system_notifier.h" #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 861251a..a1078e6b 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -6,8 +6,8 @@ #include <stddef.h> +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "base/base64.h" #include "base/bind.h" #include "base/callback.h"
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.cc index c89b3ebd..b36a5df2 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h" -#include "ash/system/system_notifier.h" +#include "ash/common/system/system_notifier.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" #include "components/signin/core/account_id/account_id.h" #include "ui/message_center/message_center.h"
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc index 6eac3f3..2015efea9 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "ash/common/session/session_state_delegate.h" +#include "ash/common/system/system_notifier.h" #include "ash/shell.h" -#include "ash/system/system_notifier.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_session_state_delegate.h" #include "ash/test/test_shell_delegate.h"
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc index 8e5bfa4..32fed2c 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -16,6 +16,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/session/session_state_observer.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "ash/common/system/chromeos/shutdown_policy_observer.h" #include "ash/common/system/date/clock_observer.h" #include "ash/common/system/tray/system_tray_delegate.h" @@ -28,7 +29,6 @@ #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/system/chromeos/bluetooth/bluetooth_observer.h" -#include "ash/system/chromeos/power/power_status.h" #include "ash/system/chromeos/session/logout_button_observer.h" #include "ash/system/ime/ime_observer.h" #include "ash/system/tray/system_tray.h"
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 66004f92..959963b2 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2749,8 +2749,7 @@ CheckDisplayModeMQ(ASCIIToUTF16("standalone"), app_contents); app_browser->exclusive_access_manager()->context()->EnterFullscreen( - GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - false); + GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION); // Sync navigation just to make sure IPC has passed (updated // display mode is delivered to RP).
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 605d5457..d0d1d43a 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -415,11 +415,7 @@ ConvertPopupToTabbedBrowser(browser_); break; case IDC_FULLSCREEN: -#if defined(OS_MACOSX) - chrome::ToggleFullscreenWithToolbarOrFallback(browser_); -#else chrome::ToggleFullscreenMode(browser_); -#endif break; #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc index 0a5532d..4e6c5d58 100644 --- a/chrome/browser/ui/browser_command_controller_unittest.cc +++ b/chrome/browser/ui/browser_command_controller_unittest.cc
@@ -260,8 +260,7 @@ bool ShouldHideUIForFullscreen() const override { return fullscreen_; } bool IsFullscreen() const override { return fullscreen_; } void EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType type, - bool with_toolbar) override { + ExclusiveAccessBubbleType type) override { fullscreen_ = true; } void ExitFullscreen() override { fullscreen_ = false; }
diff --git a/chrome/browser/ui/browser_commands_mac.cc b/chrome/browser/ui/browser_commands_mac.cc index d286aa9..9c160b5 100644 --- a/chrome/browser/ui/browser_commands_mac.cc +++ b/chrome/browser/ui/browser_commands_mac.cc
@@ -14,16 +14,6 @@ namespace chrome { -void ToggleFullscreenWithToolbarOrFallback(Browser* browser) { - DCHECK(browser); - if (mac::SupportsSystemFullscreen()) - browser->exclusive_access_manager() - ->fullscreen_controller() - ->ToggleBrowserFullscreenWithToolbar(); - else - ToggleFullscreenMode(browser); -} - void ToggleFullscreenToolbar(Browser* browser) { DCHECK(browser);
diff --git a/chrome/browser/ui/browser_commands_mac.h b/chrome/browser/ui/browser_commands_mac.h index 5fac3c62..7e66d7a3 100644 --- a/chrome/browser/ui/browser_commands_mac.h +++ b/chrome/browser/ui/browser_commands_mac.h
@@ -9,10 +9,6 @@ namespace chrome { -// Enters Mac OSX 10.7 Lion Fullscreen mode, with browser chrome displayed. -// On earlier OSX versions, falls back to presentation mode. -void ToggleFullscreenWithToolbarOrFallback(Browser* browser); - // Toggles the visibility of the toolbar in fullscreen mode. void ToggleFullscreenToolbar(Browser* browser);
diff --git a/chrome/browser/ui/cocoa/applescript/scripting.sdef b/chrome/browser/ui/cocoa/applescript/scripting.sdef index 854330b..661890f 100644 --- a/chrome/browser/ui/cocoa/applescript/scripting.sdef +++ b/chrome/browser/ui/cocoa/applescript/scripting.sdef
@@ -263,17 +263,6 @@ <property name="URL" code="URL " description="The URL of the bookmark." type="text"/> <property name="index" code="indx" description="Returns the index with respect to its parent bookmark folder" type="number" access="r"/> </class> - <class-extension extends="window"> - <property name="presenting" code="pres" description="Whether the window is in presentation mode." type="boolean" access="r"> - <cocoa key="presenting"/> - </property> - <responds-to command="enter presentation mode"> - <cocoa method="handlesEnterPresentationMode:"/> - </responds-to> - <responds-to command="exit presentation mode"> - <cocoa method="handlesExitPresentationMode:"/> - </responds-to> - </class-extension> <command name="reload" code="CrSuRlod" description="Reload a tab."> <direct-parameter description="The tab to execute the command in." type="specifier"/> </command> @@ -314,11 +303,5 @@ </parameter> <result type="any"/> </command> - <command name="enter presentation mode" code="CrSuEnPM" description="Enter presentation mode in window."> - <direct-parameter description="The window to enter presentation mode." type="specifier"/> - </command> - <command name="exit presentation mode" code="CrSuExPM" description="Exit presentation mode in window."> - <direct-parameter description="The window to exit presentation mode." type="specifier"/> - </command> </suite> </dictionary> \ No newline at end of file
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.h b/chrome/browser/ui/cocoa/applescript/window_applescript.h index 9cfa5617..d1c28de 100644 --- a/chrome/browser/ui/cocoa/applescript/window_applescript.h +++ b/chrome/browser/ui/cocoa/applescript/window_applescript.h
@@ -76,15 +76,6 @@ // The index of the window, windows are ordered front to back. - (NSNumber*)orderedIndex; -// Used to see if the windows is in presentation mode. -- (NSNumber*)presenting; - -// Used to enter presentation mode. -- (void)handlesEnterPresentationMode:(NSScriptCommand*)command; - -// Used to exit presentation mode. -- (void)handlesExitPresentationMode:(NSScriptCommand*)command; - @end #endif // CHROME_BROWSER_UI_COCOA_APPLESCRIPT_WINDOW_APPLESCRIPT_H_
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm index 216c0e3..66fd7c55 100644 --- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm +++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -259,26 +259,4 @@ browser_->window()->Close(); } -- (NSNumber*)presenting { - BOOL presentingValue = browser_->window() && - browser_->window()->IsFullscreen() && - !browser_->window() - ->GetExclusiveAccessContext() - ->IsFullscreenWithToolbar(); - return [NSNumber numberWithBool:presentingValue]; -} - -- (void)handlesEnterPresentationMode:(NSScriptCommand*)command { - AppleScript::LogAppleScriptUMA( - AppleScript::AppleScriptCommand::WINDOW_ENTER_PRESENTATION_MODE); - browser_->exclusive_access_manager()->context()->EnterFullscreen( - GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, false); -} - -- (void)handlesExitPresentationMode:(NSScriptCommand*)command { - AppleScript::LogAppleScriptUMA( - AppleScript::AppleScriptCommand::WINDOW_EXIT_PRESENTATION_MODE); - browser_->exclusive_access_manager()->context()->ExitFullscreen(); -} - @end
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h index 1ba1e7f..e82f167 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
@@ -62,8 +62,7 @@ void UpdateFullscreenToolbar() override; bool IsFullscreenWithToolbar() const override; void EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType type, - bool with_toolbar) override; + ExclusiveAccessBubbleType type) override; void ExitFullscreen() override; void UpdateExclusiveAccessExitBubbleContent( const GURL& url,
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm index de52365..7fd122ad 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
@@ -109,7 +109,7 @@ } bool ExclusiveAccessController::IsFullscreenWithToolbar() const { - return IsFullscreen() && ![controller_ inPresentationMode]; + return IsFullscreen(); } // See the Fullscreen terminology section and the (Fullscreen) interface @@ -117,18 +117,15 @@ // logic in this method. void ExclusiveAccessController::EnterFullscreen( const GURL& url, - ExclusiveAccessBubbleType bubble_type, - bool with_toolbar) { + ExclusiveAccessBubbleType bubble_type) { url_ = url; bubble_type_ = bubble_type; if (browser_->exclusive_access_manager() ->fullscreen_controller() ->IsWindowFullscreenForTabOrPending()) [controller_ enterWebContentFullscreen]; - else if (!url.is_empty()) - [controller_ enterExtensionFullscreen]; else - [controller_ enterBrowserFullscreenWithToolbar:with_toolbar]; + [controller_ enterBrowserFullscreen]; } void ExclusiveAccessController::ExitFullscreen() {
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 365df2e0..1fc240f 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -23,7 +23,7 @@ #include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" -#include "chrome/browser/ui/browser_commands_mac.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window_state.h" #import "chrome/browser/ui/cocoa/autofill/save_card_bubble_view_bridge.h" @@ -186,7 +186,7 @@ [window() orderOut:controller_]; [window() miniaturize:controller_]; } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) { - chrome::ToggleFullscreenWithToolbarOrFallback(browser_); + chrome::ToggleFullscreenMode(browser_); } initial_show_state_ = ui::SHOW_STATE_DEFAULT;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index 3e7ab18..2a6f092 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -149,11 +149,6 @@ // AppKit fullscreen mode. BOOL enteringImmersiveFullscreen_; - // True between |-setPresentationMode:url:bubbleType:| and - // |-windowDidEnterFullScreen:| to indicate that the window is in the process - // of transitioning into fullscreen presentation mode. - BOOL enteringPresentationMode_; - // When the window is in the process of entering AppKit Fullscreen, this // property indicates whether the window is being fullscreened on the // primary screen. @@ -441,6 +436,10 @@ // Returns the size of the original (non-fullscreen) window. - (NSRect)savedRegularWindowFrame; +// Returns true if the browser is in the process of entering/exiting +// fullscreen. +- (BOOL)isFullscreenTransitionInProgress; + @end // @interface BrowserWindowController(WindowType) // Fullscreen terminology: @@ -534,10 +533,8 @@ // or exit Lion fullscreen mode. Must not be called on Snow Leopard or earlier. - (void)handleLionToggleFullscreen; -// Enters Browser/Appkit Fullscreen. -// If |withToolbar| is NO, the tab strip and toolbar are hidden -// (aka Presentation Mode). -- (void)enterBrowserFullscreenWithToolbar:(BOOL)withToolbar; +// Enters Browser AppKit Fullscreen. +- (void)enterBrowserFullscreen; // Adds or removes the tab strip and toolbar from the current window. The // window must be in immersive or AppKit Fullscreen. @@ -565,22 +562,12 @@ // the AppKit Fullscreen API. - (BOOL)isInAppKitFullscreen; -// Enter fullscreen for an extension. -- (void)enterExtensionFullscreen; - // Enters Immersive Fullscreen for the given URL. - (void)enterWebContentFullscreen; // Exits the current fullscreen mode. - (void)exitAnyFullscreen; -// Whether the system is in the very specific fullscreen mode: Presentation -// Mode. -- (BOOL)inPresentationMode; - -// Whether the toolbar should be shown in fullscreen. -- (BOOL)shouldShowFullscreenToolbar; - // Called by BrowserWindowFullscreenTransition when the exit animation is // finished. - (void)exitFullscreenAnimationFinished;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 065825b..4a9c4e7 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1851,21 +1851,8 @@ chrome::ExecuteCommand(browser_.get(), IDC_FULLSCREEN); } -- (void)enterBrowserFullscreenWithToolbar:(BOOL)withToolbar { - if (!chrome::mac::SupportsSystemFullscreen()) { - if (![self isInImmersiveFullscreen]) - [self enterImmersiveFullscreen]; - return; - } - - if ([self isInAppKitFullscreen]) { - [self updateFullscreenWithToolbar:withToolbar]; - } else { - // Need to invoke AppKit Fullscreen API. Presentation mode (if set) will - // automatically be enabled in |-windowWillEnterFullScreen:|. - enteringPresentationMode_ = !withToolbar; - [self enterAppKitFullscreen]; - } +- (void)enterBrowserFullscreen { + [self enterAppKitFullscreen]; } - (void)updateFullscreenWithToolbar:(BOOL)withToolbar { @@ -1918,16 +1905,6 @@ return [presentationModeController_ menubarOffset]; } -- (void)enterExtensionFullscreen { - if (chrome::mac::SupportsSystemFullscreen()) { - [self enterBrowserFullscreenWithToolbar:NO]; - } else { - [self enterImmersiveFullscreen]; - DCHECK(!exclusiveAccessController_->url().is_empty()); - [self updateFullscreenExitBubble]; - } -} - - (void)enterWebContentFullscreen { // HTML5 Fullscreen should only use AppKit fullscreen in 10.10+. // However, if the user is using multiple monitors and turned off @@ -1935,8 +1912,7 @@ // that the other monitors won't blank out. display::Screen* screen = display::Screen::GetScreen(); BOOL hasMultipleMonitors = screen && screen->GetNumDisplays() > 1; - if (chrome::mac::SupportsSystemFullscreen() && - base::mac::IsOSYosemiteOrLater() && + if (base::mac::IsOSYosemiteOrLater() && !(hasMultipleMonitors && ![NSScreen screensHaveSeparateSpaces])) { [self enterAppKitFullscreen]; } else { @@ -1956,17 +1932,6 @@ [self exitImmersiveFullscreen]; } -- (BOOL)inPresentationMode { - return presentationModeController_.get() && - [presentationModeController_ inPresentationMode] && - presentationModeController_.get().slidingStyle == - fullscreen_mac::OMNIBOX_TABS_HIDDEN; -} - -- (BOOL)shouldShowFullscreenToolbar { - return shouldShowFullscreenToolbar_; -} - - (void)exitFullscreenAnimationFinished { if (appKitDidExitFullscreen_) { [self windowDidExitFullScreen:nil]; @@ -2062,4 +2027,8 @@ return savedRegularWindowFrame_; } +- (BOOL)isFullscreenTransitionInProgress { + return enteringAppKitFullscreen_ || exitingAppKitFullscreen_; +} + @end // @implementation BrowserWindowController(WindowType)
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm index f886a0d..4021a49 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
@@ -380,7 +380,7 @@ browser() ->exclusive_access_manager() ->fullscreen_controller() - ->ToggleBrowserFullscreenWithToolbar(); + ->ToggleBrowserFullscreenMode(); waiter->Wait(); }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 883c3b30..937409c7 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -71,11 +71,10 @@ }; // There are 2 mechanisms for invoking fullscreen: AppKit and Immersive. -// There are 2 types of AppKit Fullscreen: Presentation Mode and Canonical -// Fullscreen. +// PRESENTATION_MODE = 1 had been removed, but the enums aren't renumbered +// since they are associated with a histogram. enum FullscreenStyle { IMMERSIVE_FULLSCREEN = 0, - PRESENTATION_MODE = 1, CANONICAL_FULLSCREEN = 2, FULLSCREEN_STYLE_COUNT = 3 }; @@ -684,8 +683,7 @@ - (void)windowWillEnterFullScreen:(NSNotification*)notification { RecordFullscreenWindowLocation([self window]); - RecordFullscreenStyle(enteringPresentationMode_ ? PRESENTATION_MODE - : CANONICAL_FULLSCREEN); + RecordFullscreenStyle(CANONICAL_FULLSCREEN); if (notification) // For System Fullscreen when non-nil. [self registerForContentViewResizeNotifications]; @@ -755,7 +753,6 @@ [self deregisterForContentViewResizeNotifications]; enteringImmersiveFullscreen_ = NO; - enteringPresentationMode_ = NO; [self resetCustomAppKitFullscreenVariables]; [[tabStripController_ activeTabContentsController] @@ -867,7 +864,7 @@ fullscreen_mac::SlidingStyle style; if ([self isFullscreenForTabContentOrExtension]) { style = fullscreen_mac::OMNIBOX_TABS_NONE; - } else if (enteringPresentationMode_ || ![self shouldShowFullscreenToolbar]) { + } else if (!shouldShowFullscreenToolbar_) { style = fullscreen_mac::OMNIBOX_TABS_HIDDEN; } else { style = fullscreen_mac::OMNIBOX_TABS_PRESENT;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm index a0650c6..c6a79eb2 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
@@ -768,7 +768,7 @@ [controller_ showWindow:nil]; EXPECT_FALSE([controller_ isInAnyFullscreenMode]); - [controller_ enterBrowserFullscreenWithToolbar:YES]; + [controller_ enterBrowserFullscreen]; WaitForFullScreenTransition(); EXPECT_TRUE([controller_ isInAnyFullscreenMode]); @@ -792,7 +792,7 @@ chrome::testing::NSRunLoopRunAllPending(); EXPECT_TRUE(IsFrontWindow([controller_ window])); - [controller_ enterBrowserFullscreenWithToolbar:YES]; + [controller_ enterBrowserFullscreen]; WaitForFullScreenTransition(); [controller_ activate]; chrome::testing::NSRunLoopRunAllPending();
diff --git a/chrome/browser/ui/cocoa/presentation_mode_controller.h b/chrome/browser/ui/cocoa/presentation_mode_controller.h index 3ee4319..56bb6f0 100644 --- a/chrome/browser/ui/cocoa/presentation_mode_controller.h +++ b/chrome/browser/ui/cocoa/presentation_mode_controller.h
@@ -145,6 +145,10 @@ // Returns true if the window is the main window. - (BOOL)isMainWindow; +// Returns true if the browser is in the process of entering/exiting +// fullscreen. +- (BOOL)isFullscreenTransitionInProgress; + @end // Private methods exposed for testing.
diff --git a/chrome/browser/ui/cocoa/presentation_mode_controller.mm b/chrome/browser/ui/cocoa/presentation_mode_controller.mm index 51504cd8..a3d63f5 100644 --- a/chrome/browser/ui/cocoa/presentation_mode_controller.mm +++ b/chrome/browser/ui/cocoa/presentation_mode_controller.mm
@@ -52,7 +52,7 @@ // As such, we should ignore the kMenuBarRevealEventKind event if it gives // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and // kEventMenuBarHidden to set these values. - if ([self isMainWindow]) { + if ([self isMainWindow] && ![self isFullscreenTransitionInProgress]) { if (GetEventKind(event) == kMenuBarRevealEventKind) { CGFloat revealFraction = 0; GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, @@ -426,6 +426,10 @@ : 0; } +- (BOOL)isFullscreenTransitionInProgress { + return [browserController_ isFullscreenTransitionInProgress]; +} + - (BOOL)isMainWindow { return [browserController_ window].isMainWindow; }
diff --git a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm index 91de2236..73827e4c 100644 --- a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm +++ b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
@@ -104,8 +104,7 @@ // Flaky on Mac: http://crbug.com/90557. IN_PROC_BROWSER_TEST_F(ViewIDTest, DISABLED_Fullscreen) { browser()->exclusive_access_manager()->context()->EnterFullscreen( - GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - false); + GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION); ASSERT_NO_FATAL_FAILURE(DoTest()); }
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_context.h b/chrome/browser/ui/exclusive_access/exclusive_access_context.h index a897357..4ba3c47d 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_context.h +++ b/chrome/browser/ui/exclusive_access/exclusive_access_context.h
@@ -30,11 +30,13 @@ virtual bool IsFullscreen() const = 0; // Returns true if fullscreen with toolbar is supported. + // TODO (spqchan): Deprecate this method. crbug.com/579259 virtual bool SupportsFullscreenWithToolbar() const; // Shows or hides the tab strip, toolbar and bookmark bar with in browser // fullscreen. // Currently only supported on Mac. + // TODO (spqchan): Deprecate this method. crbug.com/579259 virtual void UpdateFullscreenWithToolbar(bool with_toolbar); // Updates the toolbar state to be hidden or shown in fullscreen according to @@ -43,14 +45,12 @@ // Returns true if the window is fullscreen with additional UI elements. See // EnterFullscreen |with_toolbar|. + // TODO (spqchan): Deprecate this method. crbug.com/579259 virtual bool IsFullscreenWithToolbar() const; // Enters fullscreen and update exit bubble. - // On Mac, the tab strip and toolbar will be shown if |with_toolbar| is true, - // |with_toolbar| is ignored on other platforms. virtual void EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType bubble_type, - bool with_toolbar) = 0; + ExclusiveAccessBubbleType bubble_type) = 0; // Exits fullscreen and update exit bubble. virtual void ExitFullscreen() = 0;
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index 7038dcb..a114fdd 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -71,10 +71,6 @@ ToggleFullscreenModeInternal(BROWSER); } -void FullscreenController::ToggleBrowserFullscreenWithToolbar() { - ToggleFullscreenModeInternal(BROWSER_WITH_TOOLBAR); -} - void FullscreenController::ToggleBrowserFullscreenModeWithExtension( const GURL& extension_url) { // |extension_caused_fullscreen_| will be reset if this causes fullscreen to @@ -347,13 +343,8 @@ !IsWindowFullscreenForTabOrPending() && exclusive_access_context->SupportsFullscreenWithToolbar() && IsExtensionFullscreenOrPending()) { - if (option == BROWSER_WITH_TOOLBAR) { - enter_fullscreen = enter_fullscreen || - !exclusive_access_context->IsFullscreenWithToolbar(); - } else { - enter_fullscreen = enter_fullscreen || - exclusive_access_context->IsFullscreenWithToolbar(); - } + enter_fullscreen = enter_fullscreen || + exclusive_access_context->IsFullscreenWithToolbar(); } // In kiosk mode, we always want to be fullscreen. When the browser first @@ -396,8 +387,7 @@ // from tab fullscreen out to browser with toolbar. exclusive_access_manager()->context()->EnterFullscreen( - url, exclusive_access_manager()->GetExclusiveAccessExitBubbleType(), - option == BROWSER_WITH_TOOLBAR); + url, exclusive_access_manager()->GetExclusiveAccessExitBubbleType()); exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h index fcd01da..82a8a95 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -65,10 +65,6 @@ void ToggleBrowserFullscreenMode(); - // Fullscreen mode with tab strip and toolbar shown. - // Currently only supported on Mac. - void ToggleBrowserFullscreenWithToolbar(); - // Extension API implementation uses this method to toggle fullscreen mode. // The extension's name is displayed in the full screen bubble UI to attribute // the cause of the full screen state change. @@ -135,7 +131,6 @@ enum FullscreenInternalOption { BROWSER, - BROWSER_WITH_TOOLBAR, TAB };
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc index 99b43f8f..16a3489 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -62,8 +62,7 @@ void HideDownloadShelf() override; void UnhideDownloadShelf() override; void EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType type, - bool with_toolbar) override; + ExclusiveAccessBubbleType type) override; void ExitFullscreen() override; void UpdateExclusiveAccessExitBubbleContent( const GURL& url, @@ -74,8 +73,6 @@ void ChangeWindowFullscreenState(); private: - // TODO(spqchan): Remove the with_toolbar param in EnterFullscreen() since - // it is now deprecated. See crbug.com/579259. void EnterFullscreen(); // Returns true if ChangeWindowFullscreenState() should be called as a result @@ -93,8 +90,7 @@ void FullscreenControllerTestWindow::EnterFullscreen( const GURL& url, - ExclusiveAccessBubbleType type, - bool with_toolbar) { + ExclusiveAccessBubbleType type) { EnterFullscreen(); }
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index 3670921..c37d34c1 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -289,11 +289,7 @@ // this case? if (launch_type == extensions::LAUNCH_TYPE_FULLSCREEN && !browser->window()->IsFullscreen()) { -#if defined(OS_MACOSX) - chrome::ToggleFullscreenWithToolbarOrFallback(browser); -#else chrome::ToggleFullscreenMode(browser); -#endif } #endif // USE_ASH return contents;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 2e51b4b..c33095dfe 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -931,8 +931,7 @@ } void BrowserView::EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType bubble_type, - bool with_toolbar) { + ExclusiveAccessBubbleType bubble_type) { if (IsFullscreen()) return; // Nothing to do.
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 18792a1..f25e171 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -278,8 +278,7 @@ void Minimize() override; void Restore() override; void EnterFullscreen(const GURL& url, - ExclusiveAccessBubbleType bubble_type, - bool with_toolbar) override; + ExclusiveAccessBubbleType bubble_type) override; void ExitFullscreen() override; void UpdateExclusiveAccessExitBubbleContent( const GURL& url,
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc index 53cb6b5d..a3ab879 100644 --- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "chrome/browser/chromeos/login/screens/network_error_model.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index f8795e98..188ffd2 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/bind.h" #include "base/guid.h" #include "base/logging.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index d738494..88971ea 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -9,8 +9,8 @@ #include <algorithm> #include <vector> +#include "ash/common/system/chromeos/devicetype_utils.h" #include "ash/shell.h" -#include "ash/system/chromeos/devicetype_utils.h" #include "ash/wm/lock_state_controller.h" #include "base/bind.h" #include "base/location.h"
diff --git a/chrome/browser/ui/webui/help/help_handler.cc b/chrome/browser/ui/webui/help/help_handler.cc index 3fd9934..423444a 100644 --- a/chrome/browser/ui/webui/help/help_handler.cc +++ b/chrome/browser/ui/webui/help/help_handler.cc
@@ -8,7 +8,7 @@ #include <string> -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h"
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index 7c2be992..0d435e05 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -112,9 +112,9 @@ #if defined(OS_CHROMEOS) #include "ash/ash_switches.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "ash/desktop_background/user_wallpaper_delegate.h" #include "ash/shell.h" -#include "ash/system/chromeos/devicetype_utils.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/accessibility/accessibility_util.h" #include "chrome/browser/chromeos/arc/arc_auth_service.h"
diff --git a/chrome/browser/ui/webui/options/chromeos/consumer_management_handler.cc b/chrome/browser/ui/webui/options/chromeos/consumer_management_handler.cc index ea72850..7acbd03 100644 --- a/chrome/browser/ui/webui/options/chromeos/consumer_management_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/consumer_management_handler.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/webui/options/chromeos/consumer_management_handler.h" -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h"
diff --git a/chrome/browser/ui/webui/options/chromeos/power_handler.h b/chrome/browser/ui/webui/options/chromeos/power_handler.h index 68667c8..b5045e6 100644 --- a/chrome/browser/ui/webui/options/chromeos/power_handler.h +++ b/chrome/browser/ui/webui/options/chromeos/power_handler.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_POWER_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_POWER_HANDLER_H_ -#include "ash/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/power_status.h" #include "base/macros.h" #include "base/strings/string16.h" #include "chrome/browser/ui/webui/options/options_ui.h"
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc index 6f9ca5d..50db13d 100644 --- a/chrome/browser/ui/webui/settings/about_handler.cc +++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -8,7 +8,7 @@ #include <string> -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h"
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 1f8269c..20cb4885 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -28,7 +28,7 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) -#include "ash/system/chromeos/devicetype_utils.h" +#include "ash/common/system/chromeos/devicetype_utils.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h" #include "chromeos/chromeos_switches.h"
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 0c4590ef..7b6f035 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi
@@ -62,6 +62,8 @@ 'browser/chromeos/arc/arc_auth_service.h', 'browser/chromeos/arc/arc_downloads_watcher_service.cc', 'browser/chromeos/arc/arc_downloads_watcher_service.h', + 'browser/chromeos/arc/arc_navigation_throttle.cc', + 'browser/chromeos/arc/arc_navigation_throttle.h', 'browser/chromeos/arc/arc_service_launcher.cc', 'browser/chromeos/arc/arc_service_launcher.h', 'browser/chromeos/arc/arc_support_host.cc',
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc index 49db418..ecaaf2d3 100644 --- a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc +++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
@@ -44,6 +44,15 @@ }; using ComparablePermissions = std::vector<ComparablePermission>; +void DropPermissionParameter(APIPermission::ID id, + PermissionIDSet* permissions) { + if (permissions->ContainsID(id)) { + // Erase the permission, and insert it again without a parameter. + permissions->erase(id); + permissions->insert(id); + } +} + } // namespace typedef std::set<PermissionMessage> PermissionMsgSet; @@ -176,6 +185,20 @@ AddAPIPermissions(new_permissions, &new_ids); AddManifestPermissions(new_permissions, &new_ids); + // Ugly hack: Before M46 beta, we didn't store the parameter for settings + // override permissions in prefs (which is where |old_permissions| is coming + // from). To avoid a spurious permission increase warning, drop the parameter. + // See crbug.com/533086 and crbug.com/619759. + // TODO(treib,devlin): Remove this for M56, when hopefully all users will have + // updated prefs. + const APIPermission::ID kSettingsOverrideIDs[] = { + APIPermission::kHomepage, APIPermission::kSearchProvider, + APIPermission::kStartupPages}; + for (auto id : kSettingsOverrideIDs) { + DropPermissionParameter(id, &old_ids); + DropPermissionParameter(id, &new_ids); + } + // If all the IDs were already there, it's not a privilege increase. if (old_ids.Includes(new_ids)) return false;
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc index 606218ab..c6d69aef 100644 --- a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc +++ b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
@@ -129,4 +129,30 @@ EXPECT_FALSE(message1.submessages().empty()); } +// Anti-test: Check that adding a parameter to a SettingsOverridePermission +// doesn't trigger a privilege increase. This is because prior to M46 beta, we +// failed to store the parameter in the granted_permissions pref. Now we do, and +// we don't want to bother every user with a spurious permissions warning. +// See crbug.com/533086 and crbug.com/619759. +// TODO(treib,devlin): Remove this for M56, when hopefully all users will have +// updated prefs. +TEST_F(ChromePermissionMessageProviderUnittest, + EvilHackToSuppressSettingsOverrideParameter) { + const APIPermissionInfo* info = + PermissionsInfo::GetInstance()->GetByID(APIPermission::kSearchProvider); + + APIPermissionSet granted_permissions; + granted_permissions.insert(new SettingsOverrideAPIPermission(info)); + + APIPermissionSet actual_permissions; + actual_permissions.insert(new SettingsOverrideAPIPermission(info, "a.com")); + + EXPECT_FALSE(IsPrivilegeIncrease(granted_permissions, actual_permissions)); + + // Just to be safe: Adding the permission (with or without parameter) should + // still be considered a privilege escalation. + EXPECT_TRUE(IsPrivilegeIncrease(APIPermissionSet(), granted_permissions)); + EXPECT_TRUE(IsPrivilegeIncrease(APIPermissionSet(), actual_permissions)); +} + } // namespace extensions
diff --git a/chrome/test/data/android/payments/dynamic_shipping.js b/chrome/test/data/android/payments/dynamic_shipping.js index 0b55e07..ede7b7f 100644 --- a/chrome/test/data/android/payments/dynamic_shipping.js +++ b/chrome/test/data/android/payments/dynamic_shipping.js
@@ -30,7 +30,7 @@ request.show() .then(function(resp) { - resp.complete(true) + resp.complete("success") .then(function() { print( JSON.stringify(resp.totalAmount, undefined, 2) + '<br>' +
diff --git a/chrome/test/data/android/payments/free_shipping.js b/chrome/test/data/android/payments/free_shipping.js index 217ea93..d7ee2132 100644 --- a/chrome/test/data/android/payments/free_shipping.js +++ b/chrome/test/data/android/payments/free_shipping.js
@@ -25,7 +25,7 @@ {requestShipping: true}); request.show() .then(function(resp) { - resp.complete(true) + resp.complete("success") .then(function() { print( JSON.stringify(resp.totalAmount, undefined, 2) + '<br>' +
diff --git a/chrome/test/data/android/payments/no_shipping.js b/chrome/test/data/android/payments/no_shipping.js index 9df7a46..060a11b9 100644 --- a/chrome/test/data/android/payments/no_shipping.js +++ b/chrome/test/data/android/payments/no_shipping.js
@@ -16,7 +16,7 @@ {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}) .show() .then(function(resp) { - resp.complete(true) + resp.complete("success") .then(function() { print( JSON.stringify(resp.totalAmount, undefined, 2) + '<br>' +
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc index 9b2bacad..fa193b12 100644 --- a/chromeos/dbus/session_manager_client.cc +++ b/chromeos/dbus/session_manager_client.cc
@@ -429,6 +429,13 @@ weak_ptr_factory_.GetWeakPtr()), base::Bind(&SessionManagerClientImpl::SignalConnected, weak_ptr_factory_.GetWeakPtr())); + session_manager_proxy_->ConnectToSignal( + login_manager::kSessionManagerInterface, + login_manager::kArcInstanceStopped, + base::Bind(&SessionManagerClientImpl::ArcInstanceStoppedReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&SessionManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); } private: @@ -654,6 +661,16 @@ FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked()); } + void ArcInstanceStoppedReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + bool clean = false; + if (!reader.PopBool(&clean)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + FOR_EACH_OBSERVER(Observer, observers_, ArcInstanceStopped(clean)); + } + // Called when the object is connected to the signal. void SignalConnected(const std::string& interface_name, const std::string& signal_name,
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h index 7b51f25..13818d5 100644 --- a/chromeos/dbus/session_manager_client.h +++ b/chromeos/dbus/session_manager_client.h
@@ -47,6 +47,11 @@ // Called after EmitLoginPromptVisible is called. virtual void EmitLoginPromptVisibleCalled() {} + + // Called when the ARC instance is stopped after it had already started. + // |clean| is true if the instance was stopped as a result of an explicit + // request, false if it died unexpectedly. + virtual void ArcInstanceStopped(bool clean) {} }; // Interface for performing actions on behalf of the stub implementation.
diff --git a/components/arc/OWNERS b/components/arc/OWNERS index f068aeb..d7d81e7 100644 --- a/components/arc/OWNERS +++ b/components/arc/OWNERS
@@ -1,3 +1,4 @@ elijahtaylor@chromium.org hidehiko@chromium.org lhchavez@chromium.org +yusukes@chromium.org
diff --git a/components/arc/arc_bridge_bootstrap.cc b/components/arc/arc_bridge_bootstrap.cc index 33b04cd..930282e 100644 --- a/components/arc/arc_bridge_bootstrap.cc +++ b/components/arc/arc_bridge_bootstrap.cc
@@ -42,7 +42,23 @@ const char kArcBridgeSocketGroup[] = "arc-bridge"; -class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap { +// This is called when StopArcInstance D-Bus method completes. Since we have the +// ArcInstanceStopped() callback and are notified if StartArcInstance fails, we +// don't need to do anything when StopArcInstance completes. +void DoNothingInstanceStopped(bool) {} + +chromeos::SessionManagerClient* GetSessionManagerClient() { + // If the DBusThreadManager or the SessionManagerClient aren't available, + // there isn't much we can do. This should only happen when running tests. + if (!chromeos::DBusThreadManager::IsInitialized() || + !chromeos::DBusThreadManager::Get() || + !chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) + return nullptr; + return chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); +} + +class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap, + public chromeos::SessionManagerClient::Observer { public: // The possible states of the bootstrap connection. In the normal flow, // the state changes in the following sequence: @@ -112,7 +128,9 @@ // DBus callbacks. void OnInstanceStarted(base::ScopedFD socket_fd, bool success); - void OnInstanceStopped(bool success); + + // chromeos::SessionManagerClient::Observer: + void ArcInstanceStopped(bool clean) override; // The state of the bootstrap connection. State state_ = State::STOPPED; @@ -126,11 +144,21 @@ DISALLOW_COPY_AND_ASSIGN(ArcBridgeBootstrapImpl); }; -ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl() : weak_factory_(this) {} +ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl() + : weak_factory_(this) { + chromeos::SessionManagerClient* client = GetSessionManagerClient(); + if (client == nullptr) + return; + client->AddObserver(this); +} ArcBridgeBootstrapImpl::~ArcBridgeBootstrapImpl() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(state_ == State::STOPPED || state_ == State::STOPPING); + chromeos::SessionManagerClient* client = GetSessionManagerClient(); + if (client == nullptr) + return; + client->RemoveObserver(this); } void ArcBridgeBootstrapImpl::Start() { @@ -228,10 +256,6 @@ void ArcBridgeBootstrapImpl::OnInstanceStarted(base::ScopedFD socket_fd, bool success) { DCHECK(thread_checker_.CalledOnValidThread()); - if (state_ != State::STARTING) { - VLOG(1) << "Stop() called when ARC is not running"; - return; - } if (!success) { LOG(ERROR) << "Failed to start ARC instance"; // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal @@ -240,6 +264,10 @@ Stop(); return; } + if (state_ != State::STARTING) { + VLOG(1) << "Stop() called when ARC is not running"; + return; + } SetState(State::STARTED); base::PostTaskAndReplyWithResult( @@ -315,21 +343,21 @@ // This was stopped before the D-Bus command to start the instance. Skip // the D-Bus command to stop it. SetState(State::STOPPING); - OnInstanceStopped(true); + ArcInstanceStopped(true); return; } SetState(State::STOPPING); + // Notification will arrive through ArcInstanceStopped(). chromeos::SessionManagerClient* session_manager_client = chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager_client->StopArcInstance(base::Bind( - &ArcBridgeBootstrapImpl::OnInstanceStopped, weak_factory_.GetWeakPtr())); + session_manager_client->StopArcInstance( + base::Bind(&DoNothingInstanceStopped)); } -void ArcBridgeBootstrapImpl::OnInstanceStopped(bool success) { +void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) { DCHECK(thread_checker_.CalledOnValidThread()); - // STOPPING is the only valid state for this function. - // DCHECK on enum classes not supported. - DCHECK(state_ == State::STOPPING); + if (!clean) + LOG(ERROR) << "ARC instance crashed"; DCHECK(delegate_); SetState(State::STOPPED); delegate_->OnStopped();
diff --git a/components/arc/arc_bridge_service_impl.cc b/components/arc/arc_bridge_service_impl.cc index 20de50a..ca87d13 100644 --- a/components/arc/arc_bridge_service_impl.cc +++ b/components/arc/arc_bridge_service_impl.cc
@@ -94,6 +94,9 @@ if (binding_.is_bound()) binding_.Close(); bootstrap_->Stop(); + + // We were explicitly asked to stop, so do not reconnect. + reconnect_ = false; } void ArcBridgeServiceImpl::SetDetectedAvailability(bool arc_available) { @@ -119,6 +122,9 @@ instance_ptr_->Init(binding_.CreateInterfacePtrAndBind()); + // The container can be considered to have been successfully launched, so + // restart if the connection goes down without being requested. + reconnect_ = true; VLOG(0) << "ARC ready"; SetState(State::READY); } @@ -154,9 +160,10 @@ return; } VLOG(1) << "Mojo connection lost"; + instance_ptr_.reset(); + if (binding_.is_bound()) + binding_.Close(); CloseAllChannels(); - reconnect_ = true; - StopInstance(); } } // namespace arc
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc index 343cdf3..598e54b 100644 --- a/components/arc/arc_bridge_service_unittest.cc +++ b/components/arc/arc_bridge_service_unittest.cc
@@ -121,7 +121,7 @@ ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); } -// If the channel is disconnected, it should be re-established. +// If the instance is stopped, it should be re-started. TEST_F(ArcBridgeTest, Restart) { ASSERT_FALSE(ready()); ASSERT_EQ(0, instance_->init_calls()); @@ -135,6 +135,7 @@ // Simulate a connection loss. service_->DisableReconnectDelayForTesting(); service_->OnChannelClosed(); + instance_->SimulateCrash(); instance_->WaitForInitCall(); ASSERT_EQ(ArcBridgeService::State::READY, state()); ASSERT_EQ(2, instance_->init_calls());
diff --git a/components/arc/test/fake_arc_bridge_bootstrap.cc b/components/arc/test/fake_arc_bridge_bootstrap.cc index 33ac6c3..cd05697 100644 --- a/components/arc/test/fake_arc_bridge_bootstrap.cc +++ b/components/arc/test/fake_arc_bridge_bootstrap.cc
@@ -15,6 +15,7 @@ FakeArcBridgeBootstrap::FakeArcBridgeBootstrap(FakeArcBridgeInstance* instance) : instance_(instance) { + instance_->set_delegate(this); } void FakeArcBridgeBootstrap::Start() { @@ -30,4 +31,8 @@ delegate_->OnStopped(); } +void FakeArcBridgeBootstrap::OnCrashed() { + Stop(); +} + } // namespace arc
diff --git a/components/arc/test/fake_arc_bridge_bootstrap.h b/components/arc/test/fake_arc_bridge_bootstrap.h index feb7d6c..f9a9b2f 100644 --- a/components/arc/test/fake_arc_bridge_bootstrap.h +++ b/components/arc/test/fake_arc_bridge_bootstrap.h
@@ -7,22 +7,25 @@ #include "base/macros.h" #include "components/arc/arc_bridge_bootstrap.h" +#include "components/arc/test/fake_arc_bridge_instance.h" namespace arc { -class FakeArcBridgeInstance; - // A fake ArcBridgeBootstrap that creates a local connection. -class FakeArcBridgeBootstrap : public ArcBridgeBootstrap { +class FakeArcBridgeBootstrap : public ArcBridgeBootstrap, + public FakeArcBridgeInstance::Delegate { public: explicit FakeArcBridgeBootstrap(FakeArcBridgeInstance* instance); - ~FakeArcBridgeBootstrap() override {} + ~FakeArcBridgeBootstrap() override = default; // ArcBridgeBootstrap: void Start() override; void Stop() override; private: + // FakeArcBridgeInstance::Delegate: + void OnCrashed() override; + // Owned by the caller. FakeArcBridgeInstance* instance_;
diff --git a/components/arc/test/fake_arc_bridge_instance.cc b/components/arc/test/fake_arc_bridge_instance.cc index 81aa152d..e51e54a 100644 --- a/components/arc/test/fake_arc_bridge_instance.cc +++ b/components/arc/test/fake_arc_bridge_instance.cc
@@ -31,4 +31,10 @@ binding_.WaitForIncomingMethodCall(); } +void FakeArcBridgeInstance::SimulateCrash() { + if (!delegate_) + return; + delegate_->OnCrashed(); +} + } // namespace arc
diff --git a/components/arc/test/fake_arc_bridge_instance.h b/components/arc/test/fake_arc_bridge_instance.h index 9488ea5..5a3aa47 100644 --- a/components/arc/test/fake_arc_bridge_instance.h +++ b/components/arc/test/fake_arc_bridge_instance.h
@@ -14,9 +14,17 @@ class FakeArcBridgeInstance : public mojom::ArcBridgeInstance { public: + class Delegate { + public: + virtual ~Delegate() = default; + virtual void OnCrashed() = 0; + }; + FakeArcBridgeInstance(); ~FakeArcBridgeInstance() override; + void set_delegate(Delegate* delegate) { delegate_ = delegate; } + // Finalizes the connection between the host and the instance, and signals // the host that the boot sequence has finished. void Bind(mojo::InterfaceRequest<mojom::ArcBridgeInstance> interface_request); @@ -33,7 +41,12 @@ // The number of times Init() has been called. int init_calls() const { return init_calls_; } + // Simulates a crash by calling Stop() on the ArcBridgeBoostrap. + void SimulateCrash(); + private: + Delegate* delegate_ = nullptr; + // Mojo endpoints. mojo::Binding<mojom::ArcBridgeInstance> binding_; mojom::ArcBridgeHostPtr host_ptr_;
diff --git a/components/drive/BUILD.gn b/components/drive/BUILD.gn index 8c7e8e8..c5c95162 100644 --- a/components/drive/BUILD.gn +++ b/components/drive/BUILD.gn
@@ -56,6 +56,7 @@ # TODO(lukasza): Remove this dependency (see DEPS file for more info). "//content/public/browser", + "//device/power_save_blocker", "//google_apis:google_apis", "//net:net", "//third_party/cacheinvalidation",
diff --git a/components/drive/DEPS b/components/drive/DEPS index 5586c3bf..dda68d0 100644 --- a/components/drive/DEPS +++ b/components/drive/DEPS
@@ -2,6 +2,7 @@ "+components/invalidation", "+components/keyed_service", "+components/prefs", + "+device/power_save_blocker", "+google_apis", "+google/cacheinvalidation/types.pb.h", "+net", @@ -10,13 +11,6 @@ ] specific_include_rules = { - # The following dependency should be removed to fully make this - # directory chrome/ and content/ and storage/ independent. - # crbug.com/257943 - "drive_uploader\.cc": [ - "+content/public/browser/power_save_blocker_factory.h", - ], - # The following test dependencies should be removed to fully componentize this # directory. crbug.com/498951 r"(copy_operation_unittest\.cc" @@ -62,8 +56,9 @@ # The following test dependencies should be removed to fully componentize this # directory. crbug.com/498951 - r"(fake_file_system\.cc" - r"|file_system_unittest.cc" + r"(drive_uploader\.cc" + r"|fake_file_system\.cc" + r"|file_system_unittest\.cc" r"|file_write_watcher_unittest\.cc" r"|get_file_for_saving_operation_unittest\.cc" r"|operation_test_base\.cc"
diff --git a/components/drive/drive_uploader.cc b/components/drive/drive_uploader.cc index e8b0c53..ed2a921 100644 --- a/components/drive/drive_uploader.cc +++ b/components/drive/drive_uploader.cc
@@ -15,7 +15,8 @@ #include "base/strings/string_number_conversions.h" #include "base/task_runner_util.h" #include "components/drive/service/drive_service_interface.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/public/browser/browser_thread.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "google_apis/drive/drive_api_parser.h" using google_apis::CancelCallback; @@ -98,10 +99,14 @@ progress_callback(progress_callback), content_length(0), next_start_position(-1), - power_save_blocker(content::CreatePowerSaveBlocker( - content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - content::PowerSaveBlocker::kReasonOther, - "Upload in progress")), + power_save_blocker(device::PowerSaveBlocker::CreateWithTaskRunners( + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, + "Upload in progress", + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE))), cancelled(false), weak_ptr_factory_(this) {} @@ -143,7 +148,7 @@ int64_t next_start_position; // Blocks system suspend while upload is in progress. - std::unique_ptr<content::PowerSaveBlocker> power_save_blocker; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker; // Fields for implementing cancellation. |cancel_callback| is non-null if // there is an in-flight HTTP request. In that case, |cancell_callback| will
diff --git a/components/flags_ui/BUILD.gn b/components/flags_ui/BUILD.gn index 81f0f5c1..36cfed8a 100644 --- a/components/flags_ui/BUILD.gn +++ b/components/flags_ui/BUILD.gn
@@ -24,6 +24,7 @@ "//components/pref_registry", "//components/prefs", "//components/strings", + "//components/variations", "//ui/base", ] } @@ -49,6 +50,7 @@ "//base", "//components/prefs:test_support", "//components/strings", + "//components/variations", "//testing/gtest", ] }
diff --git a/components/flags_ui/DEPS b/components/flags_ui/DEPS index 983d01e..02fddd1 100644 --- a/components/flags_ui/DEPS +++ b/components/flags_ui/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+components/pref_registry", "+components/prefs", + "+components/variations", "+grit/components_strings.h", "+ui/base", ]
diff --git a/components/flags_ui/feature_entry.cc b/components/flags_ui/feature_entry.cc index b755697..53a219c 100644 --- a/components/flags_ui/feature_entry.cc +++ b/components/flags_ui/feature_entry.cc
@@ -6,25 +6,28 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" namespace flags_ui { -std::string FeatureEntry::NameForChoice(int index) const { +std::string FeatureEntry::NameForOption(int index) const { DCHECK(type == FeatureEntry::MULTI_VALUE || type == FeatureEntry::ENABLE_DISABLE_VALUE || - type == FeatureEntry::FEATURE_VALUE); - DCHECK_LT(index, num_choices); + type == FeatureEntry::FEATURE_VALUE || + type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); + DCHECK_LT(index, num_options); return std::string(internal_name) + testing::kMultiSeparator + base::IntToString(index); } -base::string16 FeatureEntry::DescriptionForChoice(int index) const { +base::string16 FeatureEntry::DescriptionForOption(int index) const { DCHECK(type == FeatureEntry::MULTI_VALUE || type == FeatureEntry::ENABLE_DISABLE_VALUE || - type == FeatureEntry::FEATURE_VALUE); - DCHECK_LT(index, num_choices); + type == FeatureEntry::FEATURE_VALUE || + type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); + DCHECK_LT(index, num_options); int description_id; if (type == FeatureEntry::ENABLE_DISABLE_VALUE || type == FeatureEntry::FEATURE_VALUE) { @@ -34,12 +37,64 @@ IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED, }; description_id = kEnableDisableDescriptionIds[index]; + } else if (type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE) { + if (index == 0) { + description_id = IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT; + } else if (index == 1) { + // Variation 1: the default enabled variation => "Enabled". + description_id = IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED; + } else if (index < num_options - 1) { + // Variations 2 .. n => "Enabled <description_text>". + int variation_index = index - 1; + return l10n_util::GetStringUTF16(IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED) + + base::ASCIIToUTF16(" ") + + base::ASCIIToUTF16( + feature_variations[variation_index].description_text); + } else { + DCHECK_EQ(num_options - 1, index); + description_id = IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED; + } } else { description_id = choices[index].description_id; } return l10n_util::GetStringUTF16(description_id); } +const FeatureEntry::Choice& FeatureEntry::ChoiceForOption(int index) const { + DCHECK_EQ(FeatureEntry::MULTI_VALUE, type); + DCHECK_LT(index, num_options); + + return choices[index]; +} + +FeatureEntry::FeatureState FeatureEntry::StateForOption(int index) const { + DCHECK(type == FeatureEntry::FEATURE_VALUE || + type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); + DCHECK_LT(index, num_options); + + if (index == 0) + return FeatureEntry::FeatureState::DEFAULT; + else if (index == num_options - 1) + return FeatureEntry::FeatureState::DISABLED; + else + return FeatureEntry::FeatureState::ENABLED; +} + +const FeatureEntry::FeatureVariation* FeatureEntry::VariationForOption( + int index) const { + DCHECK(type == FeatureEntry::FEATURE_VALUE || + type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); + DCHECK_LT(index, num_options); + + if (type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE && index > 0 && + index < num_options - 1) { + // We have no variations for FEATURE_VALUE type. Option at |index| + // corresponds to variation at |index| - 1 as the first option is "Default". + return &feature_variations[index - 1]; + } + return nullptr; +} + namespace testing { // WARNING: '@' is also used in the html file. If you update this constant you
diff --git a/components/flags_ui/feature_entry.h b/components/flags_ui/feature_entry.h index 4f7f081..a3930fd 100644 --- a/components/flags_ui/feature_entry.h +++ b/components/flags_ui/feature_entry.h
@@ -47,6 +47,24 @@ // have three states: Default, Enabled, Disabled. When not specified or set // to Default, the normal default value of the feature is used. FEATURE_VALUE, + + // Corresponds to a base::Feature and additional options [O_1, ..., O_n] + // that specify variation parameters. Each of the options can specify a set + // of variation parameters. The entry will have n+2 states: Default, + // Enabled: V_1, ..., Enabled: V_n, Disabled. When not specified or set to + // Default, the normal default values of the feature and of the parameters + // are used. + FEATURE_WITH_VARIATIONS_VALUE, + }; + + // Describes state of a feature. + enum FeatureState { + // The state of the feature is not overridden by the user. + DEFAULT, + // The feature is enabled by the user. + ENABLED, + // The feature is disabled by the user. + DISABLED, }; // Used for MULTI_VALUE types to describe one of the possible values the user @@ -61,6 +79,26 @@ const char* command_line_value; }; + // Configures one parameter for FEATURE_WITH_VARIATIONS_VALUE. + struct FeatureParam { + const char* param_name; + const char* param_value; + }; + + // Specified one variation (list of parameter values) for + // FEATURE_WITH_VARIATIONS_VALUE. + struct FeatureVariation { + // Text that denotes the variation in chrome://flags. For each variation, + // the user is shown an option labeled "Enabled <description_text>" (with + // the exception of the first option labeled "Enabled" to make clear it is + // the default one). No need for description_id, chrome://flags should not + // get translated. The other parts here use ids for historical reasons and + // can realistically also be moved to direct description_texts. + const char* description_text; + const FeatureParam* params; + int num_params; + }; + // The internal name of the feature entry. This is never shown to the user. // It _is_ however stored in the prefs file, so you shouldn't change the // name of existing flags. @@ -96,18 +134,43 @@ // For FEATURE_VALUE, the base::Feature this entry corresponds to. const base::Feature* feature; - // This is used if type is MULTI_VALUE. + // Number of options to choose from. This is used if type is MULTI_VALUE, + // ENABLE_DISABLE_VALUE, FEATURE_VALUE, or FEATURE_WITH_VARIATIONS_VALUE. + int num_options; + + // This describes the options if type is MULTI_VALUE. const Choice* choices; - // Number of |choices|. - // This is used if type is MULTI_VALUE. - int num_choices; + // This describes the options if type is FEATURE_WITH_VARIATIONS_VALUE. + // The first variation is the default "Enabled" variation, its description_id + // is disregarded. + const FeatureVariation* feature_variations; - // Returns the name used in prefs for the choice at the specified |index|. - std::string NameForChoice(int index) const; + // The name of the FieldTrial in which the selected variation parameters + // should be registered. This is used if type is + // FEATURE_WITH_VARIATIONS_VALUE. + const char* feature_trial_name; - // Returns the human readable description for the choice at |index|. - base::string16 DescriptionForChoice(int index) const; + // Returns the name used in prefs for the option at the specified |index|. + // Only used for types that use |num_options|. + std::string NameForOption(int index) const; + + // Returns the human readable description for the option at |index|. + // Only used for types that use |num_options|. + base::string16 DescriptionForOption(int index) const; + + // Returns the choice for the option at |index|. Only applicable for type + // FEATURE_MULTI. + const FeatureEntry::Choice& ChoiceForOption(int index) const; + + // Returns the state of the feature at |index|. Only applicable for types + // FEATURE_VALUE and FEATURE_WITH_VARIATIONS_VALUE. + FeatureEntry::FeatureState StateForOption(int index) const; + + // Returns the variation for the option at |index| or nullptr if there is no + // variation associated at |index|. Only applicable for types FEATURE_VALUE + // and FEATURE_WITH_VARIATIONS_VALUE. + const FeatureEntry::FeatureVariation* VariationForOption(int index) const; }; namespace testing {
diff --git a/components/flags_ui/feature_entry_macros.h b/components/flags_ui/feature_entry_macros.h index 1dac0f3..9394b3730 100644 --- a/components/flags_ui/feature_entry_macros.h +++ b/components/flags_ui/feature_entry_macros.h
@@ -12,25 +12,30 @@ // different entry types and when they should be used. #define SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ flags_ui::FeatureEntry::SINGLE_VALUE, command_line_switch, switch_value, \ - nullptr, nullptr, nullptr, nullptr, 0 + nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr #define SINGLE_VALUE_TYPE(command_line_switch) \ SINGLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") #define SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, switch_value) \ flags_ui::FeatureEntry::SINGLE_DISABLE_VALUE, command_line_switch, \ - switch_value, nullptr, nullptr, nullptr, nullptr, 0 + switch_value, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr #define SINGLE_DISABLE_VALUE_TYPE(command_line_switch) \ SINGLE_DISABLE_VALUE_TYPE_AND_VALUE(command_line_switch, "") #define ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, enable_value, \ disable_switch, disable_value) \ flags_ui::FeatureEntry::ENABLE_DISABLE_VALUE, enable_switch, enable_value, \ - disable_switch, disable_value, nullptr, nullptr, 3 + disable_switch, disable_value, nullptr, 3, nullptr, nullptr, nullptr #define ENABLE_DISABLE_VALUE_TYPE(enable_switch, disable_switch) \ ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(enable_switch, "", disable_switch, "") #define MULTI_VALUE_TYPE(choices) \ flags_ui::FeatureEntry::MULTI_VALUE, nullptr, nullptr, nullptr, nullptr, \ - nullptr, choices, arraysize(choices) + nullptr, arraysize(choices), choices, nullptr, nullptr #define FEATURE_VALUE_TYPE(feature) \ flags_ui::FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr, \ - &feature, nullptr, 3 + &feature, 3, nullptr, nullptr, nullptr +#define FEATURE_WITH_VARIATIONS_VALUE_TYPE(feature, feature_variations, \ + feature_trial) \ + flags_ui::FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE, nullptr, nullptr, \ + nullptr, nullptr, &feature, 2 + arraysize(feature_variations), nullptr, \ + feature_variations, feature_trial #endif // COMPONENTS_FLAGS_UI_FEATURE_ENTRY_MACROS_H_
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc index 8206ef0..cadb8ee1 100644 --- a/components/flags_ui/flags_state.cc +++ b/components/flags_ui/flags_state.cc
@@ -11,6 +11,7 @@ #include "base/feature_list.h" #include "base/logging.h" #include "base/macros.h" +#include "base/metrics/field_trial.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -19,10 +20,15 @@ #include "components/flags_ui/feature_entry.h" #include "components/flags_ui/flags_storage.h" #include "components/flags_ui/flags_ui_switches.h" +#include "components/variations/variations_associated_data.h" #include "ui/base/l10n/l10n_util.h" namespace flags_ui { +namespace internal { +const char kTrialGroupAboutFlags[] = "AboutFlags"; +} // namespace internal + namespace { // Convert switch constants to proper CommandLine::StringType strings. @@ -99,8 +105,9 @@ case FeatureEntry::MULTI_VALUE: case FeatureEntry::ENABLE_DISABLE_VALUE: case FeatureEntry::FEATURE_VALUE: - for (int i = 0; i < e.num_choices; ++i) - names->insert(e.NameForChoice(i)); + case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: + for (int i = 0; i < e.num_options; ++i) + names->insert(e.NameForOption(i)); break; } } @@ -111,17 +118,17 @@ switch (e.type) { case FeatureEntry::SINGLE_VALUE: case FeatureEntry::SINGLE_DISABLE_VALUE: - DCHECK_EQ(0, e.num_choices); + DCHECK_EQ(0, e.num_options); DCHECK(!e.choices); return true; case FeatureEntry::MULTI_VALUE: - DCHECK_GT(e.num_choices, 0); + DCHECK_GT(e.num_options, 0); DCHECK(e.choices); - DCHECK(e.choices[0].command_line_switch); - DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); + DCHECK(e.ChoiceForOption(0).command_line_switch); + DCHECK_EQ('\0', e.ChoiceForOption(0).command_line_switch[0]); return true; case FeatureEntry::ENABLE_DISABLE_VALUE: - DCHECK_EQ(3, e.num_choices); + DCHECK_EQ(3, e.num_options); DCHECK(!e.choices); DCHECK(e.command_line_switch); DCHECK(e.command_line_value); @@ -129,10 +136,17 @@ DCHECK(e.disable_command_line_value); return true; case FeatureEntry::FEATURE_VALUE: - DCHECK_EQ(3, e.num_choices); + DCHECK_EQ(3, e.num_options); DCHECK(!e.choices); DCHECK(e.feature); return true; + case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: + DCHECK_GT(e.num_options, 2); + DCHECK(!e.choices); + DCHECK(e.feature); + DCHECK(e.feature_variations); + DCHECK(e.feature_trial_name); + return true; } NOTREACHED(); return false; @@ -148,8 +162,9 @@ case FeatureEntry::MULTI_VALUE: case FeatureEntry::ENABLE_DISABLE_VALUE: case FeatureEntry::FEATURE_VALUE: - for (int i = 0; i < entry.num_choices; ++i) { - if (enabled_entries.count(entry.NameForChoice(i)) > 0) + case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: + for (int i = 0; i < entry.num_options; ++i) { + if (enabled_entries.count(entry.NameForOption(i)) > 0) return false; } return true; @@ -159,23 +174,54 @@ } // Returns the Value representing the choice data in the specified entry. -base::Value* CreateChoiceData(const FeatureEntry& entry, - const std::set<std::string>& enabled_entries) { +base::Value* CreateOptionsData(const FeatureEntry& entry, + const std::set<std::string>& enabled_entries) { DCHECK(entry.type == FeatureEntry::MULTI_VALUE || entry.type == FeatureEntry::ENABLE_DISABLE_VALUE || - entry.type == FeatureEntry::FEATURE_VALUE); + entry.type == FeatureEntry::FEATURE_VALUE || + entry.type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); base::ListValue* result = new base::ListValue; - for (int i = 0; i < entry.num_choices; ++i) { + for (int i = 0; i < entry.num_options; ++i) { std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue); - const std::string name = entry.NameForChoice(i); + const std::string name = entry.NameForOption(i); value->SetString("internal_name", name); - value->SetString("description", entry.DescriptionForChoice(i)); + value->SetString("description", entry.DescriptionForOption(i)); value->SetBoolean("selected", enabled_entries.count(name) > 0); result->Append(std::move(value)); } return result; } +// Registers variation parameters specified by |feature_variation| for the field +// trial named |feature_trial_name|, unless a group for this trial has already +// been created (e.g. via command-line switches that take precedence over +// about:flags). In the trial, the function creates a new constant group called +// |kTrialGroupAboutFlags|. +void RegisterFeatureVariationParameters( + const std::string& feature_trial_name, + const FeatureEntry::FeatureVariation& feature_variation) { + std::map<std::string, std::string> params; + for (int i = 0; i < feature_variation.num_params; ++i) { + params[feature_variation.params[i].param_name] = + feature_variation.params[i].param_value; + } + + bool success = variations::AssociateVariationParams( + feature_trial_name, internal::kTrialGroupAboutFlags, params); + if (success) { + // Successful association also means that no group is created and selected + // for the trial, yet. Thus, create the trial to select the group. This way, + // the parameters cannot get overwritten in later phases (such as from the + // server). + base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial( + feature_trial_name, internal::kTrialGroupAboutFlags); + if (!trial) { + DLOG(WARNING) << "Could not create the trial " << feature_trial_name + << " with group " << internal::kTrialGroupAboutFlags; + } + } +} + } // namespace // Keeps track of affected switches for each FeatureEntry, based on which @@ -224,27 +270,33 @@ e.command_line_value, &name_to_switch_map); break; case FeatureEntry::MULTI_VALUE: - for (int j = 0; j < e.num_choices; ++j) { - AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch, - e.choices[j].command_line_value, - &name_to_switch_map); + for (int j = 0; j < e.num_options; ++j) { + AddSwitchMapping( + e.NameForOption(j), e.ChoiceForOption(j).command_line_switch, + e.ChoiceForOption(j).command_line_value, &name_to_switch_map); } break; case FeatureEntry::ENABLE_DISABLE_VALUE: - AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(), + AddSwitchMapping(e.NameForOption(0), std::string(), std::string(), &name_to_switch_map); - AddSwitchMapping(e.NameForChoice(1), e.command_line_switch, + AddSwitchMapping(e.NameForOption(1), e.command_line_switch, e.command_line_value, &name_to_switch_map); - AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, + AddSwitchMapping(e.NameForOption(2), e.disable_command_line_switch, e.disable_command_line_value, &name_to_switch_map); break; case FeatureEntry::FEATURE_VALUE: - AddFeatureMapping(e.NameForChoice(0), std::string(), false, - &name_to_switch_map); - AddFeatureMapping(e.NameForChoice(1), e.feature->name, true, - &name_to_switch_map); - AddFeatureMapping(e.NameForChoice(2), e.feature->name, false, - &name_to_switch_map); + case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: + for (int j = 0; j < e.num_options; ++j) { + FeatureEntry::FeatureState state = e.StateForOption(j); + if (state == FeatureEntry::FeatureState::DEFAULT) { + AddFeatureMapping(e.NameForOption(j), std::string(), false, + &name_to_switch_map); + } else { + AddFeatureMapping(e.NameForOption(j), e.feature->name, + state == FeatureEntry::FeatureState::ENABLED, + &name_to_switch_map); + } + } break; } } @@ -305,11 +357,11 @@ } else { if (enable) { // Enable the first choice. - needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second; + needs_restart_ |= enabled_entries.insert(e->NameForOption(0)).second; } else { // Find the currently enabled choice and disable it. - for (int i = 0; i < e->num_choices; ++i) { - std::string choice_name = e->NameForChoice(i); + for (int i = 0; i < e->num_options; ++i) { + std::string choice_name = e->NameForOption(i); if (enabled_entries.find(choice_name) != enabled_entries.end()) { needs_restart_ = true; enabled_entries.erase(choice_name); @@ -380,6 +432,38 @@ appended_switches_.clear(); } +void FlagsState::RegisterAllFeatureVariationParameters( + FlagsStorage* flags_storage) { + std::set<std::string> enabled_entries; + GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries); + + for (size_t i = 0; i < num_feature_entries_; ++i) { + const FeatureEntry& e = feature_entries_[i]; + if (e.type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE) { + for (int j = 0; j < e.num_options; ++j) { + const FeatureEntry::FeatureVariation* variation = + e.VariationForOption(j); + if (variation != nullptr && enabled_entries.count(e.NameForOption(j))) { + // If the option is selected by the user & has variation, register it. + RegisterFeatureVariationParameters(e.feature_trial_name, *variation); + // TODO(jkrcal) The code does not associate the feature with the field + // trial |e.feature_trial_name|. The reason is that features + // overridden in chrome://flags are translated to command-line flags + // and thus treated earlier in the initialization. The fix requires + // larger changes. As a result: + // - the API calls to variations::GetVariationParamValueByFeature and + // to variations::GetVariationParamsByFeature do not work; and + // - the API call to base::FeatureList::IsEnabled does not mark the + // field trial as active (and the trial does not appear in UMA). + // If the code calls variations::GetVariationParamValue or + // variations::GetVariationParams providing the trial name, everything + // should work fine. + } + } + } + } +} + void FlagsState::GetFlagFeatureEntries( FlagsStorage* flags_storage, FlagAccess access, @@ -421,7 +505,8 @@ case FeatureEntry::MULTI_VALUE: case FeatureEntry::ENABLE_DISABLE_VALUE: case FeatureEntry::FEATURE_VALUE: - data->Set("choices", CreateChoiceData(entry, enabled_entries)); + case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE: + data->Set("options", CreateOptionsData(entry, enabled_entries)); break; }
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h index e7d2ac1..6f0ff1f 100644 --- a/components/flags_ui/flags_state.h +++ b/components/flags_ui/flags_state.h
@@ -21,6 +21,13 @@ namespace flags_ui { +// Internal functionality exposed for tests. +namespace internal { +// The trial group selected when feature variation parameters are registered via +// FlagsState::RegisterFeatureVariationParameters(). +extern const char kTrialGroupAboutFlags[]; +} // namespace internal + struct FeatureEntry; class FlagsStorage; struct SwitchEntry; @@ -56,6 +63,9 @@ FlagsState(const FeatureEntry* feature_entries, size_t num_feature_entries); ~FlagsState(); + // Reads the state from |flags_storage| and adds the command line flags + // belonging to the active feature entries to |command_line|. Features are + // appended via |enable_features_flag_name| and |disable_features_flag_name|. void ConvertFlagsToSwitches(FlagsStorage* flags_storage, base::CommandLine* command_line, SentinelsMode sentinels, @@ -70,6 +80,10 @@ void ResetAllFlags(FlagsStorage* flags_storage); void Reset(); + // Registers variations parameter values stored in |flags_storage| (previously + // selected in about:flags). + void RegisterAllFeatureVariationParameters(FlagsStorage* flags_storage); + // Gets the list of feature entries. Entries that are available for the // current platform are appended to |supported_entries|; all other entries are // appended to |unsupported_entries|.
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc index 628331b..b95373a5 100644 --- a/components/flags_ui/flags_state_unittest.cc +++ b/components/flags_ui/flags_state_unittest.cc
@@ -15,6 +15,7 @@ #include "base/feature_list.h" #include "base/format_macros.h" #include "base/macros.h" +#include "base/metrics/field_trial.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -26,6 +27,7 @@ #include "components/flags_ui/pref_service_flags_storage.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" +#include "components/variations/variations_associated_data.h" #include "grit/components_strings.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,6 +42,7 @@ const char kFlags5[] = "flag5"; const char kFlags6[] = "flag6"; const char kFlags7[] = "flag7"; +const char kFlags8[] = "flag8"; const char kSwitch1[] = "switch"; const char kSwitch2[] = "switch2"; @@ -57,6 +60,26 @@ const char kEnableFeatures[] = "dummy-enable-features"; const char kDisableFeatures[] = "dummy-disable-features"; +const char kTestTrial[] = "TestTrial"; +const char kTestParam[] = "param"; +const char kTestParamValue1[] = "value1"; +const char kTestParamValue2[] = "value2"; + +const base::Feature kTestFeature1{"FeatureName1", + base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kTestFeature2{"FeatureName2", + base::FEATURE_ENABLED_BY_DEFAULT}; + +const FeatureEntry::FeatureParam kTestVariationDefault[] = { + {kTestParam, kTestParamValue1}}; + +const FeatureEntry::FeatureParam kTestVariationOther[] = { + {kTestParam, kTestParamValue2}}; + +const FeatureEntry::FeatureVariation kTestVariations[] = { + {"", kTestVariationDefault, 1}, + {"dummy description", kTestVariationOther, 1}}; + // Those have to be valid ids for the translation system but the value are // never used, so pick one at random from the current component. const int kDummyNameId = IDS_FLAGS_UI_WARNING_HEADER; @@ -74,44 +97,45 @@ {kDummyDescriptionId, kMultiSwitch2, kValueForMultiSwitch2}, }; -const base::Feature kTestFeature{"FeatureName", - base::FEATURE_ENABLED_BY_DEFAULT}; - // The entries that are set for these tests. The 3rd entry is not supported on // the current platform, all others are. static FeatureEntry kEntries[] = { {kFlags1, kDummyNameId, kDummyDescriptionId, 0, // Ends up being mapped to the current platform. - FeatureEntry::SINGLE_VALUE, kSwitch1, "", nullptr, nullptr, nullptr, - nullptr, 0}, + FeatureEntry::SINGLE_VALUE, kSwitch1, "", nullptr, nullptr, nullptr, 0, + nullptr, nullptr, nullptr}, {kFlags2, kDummyNameId, kDummyDescriptionId, 0, // Ends up being mapped to the current platform. FeatureEntry::SINGLE_VALUE, kSwitch2, kValueForSwitch2, nullptr, nullptr, - nullptr, nullptr, 0}, + nullptr, 0, nullptr, nullptr, nullptr}, {kFlags3, kDummyNameId, kDummyDescriptionId, 0, // This ends up enabling for an OS other than the current. - FeatureEntry::SINGLE_VALUE, kSwitch3, "", nullptr, nullptr, nullptr, - nullptr, 0}, + FeatureEntry::SINGLE_VALUE, kSwitch3, "", nullptr, nullptr, nullptr, 0, + nullptr, nullptr, nullptr}, {kFlags4, kDummyNameId, kDummyDescriptionId, 0, // Ends up being mapped to the current platform. - FeatureEntry::MULTI_VALUE, "", "", "", "", nullptr, kMultiChoices, - arraysize(kMultiChoices)}, + FeatureEntry::MULTI_VALUE, "", "", "", "", nullptr, + arraysize(kMultiChoices), kMultiChoices, nullptr, nullptr}, {kFlags5, kDummyNameId, kDummyDescriptionId, 0, // Ends up being mapped to the current platform. FeatureEntry::ENABLE_DISABLE_VALUE, kSwitch1, kEnableDisableValue1, - kSwitch2, kEnableDisableValue2, nullptr, nullptr, 3}, + kSwitch2, kEnableDisableValue2, nullptr, 3, nullptr, nullptr, nullptr}, {kFlags6, kDummyNameId, kDummyDescriptionId, 0, FeatureEntry::SINGLE_DISABLE_VALUE, kSwitch6, "", nullptr, nullptr, - nullptr, nullptr, 0}, + nullptr, 0, nullptr, nullptr, nullptr}, {kFlags7, kDummyNameId, kDummyDescriptionId, 0, // Ends up being mapped to the current platform. FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr, - &kTestFeature, nullptr, 3}, + &kTestFeature1, 3, nullptr, nullptr, nullptr}, + {kFlags8, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE, nullptr, nullptr, nullptr, + nullptr, &kTestFeature2, 4, nullptr, kTestVariations, kTestTrial}, }; class FlagsStateTest : public ::testing::Test { protected: - FlagsStateTest() : flags_storage_(&prefs_) { + FlagsStateTest() : flags_storage_(&prefs_), trial_list_(nullptr) { prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments); for (size_t i = 0; i < arraysize(kEntries); ++i) @@ -127,6 +151,7 @@ TestingPrefServiceSimple prefs_; PrefServiceFlagsStorage flags_storage_; std::unique_ptr<FlagsState> flags_state_; + base::FieldTrialList trial_list_; }; TEST_F(FlagsStateTest, NoChangeNoRestart) { @@ -157,13 +182,13 @@ ASSERT_EQ(kFlags4, entry.internal_name); EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); // Enable the 2nd choice of the multi-value. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), true); EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); flags_state_->Reset(); EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); // Enable the default choice now. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0), true); EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); } @@ -241,6 +266,42 @@ EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd)); } +TEST_F(FlagsStateTest, RegisterAllFeatureVariationParameters) { + const FeatureEntry& entry = kEntries[7]; + // Select the "Disabled" variation. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0), + true); + flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); + // No value should be associated. + EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam)); + // The trial should not be created. + base::FieldTrial* trial = base::FieldTrialList::Find(kTestTrial); + EXPECT_EQ(nullptr, trial); + + // Select the first "Enabled" variation. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1), + true); + + flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); + // The value should be associated. + EXPECT_EQ(kTestParamValue1, + variations::GetVariationParamValue(kTestTrial, kTestParam)); + + // The trial should be created. + trial = base::FieldTrialList::Find(kTestTrial); + EXPECT_NE(nullptr, trial); + // The about:flags group should be selected for the trial. + EXPECT_EQ(internal::kTrialGroupAboutFlags, trial->group_name()); + + // Select the second "Enabled" variation. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), + true); + flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); + // Associating for the second time should not change the value. + EXPECT_EQ(kTestParamValue1, + variations::GetVariationParamValue(kTestTrial, kTestParam)); +} + base::CommandLine::StringType CreateSwitch(const std::string& value) { #if defined(OS_WIN) return base::ASCIIToUTF16(value); @@ -349,11 +410,11 @@ {0, nullptr, nullptr, nullptr, nullptr}, {0, "A,B", "C", "A,B", "C"}, // "Enable" option: should only affect enabled list. - {1, nullptr, nullptr, "FeatureName", nullptr}, - {1, "A,B", "C", "A,B,FeatureName", "C"}, + {1, nullptr, nullptr, "FeatureName1", nullptr}, + {1, "A,B", "C", "A,B,FeatureName1", "C"}, // "Disable" option: should only affect disabled list. - {2, nullptr, nullptr, nullptr, "FeatureName"}, - {2, "A,B", "C", "A,B", "C,FeatureName"}, + {2, nullptr, nullptr, nullptr, "FeatureName1"}, + {2, "A,B", "C", "A,B", "C,FeatureName1"}, }; for (size_t i = 0; i < arraysize(cases); ++i) { @@ -515,7 +576,7 @@ } // Enable the 2nd choice of the multi-value. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), true); { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -529,7 +590,7 @@ } // Disable the multi-value entry. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0), true); { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -588,7 +649,7 @@ } // "Enable" option selected. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(1), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1), true); { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -601,7 +662,7 @@ } // "Disable" option selected. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), true); { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -614,7 +675,7 @@ } // "Default" option selected, same as nothing selected. - flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0), true); { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -642,13 +703,13 @@ // "Default" option selected, same as nothing selected. {0, nullptr, nullptr, "", ""}, // "Enable" option selected. - {1, nullptr, nullptr, "FeatureName", ""}, + {1, nullptr, nullptr, "FeatureName1", ""}, // "Disable" option selected. - {2, nullptr, nullptr, "", "FeatureName"}, + {2, nullptr, nullptr, "", "FeatureName1"}, // "Enable" option should get added to the existing list. - {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName", ""}, + {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName1", ""}, // "Disable" option should get added to the existing list. - {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName"}, + {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName1"}, }; for (size_t i = 0; i < arraysize(cases); ++i) { @@ -661,7 +722,7 @@ if (cases[i].enabled_choice != -1) { flags_state_->SetFeatureEntryEnabled( - &flags_storage_, entry.NameForChoice(cases[i].enabled_choice), true); + &flags_storage_, entry.NameForOption(cases[i].enabled_choice), true); } base::CommandLine command_line(base::CommandLine::NO_PROGRAM); @@ -691,7 +752,7 @@ &supported_entries, &unsupported_entries, base::Bind(&SkipFeatureEntry)); // All |kEntries| except for |kFlags3| should be supported. - EXPECT_EQ(6u, supported_entries.GetSize()); + EXPECT_EQ(7u, supported_entries.GetSize()); EXPECT_EQ(1u, unsupported_entries.GetSize()); EXPECT_EQ(arraysize(kEntries), supported_entries.GetSize() + unsupported_entries.GetSize());
diff --git a/components/flags_ui/resources/flags.html b/components/flags_ui/resources/flags.html index b29c25a..aca6d35d 100644 --- a/components/flags_ui/resources/flags.html +++ b/components/flags_ui/resources/flags.html
@@ -75,12 +75,12 @@ jsvalues="href: '#' + internal_name" jscontent="'#' + internal_name"></a> </div> - <div jsdisplay="choices && choices.length > 0"> + <div jsdisplay="options && options.length > 0"> <select class="experiment-select" jsvalues=".internal_name:internal_name;.disabled:!enabled"> <option jsvalues=".selected:selected" - jsselect="choices" + jsselect="options" jscontent="description">NAME </option> </select>
diff --git a/components/image_fetcher/image_fetcher_delegate.h b/components/image_fetcher/image_fetcher_delegate.h index dc5b83f..38d66b2 100644 --- a/components/image_fetcher/image_fetcher_delegate.h +++ b/components/image_fetcher/image_fetcher_delegate.h
@@ -5,9 +5,9 @@ #ifndef COMPONENTS_IMAGE_FETCHER_IMAGE_FETCHER_DELEGATE_H_ #define COMPONENTS_IMAGE_FETCHER_IMAGE_FETCHER_DELEGATE_H_ -#include "base/macros.h" +#include <string> -class GURL; +#include "base/macros.h" namespace gfx { class Image; @@ -19,11 +19,18 @@ public: ImageFetcherDelegate() {} - // Called when an image was fetched. |id| is an identifier for the fetch (as - // passed to ImageFetcher::StartOrQueueNetworkRequest); |image| stores image - // data owned by the caller, and can be an empty gfx::Image. + // Called when the data for an image was fetched. |id| is an identifier for + // the fetch (as passed to ImageFetcher::StartOrQueueNetworkRequest); |data| + // stores (generally compressed) image data owned by the caller, and can be + // empty if the fetch failed. + virtual void OnImageDataFetched(const std::string& id, + const std::string& data) {}; + + // Called when an image was fetched and decoded. |id| is an identifier for the + // fetch (as passed to ImageFetcher::StartOrQueueNetworkRequest); |image| + // stores image data owned by the caller, and can be an empty gfx::Image. virtual void OnImageFetched(const std::string& id, - const gfx::Image& image) = 0; + const gfx::Image& image) {}; protected: virtual ~ImageFetcherDelegate() {}
diff --git a/components/ntp_snippets/ntp_snippets_database.cc b/components/ntp_snippets/ntp_snippets_database.cc index c1b66be..9feeacdff 100644 --- a/components/ntp_snippets/ntp_snippets_database.cc +++ b/components/ntp_snippets/ntp_snippets_database.cc
@@ -18,6 +18,10 @@ // synchronize with histograms.xml, AND will also become incompatible with older // browsers still reporting the previous values. const char kDatabaseUMAClientName[] = "NTPSnippets"; +const char kImageDatabaseUMAClientName[] = "NTPSnippetImages"; + +const char kSnippetDatabaseFolder[] = "snippets"; +const char kImageDatabaseFolder[] = "images"; } namespace ntp_snippets { @@ -26,67 +30,116 @@ const base::FilePath& database_dir, scoped_refptr<base::SequencedTaskRunner> file_task_runner) : database_( - new ProtoDatabaseImpl<SnippetProto>(std::move(file_task_runner))), + new ProtoDatabaseImpl<SnippetProto>(file_task_runner)), database_initialized_(false), + image_database_( + new ProtoDatabaseImpl<SnippetImageProto>(file_task_runner)), + image_database_initialized_(false), weak_ptr_factory_(this) { - database_->Init(kDatabaseUMAClientName, database_dir, + base::FilePath snippet_dir = database_dir.AppendASCII(kSnippetDatabaseFolder); + database_->Init(kDatabaseUMAClientName, snippet_dir, base::Bind(&NTPSnippetsDatabase::OnDatabaseInited, weak_ptr_factory_.GetWeakPtr())); + + base::FilePath image_dir = database_dir.AppendASCII(kImageDatabaseFolder); + image_database_->Init(kImageDatabaseUMAClientName, image_dir, + base::Bind(&NTPSnippetsDatabase::OnImageDatabaseInited, + weak_ptr_factory_.GetWeakPtr())); } NTPSnippetsDatabase::~NTPSnippetsDatabase() {} -void NTPSnippetsDatabase::Load(const SnippetsLoadedCallback& callback) { - if (database_ && database_initialized_) - LoadImpl(callback); - else - pending_load_callbacks_.emplace_back(callback); +bool NTPSnippetsDatabase::IsInitialized() const { + return database_ && database_initialized_ && image_database_ && + image_database_initialized_; } -void NTPSnippetsDatabase::Save(const NTPSnippet& snippet) { +void NTPSnippetsDatabase::LoadSnippets(const SnippetsCallback& callback) { + if (IsInitialized()) + LoadSnippetsImpl(callback); + else + pending_snippets_callbacks_.emplace_back(callback); +} + +void NTPSnippetsDatabase::SaveSnippet(const NTPSnippet& snippet) { std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); entries_to_save->emplace_back(snippet.id(), snippet.ToProto()); - SaveImpl(std::move(entries_to_save)); + SaveSnippetsImpl(std::move(entries_to_save)); } -void NTPSnippetsDatabase::Save(const NTPSnippet::PtrVector& snippets) { +void NTPSnippetsDatabase::SaveSnippets(const NTPSnippet::PtrVector& snippets) { std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); for (const std::unique_ptr<NTPSnippet>& snippet : snippets) entries_to_save->emplace_back(snippet->id(), snippet->ToProto()); - SaveImpl(std::move(entries_to_save)); + SaveSnippetsImpl(std::move(entries_to_save)); } -void NTPSnippetsDatabase::Delete(const std::string& snippet_id) { - DeleteImpl(base::WrapUnique(new std::vector<std::string>(1, snippet_id))); +void NTPSnippetsDatabase::DeleteSnippet(const std::string& snippet_id) { + DeleteSnippetsImpl( + base::WrapUnique(new std::vector<std::string>(1, snippet_id))); } -void NTPSnippetsDatabase::Delete(const NTPSnippet::PtrVector& snippets) { +void NTPSnippetsDatabase::DeleteSnippets( + const NTPSnippet::PtrVector& snippets) { std::unique_ptr<std::vector<std::string>> keys_to_remove( new std::vector<std::string>()); for (const std::unique_ptr<NTPSnippet>& snippet : snippets) keys_to_remove->emplace_back(snippet->id()); - DeleteImpl(std::move(keys_to_remove)); + DeleteSnippetsImpl(std::move(keys_to_remove)); +} + +void NTPSnippetsDatabase::LoadImage(const std::string& snippet_id, + const SnippetImageCallback& callback) { + if (IsInitialized()) + LoadImageImpl(snippet_id, callback); + else + pending_image_callbacks_.emplace_back(snippet_id, callback); +} + +void NTPSnippetsDatabase::SaveImage(const std::string& snippet_id, + const std::string& image_data) { + // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()). + if (!IsInitialized()) + return; + + SnippetImageProto image_proto; + image_proto.set_data(image_data); + + std::unique_ptr<ImageKeyEntryVector> entries_to_save( + new ImageKeyEntryVector()); + entries_to_save->emplace_back(snippet_id, std::move(image_proto)); + + image_database_->UpdateEntries( + std::move(entries_to_save), + base::WrapUnique(new std::vector<std::string>()), + base::Bind(&NTPSnippetsDatabase::OnImageDatabaseSaved, + weak_ptr_factory_.GetWeakPtr())); +} + +void NTPSnippetsDatabase::DeleteImage(const std::string& snippet_id) { + DeleteImagesImpl( + base::WrapUnique(new std::vector<std::string>(1, snippet_id))); } void NTPSnippetsDatabase::OnDatabaseInited(bool success) { DCHECK(!database_initialized_); if (!success) { DVLOG(1) << "NTPSnippetsDatabase init failed."; - database_.reset(); + ResetDatabases(); return; } database_initialized_ = true; - for (const SnippetsLoadedCallback& callback : pending_load_callbacks_) - LoadImpl(callback); + if (IsInitialized()) + ProcessPendingLoads(); } void NTPSnippetsDatabase::OnDatabaseLoaded( - const SnippetsLoadedCallback& callback, + const SnippetsCallback& callback, bool success, std::unique_ptr<std::vector<SnippetProto>> entries) { if (!success) { DVLOG(1) << "NTPSnippetsDatabase load failed."; - database_.reset(); + ResetDatabases(); return; } @@ -109,27 +162,77 @@ // If any of the snippet protos couldn't be converted to actual snippets, // clean them up now. if (!keys_to_remove->empty()) - DeleteImpl(std::move(keys_to_remove)); + DeleteSnippetsImpl(std::move(keys_to_remove)); } void NTPSnippetsDatabase::OnDatabaseSaved(bool success) { if (!success) { DVLOG(1) << "NTPSnippetsDatabase save failed."; - database_.reset(); + ResetDatabases(); } } -void NTPSnippetsDatabase::LoadImpl(const SnippetsLoadedCallback& callback) { - DCHECK(database_); - DCHECK(database_initialized_); +void NTPSnippetsDatabase::OnImageDatabaseInited(bool success) { + DCHECK(!image_database_initialized_); + if (!success) { + DVLOG(1) << "NTPSnippetsDatabase init failed."; + ResetDatabases(); + return; + } + image_database_initialized_ = true; + if (IsInitialized()) + ProcessPendingLoads(); +} + +void NTPSnippetsDatabase::OnImageDatabaseLoaded( + const SnippetImageCallback& callback, + bool success, + std::unique_ptr<SnippetImageProto> entry) { + if (!success) { + DVLOG(1) << "NTPSnippetsDatabase load failed."; + ResetDatabases(); + return; + } + + if (!entry) { + callback.Run(std::string()); + return; + } + + std::unique_ptr<std::string> data(entry->release_data()); + callback.Run(std::move(*data)); +} + +void NTPSnippetsDatabase::OnImageDatabaseSaved(bool success) { + if (!success) { + DVLOG(1) << "NTPSnippetsDatabase save failed."; + ResetDatabases(); + } +} + +void NTPSnippetsDatabase::ProcessPendingLoads() { + DCHECK(IsInitialized()); + + for (const auto& callback : pending_snippets_callbacks_) + LoadSnippetsImpl(callback); + pending_snippets_callbacks_.clear(); + + for (const auto& id_callback : pending_image_callbacks_) + LoadImageImpl(id_callback.first, id_callback.second); + pending_image_callbacks_.clear(); +} + +void NTPSnippetsDatabase::LoadSnippetsImpl(const SnippetsCallback& callback) { + DCHECK(IsInitialized()); database_->LoadEntries(base::Bind(&NTPSnippetsDatabase::OnDatabaseLoaded, weak_ptr_factory_.GetWeakPtr(), callback)); } -void NTPSnippetsDatabase::SaveImpl( +void NTPSnippetsDatabase::SaveSnippetsImpl( std::unique_ptr<KeyEntryVector> entries_to_save) { - if (!database_ || !database_initialized_) + // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()). + if (!IsInitialized()) return; std::unique_ptr<std::vector<std::string>> keys_to_remove( @@ -140,11 +243,15 @@ weak_ptr_factory_.GetWeakPtr())); } -void NTPSnippetsDatabase::DeleteImpl( +void NTPSnippetsDatabase::DeleteSnippetsImpl( std::unique_ptr<std::vector<std::string>> keys_to_remove) { - if (!database_ || !database_initialized_) + // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()). + if (!IsInitialized()) return; + DeleteImagesImpl( + base::WrapUnique(new std::vector<std::string>(*keys_to_remove))); + std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); database_->UpdateEntries(std::move(entries_to_save), std::move(keys_to_remove), @@ -152,4 +259,31 @@ weak_ptr_factory_.GetWeakPtr())); } +void NTPSnippetsDatabase::LoadImageImpl(const std::string& snippet_id, + const SnippetImageCallback& callback) { + DCHECK(IsInitialized()); + image_database_->GetEntry( + snippet_id, + base::Bind(&NTPSnippetsDatabase::OnImageDatabaseLoaded, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void NTPSnippetsDatabase::DeleteImagesImpl( + std::unique_ptr<std::vector<std::string>> keys_to_remove) { + // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()). + if (!IsInitialized()) + return; + + image_database_->UpdateEntries( + base::WrapUnique(new ImageKeyEntryVector()), + std::move(keys_to_remove), + base::Bind(&NTPSnippetsDatabase::OnImageDatabaseSaved, + weak_ptr_factory_.GetWeakPtr())); +} + +void NTPSnippetsDatabase::ResetDatabases() { + database_.reset(); + image_database_.reset(); +} + } // namespace ntp_snippets
diff --git a/components/ntp_snippets/ntp_snippets_database.h b/components/ntp_snippets/ntp_snippets_database.h index f421b20..336dad0 100644 --- a/components/ntp_snippets/ntp_snippets_database.h +++ b/components/ntp_snippets/ntp_snippets_database.h
@@ -23,29 +23,47 @@ namespace ntp_snippets { +class SnippetImageProto; class SnippetProto; class NTPSnippetsDatabase { public: - using SnippetsLoadedCallback = base::Callback<void(NTPSnippet::PtrVector)>; + using SnippetsCallback = base::Callback<void(NTPSnippet::PtrVector)>; + using SnippetImageCallback = base::Callback<void(std::string)>; NTPSnippetsDatabase( const base::FilePath& database_dir, scoped_refptr<base::SequencedTaskRunner> file_task_runner); ~NTPSnippetsDatabase(); + // Returns whether the database has finished initialization. While this is + // false, loads may already be started (they'll be serviced after + // initialization finishes), but no updates are allowed. + bool IsInitialized() const; + // Loads all snippets from storage and passes them to |callback|. - void Load(const SnippetsLoadedCallback& callback); + void LoadSnippets(const SnippetsCallback& callback); // Adds or updates the given snippet. - void Save(const NTPSnippet& snippet); + void SaveSnippet(const NTPSnippet& snippet); // Adds or updates all the given snippets. - void Save(const NTPSnippet::PtrVector& snippets); + void SaveSnippets(const NTPSnippet::PtrVector& snippets); - // Deletes the snippet with the given ID. - void Delete(const std::string& snippet_id); - // Deletes all the given snippets (identified by their IDs). - void Delete(const NTPSnippet::PtrVector& snippets); + // Deletes the snippet with the given ID, and its image. + void DeleteSnippet(const std::string& snippet_id); + // Deletes all the given snippets (identified by their IDs) and their images. + void DeleteSnippets(const NTPSnippet::PtrVector& snippets); + + // Loads the image data for the snippet with the given ID and passes it to + // |callback|. Passes an empty string if not found. + void LoadImage(const std::string& snippet_id, + const SnippetImageCallback& callback); + + // Adds or updates the image data for the given snippet ID. + void SaveImage(const std::string& snippet_id, const std::string& image_data); + + // Deletes the image data for the given snippet ID. + void DeleteImage(const std::string& snippet_id); private: friend class NTPSnippetsDatabaseTest; @@ -53,23 +71,46 @@ using KeyEntryVector = leveldb_proto::ProtoDatabase<SnippetProto>::KeyEntryVector; - // Callbacks for ProtoDatabase operations. + using ImageKeyEntryVector = + leveldb_proto::ProtoDatabase<SnippetImageProto>::KeyEntryVector; + + // Callbacks for ProtoDatabase<SnippetProto> operations. void OnDatabaseInited(bool success); - void OnDatabaseLoaded(const SnippetsLoadedCallback& callback, + void OnDatabaseLoaded(const SnippetsCallback& callback, bool success, std::unique_ptr<std::vector<SnippetProto>> entries); void OnDatabaseSaved(bool success); - void LoadImpl(const SnippetsLoadedCallback& callback); + // Callbacks for ProtoDatabase<SnippetImageProto> operations. + void OnImageDatabaseInited(bool success); + void OnImageDatabaseLoaded(const SnippetImageCallback& callback, + bool success, + std::unique_ptr<SnippetImageProto> entry); + void OnImageDatabaseSaved(bool success); - void SaveImpl(std::unique_ptr<KeyEntryVector> entries_to_save); + void ProcessPendingLoads(); - void DeleteImpl(std::unique_ptr<std::vector<std::string>> keys_to_remove); + void LoadSnippetsImpl(const SnippetsCallback& callback); + void SaveSnippetsImpl(std::unique_ptr<KeyEntryVector> entries_to_save); + void DeleteSnippetsImpl( + std::unique_ptr<std::vector<std::string>> keys_to_remove); + + void LoadImageImpl(const std::string& snippet_id, + const SnippetImageCallback& callback); + void DeleteImagesImpl( + std::unique_ptr<std::vector<std::string>> keys_to_remove); + + void ResetDatabases(); std::unique_ptr<leveldb_proto::ProtoDatabase<SnippetProto>> database_; bool database_initialized_; + std::vector<SnippetsCallback> pending_snippets_callbacks_; - std::vector<SnippetsLoadedCallback> pending_load_callbacks_; + std::unique_ptr<leveldb_proto::ProtoDatabase<SnippetImageProto>> + image_database_; + bool image_database_initialized_; + std::vector<std::pair<std::string, SnippetImageCallback>> + pending_image_callbacks_; base::WeakPtrFactory<NTPSnippetsDatabase> weak_ptr_factory_;
diff --git a/components/ntp_snippets/ntp_snippets_database_unittest.cc b/components/ntp_snippets/ntp_snippets_database_unittest.cc index c9f7dcc..5a7cf570 100644 --- a/components/ntp_snippets/ntp_snippets_database_unittest.cc +++ b/components/ntp_snippets/ntp_snippets_database_unittest.cc
@@ -80,8 +80,6 @@ NTPSnippetsDatabase* db() { return db_.get(); } - bool db_inited() { return db_->database_initialized_; } - void OnSnippetsLoaded(NTPSnippet::PtrVector snippets) { OnSnippetsLoadedImpl(snippets); } @@ -101,36 +99,36 @@ ASSERT_FALSE(db()); CreateDatabase(); - EXPECT_FALSE(db_inited()); + EXPECT_FALSE(db()->IsInitialized()); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(db_inited()); + EXPECT_TRUE(db()->IsInitialized()); } TEST_F(NTPSnippetsDatabaseTest, LoadBeforeInit) { CreateDatabase(); - EXPECT_FALSE(db_inited()); + EXPECT_FALSE(db()->IsInitialized()); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(_)); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(db_inited()); + EXPECT_TRUE(db()->IsInitialized()); } TEST_F(NTPSnippetsDatabaseTest, LoadAfterInit) { CreateDatabase(); - EXPECT_FALSE(db_inited()); + EXPECT_FALSE(db()->IsInitialized()); EXPECT_CALL(*this, OnSnippetsLoadedImpl(_)).Times(0); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(db_inited()); + EXPECT_TRUE(db()->IsInitialized()); Mock::VerifyAndClearExpectations(this); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(_)); base::RunLoop().RunUntilIdle(); @@ -139,15 +137,15 @@ TEST_F(NTPSnippetsDatabaseTest, Save) { CreateDatabase(); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(db_inited()); + ASSERT_TRUE(db()->IsInitialized()); std::unique_ptr<NTPSnippet> snippet = CreateTestSnippet(); - db()->Save(*snippet); + db()->SaveSnippet(*snippet); base::RunLoop().RunUntilIdle(); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(ElementsAre(SnippetEq(snippet.get())))); @@ -158,8 +156,8 @@ // The snippet should still exist after recreating the database. CreateDatabase(); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(ElementsAre(SnippetEq(snippet.get())))); @@ -169,21 +167,21 @@ TEST_F(NTPSnippetsDatabaseTest, Update) { CreateDatabase(); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(db_inited()); + ASSERT_TRUE(db()->IsInitialized()); std::unique_ptr<NTPSnippet> snippet = CreateTestSnippet(); - db()->Save(*snippet); + db()->SaveSnippet(*snippet); base::RunLoop().RunUntilIdle(); const std::string text("some text"); snippet->set_snippet(text); - db()->Save(*snippet); + db()->SaveSnippet(*snippet); base::RunLoop().RunUntilIdle(); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(ElementsAre(SnippetEq(snippet.get())))); @@ -193,18 +191,18 @@ TEST_F(NTPSnippetsDatabaseTest, Delete) { CreateDatabase(); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(db_inited()); + ASSERT_TRUE(db()->IsInitialized()); std::unique_ptr<NTPSnippet> snippet = CreateTestSnippet(); - db()->Save(*snippet); + db()->SaveSnippet(*snippet); base::RunLoop().RunUntilIdle(); - db()->Delete(snippet->id()); + db()->DeleteSnippet(snippet->id()); base::RunLoop().RunUntilIdle(); - db()->Load(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, - base::Unretained(this))); + db()->LoadSnippets(base::Bind(&NTPSnippetsDatabaseTest::OnSnippetsLoaded, + base::Unretained(this))); EXPECT_CALL(*this, OnSnippetsLoadedImpl(IsEmpty())); base::RunLoop().RunUntilIdle();
diff --git a/components/ntp_snippets/ntp_snippets_service.cc b/components/ntp_snippets/ntp_snippets_service.cc index 040c1c8..bf55467f 100644 --- a/components/ntp_snippets/ntp_snippets_service.cc +++ b/components/ntp_snippets/ntp_snippets_service.cc
@@ -19,6 +19,7 @@ #include "base/task_runner_util.h" #include "base/time/time.h" #include "base/values.h" +#include "components/image_fetcher/image_decoder.h" #include "components/image_fetcher/image_fetcher.h" #include "components/ntp_snippets/ntp_snippets_constants.h" #include "components/ntp_snippets/ntp_snippets_database.h" @@ -31,6 +32,7 @@ #include "components/variations/variations_associated_data.h" #include "ui/gfx/image/image.h" +using image_fetcher::ImageDecoder; using image_fetcher::ImageFetcher; using suggestions::ChromeSuggestion; using suggestions::SuggestionsProfile; @@ -186,6 +188,7 @@ NTPSnippetsScheduler* scheduler, std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, std::unique_ptr<ImageFetcher> image_fetcher, + std::unique_ptr<ImageDecoder> image_decoder, std::unique_ptr<NTPSnippetsDatabase> database) : state_(State::NOT_INITED), explicitly_disabled_(!enabled), @@ -197,6 +200,7 @@ scheduler_(scheduler), snippets_fetcher_(std::move(snippets_fetcher)), image_fetcher_(std::move(image_fetcher)), + image_decoder_(std::move(image_decoder)), database_(std::move(database)), fetch_after_load_(false) { // TODO(dgn) should be removed after branch point (https:://crbug.com/617585). @@ -209,8 +213,8 @@ // We transition to other states while finalizing the initialization, when the // database is done loading. - database_->Load(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, - base::Unretained(this))); + database_->LoadSnippets(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, + base::Unretained(this))); } NTPSnippetsService::~NTPSnippetsService() { @@ -262,21 +266,10 @@ void NTPSnippetsService::FetchSnippetImage( const std::string& snippet_id, const ImageFetchedCallback& callback) { - auto it = - std::find_if(snippets_.begin(), snippets_.end(), - [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { - return snippet->id() == snippet_id; - }); - if (it == snippets_.end()) { - gfx::Image empty_image; - callback.Run(snippet_id, empty_image); - return; - } - - const NTPSnippet& snippet = *it->get(); - image_fetcher_->StartOrQueueNetworkRequest( - snippet.id(), snippet.salient_image_url(), callback); - // TODO(treib): Cache/persist the snippet image. + database_->LoadImage( + snippet_id, + base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase, + base::Unretained(this), snippet_id, callback)); } void NTPSnippetsService::ClearSnippets() { @@ -286,7 +279,7 @@ if (snippets_.empty()) return; - database_->Delete(snippets_); + database_->DeleteSnippets(snippets_); snippets_.clear(); FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, @@ -317,7 +310,8 @@ (*it)->set_discarded(true); - database_->Save(**it); + database_->SaveSnippet(**it); + database_->DeleteImage((*it)->id()); discarded_snippets_.push_back(std::move(*it)); snippets_.erase(it); @@ -331,7 +325,7 @@ if (!initialized()) return; - database_->Delete(discarded_snippets_); + database_->DeleteSnippets(discarded_snippets_); discarded_snippets_.clear(); } @@ -387,6 +381,24 @@ EnterState(GetStateForDependenciesStatus()); } +// image_fetcher::ImageFetcherDelegate implementation. +void NTPSnippetsService::OnImageDataFetched(const std::string& snippet_id, + const std::string& image_data) { + if (image_data.empty()) + return; + + // Only save the image if the corresponding snippet still exists. + auto it = + std::find_if(snippets_.begin(), snippets_.end(), + [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { + return snippet->id() == snippet_id; + }); + if (it == snippets_.end()) + return; + + database_->SaveImage(snippet_id, image_data); +} + void NTPSnippetsService::OnDatabaseLoaded(NTPSnippet::PtrVector snippets) { DCHECK(state_ == State::NOT_INITED || state_ == State::SHUT_DOWN); if (state_ == State::SHUT_DOWN) @@ -429,7 +441,7 @@ } Compact(&snippets_); // Then delete the removed snippets from the database. - database_->Delete(to_delete); + database_->DeleteSnippets(to_delete); StoreSnippetHostsToPrefs(hosts); @@ -455,17 +467,14 @@ ClearExpiredSnippets(); - // If there are still more snippets than we want to show, move the extra ones - // over into |to_delete|. - NTPSnippet::PtrVector to_delete; + // If there are more snippets than we want to show, delete the extra ones. if (snippets_.size() > kMaxSnippetCount) { - to_delete.insert( - to_delete.end(), + NTPSnippet::PtrVector to_delete( std::make_move_iterator(snippets_.begin() + kMaxSnippetCount), - std::make_move_iterator(snippets_.end())); + std::make_move_iterator(snippets_.end())); snippets_.resize(kMaxSnippetCount); + database_->DeleteSnippets(to_delete); } - database_->Delete(to_delete); UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", snippets_.size()); @@ -533,7 +542,7 @@ } // Save the new snippets to the DB. - database_->Save(new_snippets); + database_->SaveSnippets(new_snippets); // Insert the new snippets at the front. snippets_.insert(snippets_.begin(), @@ -580,7 +589,7 @@ Compact(&discarded_snippets_); // Finally, actually delete the removed snippets from the DB. - database_->Delete(to_delete); + database_->DeleteSnippets(to_delete); // If there are any snippets left, schedule a timer for the next expiry. if (snippets_.empty() && discarded_snippets_.empty()) @@ -601,6 +610,56 @@ base::Unretained(this))); } +void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( + const std::string& snippet_id, + const ImageFetchedCallback& callback, + std::string data) { + // |image_decoder_| is null on iOS and in tests. + if (image_decoder_ && !data.empty()) { + image_decoder_->DecodeImage( + std::move(data), + base::Bind(&NTPSnippetsService::OnSnippetImageDecoded, + base::Unretained(this), snippet_id, callback)); + return; + } + + // Fetching from the DB failed; start a network fetch. + FetchSnippetImageFromNetwork(snippet_id, callback); +} + +void NTPSnippetsService::OnSnippetImageDecoded( + const std::string& snippet_id, + const ImageFetchedCallback& callback, + const gfx::Image& image) { + if (!image.IsEmpty()) { + callback.Run(snippet_id, image); + return; + } + + // If decoding the image failed, delete the DB entry. + database_->DeleteImage(snippet_id); + + FetchSnippetImageFromNetwork(snippet_id, callback); +} + +void NTPSnippetsService::FetchSnippetImageFromNetwork( + const std::string& snippet_id, + const ImageFetchedCallback& callback) { + auto it = + std::find_if(snippets_.begin(), snippets_.end(), + [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { + return snippet->id() == snippet_id; + }); + if (it == snippets_.end()) { + callback.Run(snippet_id, gfx::Image()); + return; + } + + const NTPSnippet& snippet = *it->get(); + image_fetcher_->StartOrQueueNetworkRequest( + snippet.id(), snippet.salient_image_url(), callback); +} + void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { if (fetch_snippets) FetchSnippets(); @@ -643,6 +702,10 @@ snippets_fetcher_->SetCallback( base::Bind(&NTPSnippetsService::OnFetchFinished, base::Unretained(this))); + // |image_fetcher_| can be null in tests. + if (image_fetcher_) + image_fetcher_->SetImageFetcherDelegate(this); + // |sync_service_| can be null in tests or if sync is disabled. // This is a service we want to keep listening to all the time, independently // from the state, since it will allow us to enable or disable the snippets
diff --git a/components/ntp_snippets/ntp_snippets_service.h b/components/ntp_snippets/ntp_snippets_service.h index fad27ab..1b1295c 100644 --- a/components/ntp_snippets/ntp_snippets_service.h +++ b/components/ntp_snippets/ntp_snippets_service.h
@@ -17,6 +17,7 @@ #include "base/observer_list.h" #include "base/scoped_observer.h" #include "base/timer/timer.h" +#include "components/image_fetcher/image_fetcher_delegate.h" #include "components/keyed_service/core/keyed_service.h" #include "components/ntp_snippets/ntp_snippet.h" #include "components/ntp_snippets/ntp_snippets_fetcher.h" @@ -28,6 +29,7 @@ class PrefService; namespace base { +class RefCountedMemory; class Value; } @@ -36,6 +38,7 @@ } namespace image_fetcher { +class ImageDecoder; class ImageFetcher; } @@ -65,7 +68,8 @@ // Stores and vends fresh content data for the NTP. class NTPSnippetsService : public KeyedService, - public sync_driver::SyncServiceObserver { + public sync_driver::SyncServiceObserver, + public image_fetcher::ImageFetcherDelegate { public: using ImageFetchedCallback = base::Callback<void(const std::string& snippet_id, const gfx::Image&)>; @@ -82,6 +86,7 @@ NTPSnippetsScheduler* scheduler, std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher, + std::unique_ptr<image_fetcher::ImageDecoder> image_decoder, std::unique_ptr<NTPSnippetsDatabase> database); ~NTPSnippetsService() override; @@ -197,6 +202,10 @@ // sync_driver::SyncServiceObserver implementation. void OnStateChanged() override; + // image_fetcher::ImageFetcherDelegate implementation. + void OnImageDataFetched(const std::string& snippet_id, + const std::string& image_data) override; + // Callback for the NTPSnippetsDatabase. void OnDatabaseLoaded(NTPSnippet::PtrVector snippets); @@ -222,6 +231,17 @@ void LoadingSnippetsFinished(); + void OnSnippetImageFetchedFromDatabase(const std::string& snippet_id, + const ImageFetchedCallback& callback, + std::string data); + + void OnSnippetImageDecoded(const std::string& snippet_id, + const ImageFetchedCallback& callback, + const gfx::Image& image); + + void FetchSnippetImageFromNetwork(const std::string& snippet_id, + const ImageFetchedCallback& callback); + // Returns whether the service should be enabled or disable depending on its // internal state and the state of its dependencies. State GetStateForDependenciesStatus(); @@ -292,6 +312,7 @@ base::OneShotTimer expiry_timer_; std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher_; + std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_; // The database for persisting snippets. std::unique_ptr<NTPSnippetsDatabase> database_;
diff --git a/components/ntp_snippets/ntp_snippets_service_unittest.cc b/components/ntp_snippets/ntp_snippets_service_unittest.cc index e55dc707..fac43c4 100644 --- a/components/ntp_snippets/ntp_snippets_service_unittest.cc +++ b/components/ntp_snippets/ntp_snippets_service_unittest.cc
@@ -21,6 +21,7 @@ #include "base/test/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "components/image_fetcher/image_decoder.h" #include "components/image_fetcher/image_fetcher.h" #include "components/ntp_snippets/ntp_snippet.h" #include "components/ntp_snippets/ntp_snippets_database.h" @@ -326,7 +327,7 @@ fake_signin_manager_.get(), fake_token_service_.get(), std::move(request_context_getter), base::Bind(&ParseJson), /*is_stable_channel=*/true)), - /*image_fetcher=*/nullptr, + /*image_fetcher=*/nullptr, /*image_decoder=*/nullptr, base::WrapUnique(new NTPSnippetsDatabase(database_dir_.path(), task_runner)))); if (enabled)
diff --git a/components/ntp_snippets/proto/ntp_snippets.proto b/components/ntp_snippets/proto/ntp_snippets.proto index 49d46bcb..0225dc69 100644 --- a/components/ntp_snippets/proto/ntp_snippets.proto +++ b/components/ntp_snippets/proto/ntp_snippets.proto
@@ -25,3 +25,7 @@ repeated SnippetSourceProto sources = 8; optional bool discarded = 9; } + +message SnippetImageProto { + optional bytes data = 1; +}
diff --git a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h index 84e8f8eb..bd3287c 100644 --- a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h +++ b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h
@@ -27,8 +27,6 @@ const std::set<std::string>& scopes, const AccessTokenCallback& callback) override; std::vector<AccountInfo> GetAllAccounts() const override; - AccountInfo GetAccountInfoForEmail(const std::string& email) const override; - AccountInfo GetAccountInfoForGaia(const std::string& gaia) const override; AuthenticationErrorCategory GetAuthenticationErrorCategory( const std::string& gaia_id, NSError* error) const override;
diff --git a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm index a7337f4..763fa823 100644 --- a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm +++ b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm
@@ -32,26 +32,6 @@ } ProfileOAuth2TokenServiceIOSProvider::AccountInfo -FakeProfileOAuth2TokenServiceIOSProvider::GetAccountInfoForEmail( - const std::string& email) const { - for (const auto& account : accounts_) { - if (account.email == email) - return account; - } - return ProfileOAuth2TokenServiceIOSProvider::AccountInfo(); -} - -ProfileOAuth2TokenServiceIOSProvider::AccountInfo -FakeProfileOAuth2TokenServiceIOSProvider::GetAccountInfoForGaia( - const std::string& gaia) const { - for (const auto& account : accounts_) { - if (account.gaia == gaia) - return account; - } - return ProfileOAuth2TokenServiceIOSProvider::AccountInfo(); -} - -ProfileOAuth2TokenServiceIOSProvider::AccountInfo FakeProfileOAuth2TokenServiceIOSProvider::AddAccount(const std::string& gaia, const std::string& email) { ProfileOAuth2TokenServiceIOSProvider::AccountInfo account;
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h b/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h index ed8b3d6a..4bd55c3 100644 --- a/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h +++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h
@@ -56,14 +56,6 @@ // Returns the ids of all accounts. virtual std::vector<AccountInfo> GetAllAccounts() const; - // Returns the account info composed of a GAIA id and email corresponding to - // email |email|. - virtual AccountInfo GetAccountInfoForEmail(const std::string& email) const; - - // Returns the account info composed of a GAIA id and email corresponding to - // GAIA id |gaia|. - virtual AccountInfo GetAccountInfoForGaia(const std::string& gaia) const; - // Starts fetching an access token for the account with id |gaia_id| with // the given |scopes|. Once the token is obtained, |callback| is called. virtual void GetAccessToken(const std::string& gaia_id,
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm index 372bfac..4144c6f 100644 --- a/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm +++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_provider.mm
@@ -9,18 +9,6 @@ return std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>(); } -ProfileOAuth2TokenServiceIOSProvider::AccountInfo -ProfileOAuth2TokenServiceIOSProvider::GetAccountInfoForEmail( - const std::string& email) const { - return ProfileOAuth2TokenServiceIOSProvider::AccountInfo(); -} - -ProfileOAuth2TokenServiceIOSProvider::AccountInfo -ProfileOAuth2TokenServiceIOSProvider::GetAccountInfoForGaia( - const std::string& gaia) const { - return ProfileOAuth2TokenServiceIOSProvider::AccountInfo(); -} - void ProfileOAuth2TokenServiceIOSProvider::GetAccessToken( const std::string& gaia_id, const std::string& client_id,
diff --git a/content/app/DEPS b/content/app/DEPS index dc85fc19..961957d6 100644 --- a/content/app/DEPS +++ b/content/app/DEPS
@@ -3,6 +3,7 @@ "+content", "+device/battery", "+device/bluetooth", + "+device/power_save_blocker", "+device/usb", "+device/vibration", # For loading V8's initial snapshot from external files.
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc index 9956b29..f26a706 100644 --- a/content/app/android/library_loader_hooks.cc +++ b/content/app/android/library_loader_hooks.cc
@@ -26,6 +26,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" #include "device/bluetooth/android/bluetooth_jni_registrar.h" +#include "device/power_save_blocker/power_save_blocker_jni_registrar.h" #include "device/usb/android/usb_jni_registrar.h" #include "media/base/android/media_jni_registrar.h" #include "media/capture/video/android/capture_jni_registrar.h" @@ -77,6 +78,9 @@ if (!device::android::RegisterBluetoothJni(env)) return false; + if (!device::android::RegisterPowerSaveBlockerJni(env)) + return false; + if (!device::android::RegisterUsbJni(env)) return false;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 91fce04..f5c3906 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -57,6 +57,7 @@ "//crypto", "//device/battery", "//device/bluetooth", + "//device/power_save_blocker", "//device/vibration", "//gin", "//google_apis", @@ -291,22 +292,9 @@ if (use_x11) { configs += [ "//build/config/linux:x11" ] - if (!is_chromeos) { - configs += [ "//build/config/linux:xscrnsaver" ] - } deps += [ "//ui/gfx/x" ] } - # Dealing with power_save_blocker_{x11,ozone}.cc is a little complicated - # given the interaction between os_chromeos and the feature flags for X11 and - # ozone, so do it all in one spot. - if (is_chromeos || !use_ozone) { - sources -= [ "power_save_blocker_ozone.cc" ] - } - if (is_chromeos || !use_x11) { - sources -= [ "power_save_blocker_x11.cc" ] - } - # Dealing with *wifi_data_provider_*.cc is also a bit complicated given # android, chromeos, linux and use_dbus. if (is_android) {
diff --git a/content/browser/DEPS b/content/browser/DEPS index f6e95f0d..0297668 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -16,6 +16,7 @@ "+content/app/strings/grit", # For generated headers "+content/public/browser", "+device/battery", # For battery status service. + "+device/power_save_blocker", "+device/vibration", # For Vibration API "+device/vr", # For WebVR API "+gin/v8_initializer.h",
diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc index 3dd22cc..94d214f0 100644 --- a/content/browser/android/browser_jni_registrar.cc +++ b/content/browser/android/browser_jni_registrar.cc
@@ -32,13 +32,13 @@ #include "content/browser/media/android/media_resource_getter_impl.h" #include "content/browser/media/session/media_session_delegate_android.h" #include "content/browser/mojo/service_registrar_android.h" -#include "content/browser/power_save_blocker_android.h" #include "content/browser/renderer_host/ime_adapter_android.h" #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" #include "content/browser/screen_orientation/screen_orientation_delegate_android.h" #include "content/browser/speech/speech_recognizer_impl_android.h" #include "content/browser/time_zone_monitor_android.h" #include "content/browser/web_contents/web_contents_android.h" +#include "device/power_save_blocker/power_save_blocker_android.h" #include "mojo/android/system/core_impl.h" namespace { @@ -63,9 +63,8 @@ {"DateTimePickerAndroid", content::RegisterDateTimeChooserAndroid}, {"DownloadControllerAndroidImpl", content::DownloadControllerAndroidImpl::RegisterDownloadController}, - {"GamepadList", - content::GamepadPlatformDataFetcherAndroid:: - RegisterGamepadPlatformDataFetcherAndroid}, + {"GamepadList", content::GamepadPlatformDataFetcherAndroid:: + RegisterGamepadPlatformDataFetcherAndroid}, {"HandleViewResources", content::CompositedTouchHandleDrawable::RegisterHandleViewResources}, {"InterstitialPageDelegateAndroid", @@ -78,7 +77,6 @@ content::NavigationControllerAndroid::Register}, {"PopupTouchHandleDrawable", content::PopupTouchHandleDrawable::RegisterPopupTouchHandleDrawable}, - {"PowerSaveBlock", content::RegisterPowerSaveBlocker}, {"RegisterImeAdapter", content::RegisterImeAdapter}, {"ScreenOrientationProvider", content::ScreenOrientationDelegateAndroid::Register},
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 41c4d7c8..47e3fb4 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -40,9 +40,9 @@ #include "content/public/common/browser_side_navigation_policy.h" #if defined(OS_ANDROID) -#include "content/browser/power_save_blocker_impl.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/public/browser/render_widget_host_view.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #endif namespace content { @@ -501,10 +501,10 @@ frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder()); #if defined(OS_ANDROID) - power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>( + power_save_blocker_.reset(static_cast<device::PowerSaveBlockerImpl*>( CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonOther, "DevTools") + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonOther, "DevTools") .release())); if (web_contents()->GetNativeView()) { view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>(
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index e5d1d83..249d9d2d 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -23,6 +23,12 @@ class CompositorFrameMetadata; } +#if defined(OS_ANDROID) +namespace device { +class PowerSaveBlockerImpl; +} // namespace device +#endif + namespace content { class BrowserContext; @@ -32,10 +38,6 @@ class NavigationHandle; class RenderFrameHostImpl; -#if defined(OS_ANDROID) -class PowerSaveBlockerImpl; -#endif - namespace devtools { namespace browser { class BrowserHandler; } namespace dom { class DOMHandler; } @@ -171,7 +173,7 @@ std::unique_ptr<devtools::emulation::EmulationHandler> emulation_handler_; std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_; #if defined(OS_ANDROID) - std::unique_ptr<PowerSaveBlockerImpl> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlockerImpl> power_save_blocker_; std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_; #endif std::unique_ptr<DevToolsProtocolHandler> protocol_handler_;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index a32feb9..06393fab 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -30,9 +30,9 @@ #include "content/browser/download/download_manager_impl.h" #include "content/browser/download/download_resource_handler.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/download_danger_type.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/browser/resource_throttle.h" #include "content/public/common/content_features.h" @@ -122,13 +122,14 @@ class DownloadFileWithDelay : public DownloadFileImpl { public: - DownloadFileWithDelay(std::unique_ptr<DownloadSaveInfo> save_info, - const base::FilePath& default_download_directory, - std::unique_ptr<ByteStreamReader> stream, - const net::BoundNetLog& bound_net_log, - std::unique_ptr<PowerSaveBlocker> power_save_blocker, - base::WeakPtr<DownloadDestinationObserver> observer, - base::WeakPtr<DownloadFileWithDelayFactory> owner); + DownloadFileWithDelay( + std::unique_ptr<DownloadSaveInfo> save_info, + const base::FilePath& default_download_directory, + std::unique_ptr<ByteStreamReader> stream, + const net::BoundNetLog& bound_net_log, + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker, + base::WeakPtr<DownloadDestinationObserver> observer, + base::WeakPtr<DownloadFileWithDelayFactory> owner); ~DownloadFileWithDelay() override; @@ -193,7 +194,7 @@ const base::FilePath& default_download_directory, std::unique_ptr<ByteStreamReader> stream, const net::BoundNetLog& bound_net_log, - std::unique_ptr<PowerSaveBlocker> power_save_blocker, + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker, base::WeakPtr<DownloadDestinationObserver> observer, base::WeakPtr<DownloadFileWithDelayFactory> owner) : DownloadFileImpl(std::move(save_info), @@ -254,9 +255,9 @@ std::unique_ptr<ByteStreamReader> stream, const net::BoundNetLog& bound_net_log, base::WeakPtr<DownloadDestinationObserver> observer) { - std::unique_ptr<PowerSaveBlocker> psb(CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonOther, "Download in progress")); + std::unique_ptr<device::PowerSaveBlocker> psb(CreatePowerSaveBlocker( + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, "Download in progress")); return new DownloadFileWithDelay(std::move(save_info), default_download_directory, std::move(stream), @@ -291,12 +292,13 @@ class CountingDownloadFile : public DownloadFileImpl { public: - CountingDownloadFile(std::unique_ptr<DownloadSaveInfo> save_info, - const base::FilePath& default_downloads_directory, - std::unique_ptr<ByteStreamReader> stream, - const net::BoundNetLog& bound_net_log, - std::unique_ptr<PowerSaveBlocker> power_save_blocker, - base::WeakPtr<DownloadDestinationObserver> observer) + CountingDownloadFile( + std::unique_ptr<DownloadSaveInfo> save_info, + const base::FilePath& default_downloads_directory, + std::unique_ptr<ByteStreamReader> stream, + const net::BoundNetLog& bound_net_log, + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker, + base::WeakPtr<DownloadDestinationObserver> observer) : DownloadFileImpl(std::move(save_info), default_downloads_directory, std::move(stream), @@ -350,9 +352,9 @@ std::unique_ptr<ByteStreamReader> stream, const net::BoundNetLog& bound_net_log, base::WeakPtr<DownloadDestinationObserver> observer) override { - std::unique_ptr<PowerSaveBlocker> psb(CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonOther, "Download in progress")); + std::unique_ptr<device::PowerSaveBlocker> psb(CreatePowerSaveBlocker( + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, "Download in progress")); return new CountingDownloadFile(std::move(save_info), default_downloads_directory, std::move(stream),
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc index 2f5b2f1..27965757 100644 --- a/content/browser/download/download_request_core.cc +++ b/content/browser/download/download_request_core.cc
@@ -24,12 +24,12 @@ #include "content/browser/download/download_request_handle.h" #include "content/browser/download/download_stats.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_interrupt_reasons.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager_delegate.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/web_contents.h" #include "net/base/elements_upload_data_stream.h" @@ -205,8 +205,8 @@ DCHECK(delegate_); RecordDownloadCount(UNTHROTTLED_COUNT); power_save_blocker_ = CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonOther, "Download in progress"); + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, "Download in progress"); DownloadRequestData* request_data = DownloadRequestData::Get(request_); if (request_data) { save_info_ = request_data->TakeSaveInfo();
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h index 84eb2e0..6469116 100644 --- a/content/browser/download/download_request_core.h +++ b/content/browser/download/download_request_core.h
@@ -19,6 +19,10 @@ #include "content/public/browser/download_save_info.h" #include "content/public/browser/download_url_parameters.h" +namespace device { +class PowerSaveBlocker; +} // namespace device + namespace net { class HttpResponseHeaders; class URLRequest; @@ -29,7 +33,6 @@ class DownloadManagerImpl; class ByteStreamReader; class ByteStreamWriter; -class PowerSaveBlocker; struct DownloadCreateInfo; // This class encapsulates the core logic for reading data from a URLRequest and @@ -140,7 +143,7 @@ // Keeps the system from sleeping while this is alive. If the // system enters power saving mode while a request is alive, it can cause the // request to fail and the associated download will be interrupted. - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; // The following are used to collect stats. base::TimeTicks download_start_time_;
diff --git a/content/browser/download/drag_download_file_browsertest.cc b/content/browser/download/drag_download_file_browsertest.cc index 8986c39..5821c301 100644 --- a/content/browser/download/drag_download_file_browsertest.cc +++ b/content/browser/download/drag_download_file_browsertest.cc
@@ -14,7 +14,6 @@ #include "content/browser/download/drag_download_util.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/power_save_blocker.h" #include "content/public/common/content_client.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" @@ -23,6 +22,7 @@ #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_browser_context.h" #include "content/shell/browser/shell_download_manager_delegate.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "net/test/url_request/url_request_mock_http_job.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 1585270..9b5f806 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -29,6 +29,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/browser_side_navigation_policy.h" +#include "content/public/common/renderer_preferences.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" @@ -4578,4 +4579,41 @@ } } +// Tests that POST body is not lost when decidePolicyForNavigation tells the +// renderer to route the request via FrameHostMsg_OpenURL sent to the browser. +// See also https://crbug.com/344348. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, PostViaOpenUrlMsg) { + GURL main_url( + embedded_test_server()->GetURL("/form_that_posts_to_echoall.html")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + // Ask the renderer to go through OpenURL FrameHostMsg_OpenURL IPC message. + // Without this, the test wouldn't repro https://crbug.com/344348. + shell() + ->web_contents() + ->GetMutableRendererPrefs() + ->browser_handles_all_top_level_requests = true; + shell()->web_contents()->GetRenderViewHost()->SyncRendererPrefs(); + + // Submit the form. + TestNavigationObserver form_post_observer(shell()->web_contents(), 1); + EXPECT_TRUE(ExecuteScript(shell()->web_contents(), + "document.getElementById('form').submit();")); + form_post_observer.Wait(); + + // Verify that we arrived at the expected location. + GURL target_url(embedded_test_server()->GetURL("/echoall")); + EXPECT_EQ(target_url, shell()->web_contents()->GetLastCommittedURL()); + + // Verify that POST body was correctly passed to the server and ended up in + // the body of the page. + std::string body; + EXPECT_TRUE(ExecuteScriptAndExtractString( + shell()->web_contents(), + "window.domAutomationController.send(" + "document.getElementsByTagName('pre')[0].innerText);", + &body)); + EXPECT_EQ("text=value\n", body); +} + } // namespace content
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index 8c76f22..7270a7c 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h
@@ -110,13 +110,16 @@ // The RenderFrameHostImpl has received a request to open a URL with the // specified |disposition|. - virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host, - const GURL& url, - SiteInstance* source_site_instance, - const Referrer& referrer, - WindowOpenDisposition disposition, - bool should_replace_current_entry, - bool user_gesture) {} + virtual void RequestOpenURL( + RenderFrameHostImpl* render_frame_host, + const GURL& url, + bool uses_post, + const scoped_refptr<ResourceRequestBodyImpl>& body, + SiteInstance* source_site_instance, + const Referrer& referrer, + WindowOpenDisposition disposition, + bool should_replace_current_entry, + bool user_gesture) {} // The RenderFrameHostImpl wants to transfer the request to a new renderer. // |redirect_chain| contains any redirect URLs (excluding |url|) that happened
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 263dd716..c63d436 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -648,13 +648,16 @@ return GetContentClient()->browser()->ShouldAssignSiteForURL(url); } -void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host, - const GURL& url, - SiteInstance* source_site_instance, - const Referrer& referrer, - WindowOpenDisposition disposition, - bool should_replace_current_entry, - bool user_gesture) { +void NavigatorImpl::RequestOpenURL( + RenderFrameHostImpl* render_frame_host, + const GURL& url, + bool uses_post, + const scoped_refptr<ResourceRequestBodyImpl>& body, + SiteInstance* source_site_instance, + const Referrer& referrer, + WindowOpenDisposition disposition, + bool should_replace_current_entry, + bool user_gesture) { // Note: This can be called for subframes (even when OOPIFs are not possible) // if the disposition calls for a different window. @@ -692,6 +695,8 @@ OpenURLParams params(dest_url, referrer, frame_tree_node_id, disposition, ui::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */); + params.uses_post = uses_post; + params.post_data = body; params.source_site_instance = source_site_instance; if (redirect_chain.size() > 0) params.redirect_chain = redirect_chain;
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h index 3ee2c8b..f4df998 100644 --- a/content/browser/frame_host/navigator_impl.h +++ b/content/browser/frame_host/navigator_impl.h
@@ -65,6 +65,8 @@ const std::string& unique_name) override; void RequestOpenURL(RenderFrameHostImpl* render_frame_host, const GURL& url, + bool uses_post, + const scoped_refptr<ResourceRequestBodyImpl>& body, SiteInstance* source_site_instance, const Referrer& referrer, WindowOpenDisposition disposition,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 20a458b..aa02e59a 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2183,9 +2183,9 @@ TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url", validated_url.possibly_invalid_spec()); frame_tree_node_->navigator()->RequestOpenURL( - this, validated_url, source_site_instance, params.referrer, - params.disposition, params.should_replace_current_entry, - params.user_gesture); + this, validated_url, params.uses_post, params.resource_request_body, + source_site_instance, params.referrer, params.disposition, + params.should_replace_current_entry, params.user_gesture); } void RenderFrameHostImpl::Stop() {
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc index 9f7a80c..6ee07fd 100644 --- a/content/browser/frame_host/render_frame_proxy_host.cc +++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -260,11 +260,11 @@ // TODO(alexmos, creis): Figure out whether |params.user_gesture| needs to be // passed in as well. - // TODO(lukasza): https://crbug.com/344348: Pass real method and post_data. frame_tree_node_->navigator()->RequestTransferURL( current_rfh, validated_url, site_instance_.get(), std::vector<GURL>(), params.referrer, ui::PAGE_TRANSITION_LINK, GlobalRequestID(), - params.should_replace_current_entry, "GET", nullptr); + params.should_replace_current_entry, params.uses_post ? "POST" : "GET", + params.resource_request_body); } void RenderFrameProxyHost::OnRouteMessageEvent(
diff --git a/content/browser/loader/DEPS b/content/browser/loader/DEPS index f01c3f6..24dd2400 100644 --- a/content/browser/loader/DEPS +++ b/content/browser/loader/DEPS
@@ -94,6 +94,7 @@ "+content/public/browser/resource_throttle.h", # TODO: these all have to be removed. + "+content/public/browser/browser_thread.h", "+content/public/browser/power_save_blocker_factory.h", ], "resource_dispatcher_host_impl\.(cc|h)": [
diff --git a/content/browser/loader/power_save_block_resource_throttle.cc b/content/browser/loader/power_save_block_resource_throttle.cc index 9ef3e2b..47ce12b 100644 --- a/content/browser/loader/power_save_block_resource_throttle.cc +++ b/content/browser/loader/power_save_block_resource_throttle.cc
@@ -4,7 +4,8 @@ #include "content/browser/loader/power_save_block_resource_throttle.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/public/browser/browser_thread.h" +#include "device/power_save_blocker/power_save_blocker.h" namespace content { @@ -40,9 +41,11 @@ } void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() { - power_save_blocker_ = CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonOther, "Uploading data to " + host_); + power_save_blocker_ = device::PowerSaveBlocker::CreateWithTaskRunners( + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, "Uploading data to " + host_, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); } } // namespace content
diff --git a/content/browser/loader/power_save_block_resource_throttle.h b/content/browser/loader/power_save_block_resource_throttle.h index 3f6f1d36..7e4b9ba 100644 --- a/content/browser/loader/power_save_block_resource_throttle.h +++ b/content/browser/loader/power_save_block_resource_throttle.h
@@ -13,9 +13,11 @@ #include "base/timer/timer.h" #include "content/public/browser/resource_throttle.h" -namespace content { - +namespace device { class PowerSaveBlocker; +} // namespace device + +namespace content { // This ResourceThrottle blocks power save until large upload request finishes. class PowerSaveBlockResourceThrottle : public ResourceThrottle { @@ -33,7 +35,7 @@ const std::string host_; base::OneShotTimer timer_; - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockResourceThrottle); };
diff --git a/content/browser/media/capture/aura_window_capture_machine.cc b/content/browser/media/capture/aura_window_capture_machine.cc index 529d09a8..86f9524 100644 --- a/content/browser/media/capture/aura_window_capture_machine.cc +++ b/content/browser/media/capture/aura_window_capture_machine.cc
@@ -14,8 +14,8 @@ #include "components/display_compositor/gl_helper.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/media/capture/desktop_capture_device_uma_types.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "media/base/video_capture_types.h" #include "media/base/video_util.h" #include "media/capture/content/thread_safe_capture_oracle.h" @@ -87,8 +87,9 @@ power_save_blocker_.reset( CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonOther, "DesktopCaptureDevice is running") + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonOther, + "DesktopCaptureDevice is running") .release()); return true;
diff --git a/content/browser/media/capture/aura_window_capture_machine.h b/content/browser/media/capture/aura_window_capture_machine.h index ceb6e7f..848c325 100644 --- a/content/browser/media/capture/aura_window_capture_machine.h +++ b/content/browser/media/capture/aura_window_capture_machine.h
@@ -18,19 +18,19 @@ #include "ui/compositor/compositor_animation_observer.h" namespace cc { - class CopyOutputResult; - } // namespace cc +namespace device { +class PowerSaveBlocker; +} // namespace device + namespace display_compositor { class ReadbackYUVInterface; } namespace content { -class PowerSaveBlocker; - class AuraWindowCaptureMachine : public media::VideoCaptureMachine, public aura::WindowObserver, @@ -124,7 +124,7 @@ // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the // screen from sleeping for the drive-by web. - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; // WeakPtrs are used for the asynchronous capture callbacks passed to external // modules. They are only valid on the UI thread and become invalidated
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc index 415096a..d468f01 100644 --- a/content/browser/media/capture/desktop_capture_device.cc +++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -20,9 +20,9 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "content/browser/media/capture/desktop_capture_device_uma_types.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "media/base/video_util.h" #include "media/capture/content/capture_resolution_chooser.h" #include "third_party/libyuv/include/libyuv/scale_argb.h" @@ -133,7 +133,7 @@ // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the // screen from sleeping for the drive-by web. - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; DISALLOW_COPY_AND_ASSIGN(Core); }; @@ -174,8 +174,9 @@ power_save_blocker_.reset( CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonOther, "DesktopCaptureDevice is running") + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonOther, + "DesktopCaptureDevice is running") .release()); desktop_capturer_->Start(this);
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index fd3a9c0..55d8533a4 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -10,12 +10,12 @@ #include "build/build_config.h" #include "content/browser/media/audible_metrics.h" #include "content/browser/media/audio_stream_monitor.h" -#include "content/browser/power_save_blocker_impl.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/media/media_player_delegate_messages.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include "ipc/ipc_message_macros.h" namespace content { @@ -185,21 +185,21 @@ void MediaWebContentsObserver::CreateAudioPowerSaveBlocker() { DCHECK(!audio_power_save_blocker_); audio_power_save_blocker_ = CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonAudioPlayback, "Playing audio"); + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonAudioPlayback, "Playing audio"); } void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() { DCHECK(!video_power_save_blocker_); DCHECK(!active_video_players_.empty()); video_power_save_blocker_ = CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonVideoPlayback, "Playing video"); + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonVideoPlayback, "Playing video"); #if defined(OS_ANDROID) if (web_contents()->GetNativeView()) { view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>( web_contents()->GetNativeView())); - static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get()) + static_cast<device::PowerSaveBlockerImpl*>(video_power_save_blocker_.get()) ->InitDisplaySleepBlocker(view_weak_factory_->GetWeakPtr()); } #endif
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h index 281e3e3..540a921 100644 --- a/content/browser/media/media_web_contents_observer.h +++ b/content/browser/media/media_web_contents_observer.h
@@ -20,9 +20,11 @@ #include "ui/android/view_android.h" #endif // OS_ANDROID -namespace content { - +namespace device { class PowerSaveBlocker; +} // namespace device + +namespace content { // This class manages all RenderFrame based media related managers at the // browser side. It receives IPC messages from media RenderFrameObservers and @@ -98,8 +100,8 @@ // Tracking variables and associated power save blockers for media playback. ActiveMediaPlayerMap active_audio_players_; ActiveMediaPlayerMap active_video_players_; - std::unique_ptr<PowerSaveBlocker> audio_power_save_blocker_; - std::unique_ptr<PowerSaveBlocker> video_power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> audio_power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> video_power_save_blocker_; #if defined(OS_ANDROID) std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_; #endif
diff --git a/content/browser/media/webrtc/webrtc_internals.cc b/content/browser/media/webrtc/webrtc_internals.cc index 3046722..de28bb0 100644 --- a/content/browser/media/webrtc/webrtc_internals.cc +++ b/content/browser/media/webrtc/webrtc_internals.cc
@@ -9,10 +9,10 @@ #include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "content/browser/media/webrtc/webrtc_internals_ui_observer.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/browser/web_contents/web_contents_view.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" @@ -501,8 +501,9 @@ DVLOG(1) << ("Preventing the application from being suspended while one or " "more PeerConnections are active."); power_save_blocker_ = content::CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, - PowerSaveBlocker::kReasonOther, "WebRTC has active PeerConnections"); + device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, + device::PowerSaveBlocker::kReasonOther, + "WebRTC has active PeerConnections"); } }
diff --git a/content/browser/media/webrtc/webrtc_internals.h b/content/browser/media/webrtc/webrtc_internals.h index e319313d..ddcb671 100644 --- a/content/browser/media/webrtc/webrtc_internals.h +++ b/content/browser/media/webrtc/webrtc_internals.h
@@ -20,9 +20,12 @@ #include "content/public/browser/render_process_host_observer.h" #include "ui/shell_dialogs/select_file_dialog.h" +namespace device { +class PowerSaveBlocker; +} // namespace device + namespace content { -class PowerSaveBlocker; class WebContents; class WebRTCInternalsUIObserver; @@ -202,7 +205,7 @@ // While |peer_connection_data_| is non-empty, hold an instance of // PowerSaveBlocker. This prevents the application from being suspended while // remoting. - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; // Set of render process hosts that |this| is registered as an observer on. base::hash_set<int> render_process_id_set_;
diff --git a/content/browser/power_save_blocker_android.h b/content/browser/power_save_blocker_android.h deleted file mode 100644 index 1df7d69..0000000 --- a/content/browser/power_save_blocker_android.h +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <jni.h> - -namespace content { - -bool RegisterPowerSaveBlocker(JNIEnv* env); - -} // namespace content
diff --git a/content/browser/power_save_blocker_factory.cc b/content/browser/power_save_blocker_factory.cc index d496029..113e35b 100644 --- a/content/browser/power_save_blocker_factory.cc +++ b/content/browser/power_save_blocker_factory.cc
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/browser/power_save_blocker_factory.h" #include "base/threading/sequenced_worker_pool.h" #include "content/public/browser/browser_thread.h" namespace content { -std::unique_ptr<PowerSaveBlocker> CreatePowerSaveBlocker( - PowerSaveBlocker::PowerSaveBlockerType type, - PowerSaveBlocker::Reason reason, +std::unique_ptr<device::PowerSaveBlocker> CreatePowerSaveBlocker( + device::PowerSaveBlocker::PowerSaveBlockerType type, + device::PowerSaveBlocker::Reason reason, const std::string& description) { - return PowerSaveBlocker::CreateWithTaskRunners( + return device::PowerSaveBlocker::CreateWithTaskRunners( type, reason, description, BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
diff --git a/content/browser/power_save_blocker_factory.h b/content/browser/power_save_blocker_factory.h new file mode 100644 index 0000000..3d430d8a --- /dev/null +++ b/content/browser/power_save_blocker_factory.h
@@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_ +#define CONTENT_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_ + +#include <memory> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" +#include "content/common/content_export.h" +#include "device/power_save_blocker/power_save_blocker.h" + +namespace content { + +CONTENT_EXPORT std::unique_ptr<device::PowerSaveBlocker> CreatePowerSaveBlocker( + device::PowerSaveBlocker::PowerSaveBlockerType type, + device::PowerSaveBlocker::Reason reason, + const std::string& description); + +} // namespace content + +#endif // CONTENT_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index a5ab74c8..b9cc76e 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -82,8 +82,8 @@ #include "ui/snapshot/snapshot.h" #if defined(OS_MACOSX) -#include "content/public/browser/power_save_blocker.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/browser/power_save_blocker_factory.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #endif @@ -1296,8 +1296,8 @@ DCHECK(!power_save_blocker_); power_save_blocker_.reset( CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonOther, "GetSnapshot") + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonOther, "GetSnapshot") .release()); } #endif
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index a957311..502fc12 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -68,6 +68,12 @@ class CompositorFrameAck; } +#if defined(OS_MACOSX) +namespace device { +class PowerSaveBlocker; +} // namespace device +#endif + namespace gfx { class Range; } @@ -87,10 +93,6 @@ struct ResizeParams; struct TextInputState; -#if defined(OS_MACOSX) -class PowerSaveBlocker; -#endif - // This implements the RenderWidgetHost interface that is exposed to // embedders of content, and adds things only visible to content. class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost, @@ -829,7 +831,7 @@ base::TimeDelta new_content_rendering_delay_; #if defined(OS_MACOSX) - std::unique_ptr<PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; #endif base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 68b3476..6b759cee 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -597,9 +597,6 @@ ->GetInputEventRouter() ->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this); } - - if (!render_widget_host_->is_hidden()) - EnsureBrowserCompositorView(); } RenderWidgetHostViewMac::~RenderWidgetHostViewMac() { @@ -643,7 +640,6 @@ // RenderWidgetHostViewMac, RenderWidgetHostView implementation: void RenderWidgetHostViewMac::EnsureBrowserCompositorView() { - DCHECK(!render_widget_host_->is_hidden()); TRACE_EVENT0("browser", "RenderWidgetHostViewMac::EnsureBrowserCompositorView"); @@ -720,7 +716,6 @@ // This should only be reached if |render_widget_host_| is hidden, destroyed, // or in the process of being destroyed. - DCHECK(!render_widget_host_ || render_widget_host_->is_hidden()); DestroyBrowserCompositorView(); } @@ -892,12 +887,8 @@ void RenderWidgetHostViewMac::Show() { ScopedCAActionDisabler disabler; [cocoa_view_ setHidden:NO]; - if (!render_widget_host_->is_hidden()) { - DCHECK_EQ(browser_compositor_state_, BrowserCompositorActive); + if (!render_widget_host_->is_hidden()) return; - } - - WasUnOccluded(); // Re-create the browser compositor. If the DelegatedFrameHost has a cached // frame from the last time it was visible, then it will immediately be @@ -905,6 +896,8 @@ // frame is swapped. EnsureBrowserCompositorView(); + WasUnOccluded(); + // If there is not a frame being currently drawn, kick one, so that the below // pause will have a frame to wait on. render_widget_host_->ScheduleComposite(); @@ -924,11 +917,6 @@ // completes. As a result you won't get a thumbnail for the page unless you // execute these two statements in this specific order. render_widget_host_->WasHidden(); - // Re-check hidden flag, as the thumbnail generation could have called - // WasUnOccluded and unhidden itself. - if (!render_widget_host_->is_hidden()) { - return; - } SuspendBrowserCompositorView(); } DestroySuspendedBrowserCompositorViewIfNeeded(); @@ -944,7 +932,6 @@ render_widget_host_->GetLatencyComponentId(), 0); render_widget_host_->WasShown(renderer_latency_info); - EnsureBrowserCompositorView(); } void RenderWidgetHostViewMac::WasOccluded() { @@ -1507,7 +1494,8 @@ gfx::Size dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size); root_layer_->SetBounds(gfx::Rect(dip_size)); - if (browser_compositor_ && browser_compositor_->compositor()) { + if (!render_widget_host_->is_hidden()) { + EnsureBrowserCompositorView(); browser_compositor_->compositor()->SetScaleAndSize( scale_factor, pixel_size); }
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm index 42275cb5..5a8cfef 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -20,7 +20,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/layout.h" using content::RenderWidgetHostViewMac; @@ -134,10 +133,6 @@ base::mac::ScopedNSAutoreleasePool pool; - base::MessageLoop message_loop; - ui::WindowResizeHelperMac::Get()->Init( - base::MessageLoop::current()->task_runner()); - // Owned by its |cocoa_view()|, i.e. |rwhv_cocoa|. RenderWidgetHostViewMac* rwhv_mac = new RenderWidgetHostViewMac( render_widget, false); @@ -162,10 +157,11 @@ rwhv_cocoa.reset(); pool.Recycle(); - // The |render_widget|'s process needs to be deleted within |message_loop|. - delete render_widget; - - ui::WindowResizeHelperMac::Get()->ShutdownForTests(); + { + // The |render_widget|'s process needs to be deleted within |message_loop|. + base::MessageLoop message_loop; + delete render_widget; + } } // Test RenderWidgetHostViewMacEditCommandHelper::AddEditingSelectorsToClass
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index cd5835c..f9d6d7f 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -87,8 +87,8 @@ GURL extension_url("https://bar.com/simple_page.html"); WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents()); wc->GetFrameTree()->root()->navigator()->RequestOpenURL( - wc->GetFrameTree()->root()->current_frame_host(), extension_url, nullptr, - Referrer(), CURRENT_TAB, false, true); + wc->GetFrameTree()->root()->current_frame_host(), extension_url, false, + nullptr, nullptr, Referrer(), CURRENT_TAB, false, true); // Since the navigation above requires a cross-process swap, there will be a // speculative/pending RenderFrameHost. Ensure it exists and is in a different
diff --git a/content/browser/wake_lock/wake_lock_service_context.cc b/content/browser/wake_lock/wake_lock_service_context.cc index 1f0f0c5..48d3454 100644 --- a/content/browser/wake_lock/wake_lock_service_context.cc +++ b/content/browser/wake_lock/wake_lock_service_context.cc
@@ -8,13 +8,13 @@ #include "base/bind.h" #include "build/build_config.h" -#include "content/browser/power_save_blocker_impl.h" +#include "content/browser/power_save_blocker_factory.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/power_save_blocker_factory.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/service_registry.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" namespace content { @@ -69,8 +69,8 @@ void WakeLockServiceContext::CreateWakeLock() { DCHECK(!wake_lock_); wake_lock_ = CreatePowerSaveBlocker( - PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, - PowerSaveBlocker::kReasonOther, "Wake Lock API"); + device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, + device::PowerSaveBlocker::kReasonOther, "Wake Lock API"); #if defined(OS_ANDROID) // On Android, additionaly associate the blocker with this WebContents. @@ -79,7 +79,7 @@ if (web_contents()->GetNativeView()) { view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>( web_contents()->GetNativeView())); - static_cast<PowerSaveBlockerImpl*>(wake_lock_.get()) + static_cast<device::PowerSaveBlockerImpl*>(wake_lock_.get()) ->InitDisplaySleepBlocker(view_weak_factory_->GetWeakPtr()); } #endif
diff --git a/content/browser/wake_lock/wake_lock_service_context.h b/content/browser/wake_lock/wake_lock_service_context.h index 28ce108..31bd1cb 100644 --- a/content/browser/wake_lock/wake_lock_service_context.h +++ b/content/browser/wake_lock/wake_lock_service_context.h
@@ -20,9 +20,12 @@ #include "ui/android/view_android.h" #endif // OS_ANDROID +namespace device { +class PowerSaveBlocker; +} // namespace device + namespace content { -class PowerSaveBlocker; class RenderFrameHost; class WebContents; @@ -62,7 +65,7 @@ std::set<std::pair<int, int>> frames_requesting_lock_; // The actual power save blocker for screen. - std::unique_ptr<PowerSaveBlocker> wake_lock_; + std::unique_ptr<device::PowerSaveBlocker> wake_lock_; #if defined(OS_ANDROID) std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_; #endif
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 520b312..e3ae870 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -452,6 +452,9 @@ // the browser process should look for an existing history item for the frame. IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params) IPC_STRUCT_MEMBER(GURL, url) + IPC_STRUCT_MEMBER(bool, uses_post) + IPC_STRUCT_MEMBER(scoped_refptr<content::ResourceRequestBodyImpl>, + resource_request_body) IPC_STRUCT_MEMBER(content::Referrer, referrer) IPC_STRUCT_MEMBER(WindowOpenDisposition, disposition) IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index c01062f..09ded70 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -18,6 +18,7 @@ '../device/battery/battery.gyp:device_battery_mojo_bindings', '../device/bluetooth/bluetooth.gyp:device_bluetooth', '../device/usb/usb.gyp:device_usb', + '../device/power_save_blocker/power_save_blocker.gyp:device_power_save_blocker', '../device/vibration/vibration.gyp:device_vibration', '../device/vibration/vibration.gyp:device_vibration_mojo_bindings', '../gin/gin.gyp:gin', @@ -102,6 +103,7 @@ ], 'variables': { 'public_browser_sources': [ + 'browser/power_save_blocker_factory.h', 'public/browser/access_token_store.h', 'public/browser/android/browser_media_player_manager_register.cc', 'public/browser/android/browser_media_player_manager_register.h', @@ -253,8 +255,6 @@ 'public/browser/plugin_data_remover.h', 'public/browser/plugin_service.h', 'public/browser/plugin_service_filter.h', - 'public/browser/power_save_blocker.h', - 'public/browser/power_save_blocker_factory.h', 'public/browser/presentation_screen_availability_listener.h', 'public/browser/presentation_service_delegate.h', 'public/browser/presentation_session.cc', @@ -1174,15 +1174,7 @@ 'browser/permissions/permission_service_impl.h', 'browser/power_monitor_message_broadcaster.cc', 'browser/power_monitor_message_broadcaster.h', - 'browser/power_save_blocker_android.h', - 'browser/power_save_blocker_chromeos.cc', 'browser/power_save_blocker_factory.cc', - 'browser/power_save_blocker_impl.cc', - 'browser/power_save_blocker_impl.h', - 'browser/power_save_blocker_mac.cc', - 'browser/power_save_blocker_ozone.cc', - 'browser/power_save_blocker_win.cc', - 'browser/power_save_blocker_x11.cc', 'browser/power_usage_monitor_impl.cc', 'browser/power_usage_monitor_impl.h', 'browser/presentation/presentation_service_impl.cc', @@ -1710,7 +1702,6 @@ 'browser/android/tracing_controller_android.h', 'browser/android/web_contents_observer_proxy.cc', 'browser/android/web_contents_observer_proxy.h', - 'browser/power_save_blocker_android.cc', 'browser/renderer_host/compositor_impl_android.cc', 'browser/renderer_host/compositor_impl_android.h', 'browser/renderer_host/ime_adapter_android.cc', @@ -1766,8 +1757,8 @@ 'browser/compositor/browser_compositor_output_surface.h', 'browser/compositor/gpu_browser_compositor_output_surface.cc', 'browser/compositor/gpu_browser_compositor_output_surface.h', - 'browser/compositor/gpu_output_surface_mac.mm', 'browser/compositor/gpu_output_surface_mac.h', + 'browser/compositor/gpu_output_surface_mac.mm', 'browser/compositor/gpu_process_transport_factory.cc', 'browser/compositor/gpu_process_transport_factory.h', 'browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc', @@ -2111,8 +2102,6 @@ 'sources!': [ 'browser/device_sensors/data_fetcher_shared_memory_default.cc', 'browser/geolocation/wifi_data_provider_linux.cc', - 'browser/power_save_blocker_ozone.cc', - 'browser/power_save_blocker_x11.cc', ], }], ['os_bsd==1', {
diff --git a/content/content_jni.gypi b/content/content_jni.gypi index 141c169..5ed0cc7 100644 --- a/content/content_jni.gypi +++ b/content/content_jni.gypi
@@ -31,7 +31,6 @@ 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/MediaThrottler.java', 'public/android/java/src/org/chromium/content/browser/MotionEventSynthesizer.java', - 'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java', 'public/android/java/src/org/chromium/content/browser/ServiceRegistrar.java', 'public/android/java/src/org/chromium/content/browser/ServiceRegistry.java', 'public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 1f59c45..bcd6f4c 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -985,11 +985,6 @@ '../third_party/libvpx/libvpx.gyp:libvpx', ], }], - ['OS=="mac"', { - 'dependencies': [ - '../ui/accelerated_widget_mac/accelerated_widget_mac.gyp:accelerated_widget_mac', - ], - }], ['OS=="android"', { 'dependencies': [ '../ui/android/ui_android.gyp:ui_android',
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 0c181c7..61e90bc 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -35,6 +35,7 @@ "//device/battery:mojo_bindings_java", "//device/battery/android:battery_monitor_android", "//device/bluetooth:java", + "//device/power_save_blocker:java", "//device/usb:java", "//device/vibration:mojo_bindings_java", "//device/vibration/android:vibration_manager_android", @@ -132,7 +133,6 @@ "java/src/org/chromium/content/browser/PepperPluginManager.java", "java/src/org/chromium/content/browser/PopupZoomer.java", "java/src/org/chromium/content/browser/PositionObserver.java", - "java/src/org/chromium/content/browser/PowerSaveBlocker.java", "java/src/org/chromium/content/browser/RenderCoordinates.java", "java/src/org/chromium/content/browser/SPenSupport.java", "java/src/org/chromium/content/browser/ScreenOrientationListener.java",
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 4107dd9..e1d56fa9 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -24,6 +24,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.FlakyTest; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; @@ -628,6 +629,7 @@ @CommandLineFlags.Add("enable-features=ImeThread") @MediumTest @Feature({"TextInput"}) + @FlakyTest public void testPasteLongText() throws Exception { int textLength = 25000; String text = new String(new char[textLength]).replace("\0", "a");
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 6b1faf1..a8c4629 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -43,6 +43,7 @@ "//cc", "//content/browser", # Must not be public_deps! "//content/public/common:common_sources", + "//device/power_save_blocker", "//gpu", "//media", "//net",
diff --git a/content/public/browser/power_save_blocker_factory.h b/content/public/browser/power_save_blocker_factory.h deleted file mode 100644 index a40c0ce..0000000 --- a/content/public/browser/power_save_blocker_factory.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_ -#define CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_ - -#include <memory> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "content/common/content_export.h" -#include "content/public/browser/power_save_blocker.h" - -namespace content { - -CONTENT_EXPORT std::unique_ptr<PowerSaveBlocker> CreatePowerSaveBlocker( - PowerSaveBlocker::PowerSaveBlockerType type, - PowerSaveBlocker::Reason reason, - const std::string& description); - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_FACTORY_H_
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index 8983d7a..35d4ca6 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -37,10 +37,6 @@ #include "ui/wm/core/default_activation_client.h" #endif -#if defined(OS_MACOSX) -#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" -#endif - namespace content { // RenderFrameHostTester ------------------------------------------------------ @@ -215,11 +211,6 @@ if (IsBrowserSideNavigationEnabled()) BrowserSideNavigationSetUp(); - -#if defined(OS_MACOSX) - ui::WindowResizeHelperMac::Get()->Init( - base::MessageLoop::current()->task_runner()); -#endif // OS_MACOSX } void RenderViewHostTestHarness::TearDown() { @@ -235,10 +226,6 @@ // before we destroy the browser context. base::RunLoop().RunUntilIdle(); -#if defined(OS_MACOSX) - ui::WindowResizeHelperMac::Get()->ShutdownForTests(); -#endif // OS_MACOSX - #if defined(OS_WIN) ole_initializer_.reset(); #endif
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc index 68aefcbf..272a70f 100644 --- a/content/renderer/media/media_stream_audio_processor.cc +++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -136,6 +136,11 @@ thread_checker_.DetachFromThread(); } + void ReattachThreadChecker() { + thread_checker_.DetachFromThread(); + DCHECK(thread_checker_.CalledOnValidThread()); + } + media::AudioBus* bus() { DCHECK(thread_checker_.CalledOnValidThread()); return bus_.get(); @@ -194,6 +199,12 @@ thread_checker_.DetachFromThread(); } + void ReattachThreadChecker() { + thread_checker_.DetachFromThread(); + DCHECK(thread_checker_.CalledOnValidThread()); + destination_->ReattachThreadChecker(); + } + void Push(const media::AudioBus& source, base::TimeDelta audio_delay) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(source.channels(), source_channels_); @@ -474,6 +485,12 @@ render_fifo_.reset(); } +void MediaStreamAudioProcessor::OnRenderThreadChanged() { + render_thread_checker_.DetachFromThread(); + DCHECK(render_thread_checker_.CalledOnValidThread()); + render_fifo_->ReattachThreadChecker(); +} + void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) { stats->typing_noise_detected = (base::subtle::Acquire_Load(&typing_detected_) != false);
diff --git a/content/renderer/media/media_stream_audio_processor.h b/content/renderer/media/media_stream_audio_processor.h index 6629015..7cf9af0 100644 --- a/content/renderer/media/media_stream_audio_processor.h +++ b/content/renderer/media/media_stream_audio_processor.h
@@ -124,6 +124,7 @@ int sample_rate, int audio_delay_milliseconds) override; void OnPlayoutDataSourceChanged() override; + void OnRenderThreadChanged() override; // webrtc::AudioProcessorInterface implementation. // This method is called on the libjingle thread.
diff --git a/content/renderer/media/rtc_video_encoder.cc b/content/renderer/media/rtc_video_encoder.cc index 4ce16d5..cb7752b 100644 --- a/content/renderer/media/rtc_video_encoder.cc +++ b/content/renderer/media/rtc_video_encoder.cc
@@ -453,10 +453,10 @@ size_t payload_size, bool key_frame, base::TimeDelta timestamp) { - DVLOG(3) << "Impl::BitstreamBufferReady(): " - "bitstream_buffer_id=" << bitstream_buffer_id - << ", payload_size=" << payload_size - << ", key_frame=" << key_frame; + DVLOG(3) << "Impl::BitstreamBufferReady(): bitstream_buffer_id=" + << bitstream_buffer_id << ", payload_size=" << payload_size + << ", key_frame=" << key_frame + << ", timestamp ms=" << timestamp.InMilliseconds(); DCHECK(thread_checker_.CalledOnValidThread()); if (bitstream_buffer_id < 0 || @@ -473,11 +473,17 @@ } output_buffers_free_count_--; + // CrOS Nyan provides invalid timestamp. Use the current time for now. + // TODO(wuchengli): use the timestamp in BitstreamBufferReady after Nyan is + // fixed. http://crbug.com/620565. + const int64_t capture_time_us = rtc::TimeMicros(); + // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). - // This is based on how input timestamps are calculated in - // webrtc/video/video_capture_input.cc. - const uint32_t rtp_timestamp = - static_cast<uint32_t>(timestamp.InMilliseconds()) * 90; + const int64_t capture_time_ms = + capture_time_us / base::Time::kMicrosecondsPerMillisecond; + + const uint32_t rtp_timestamp = static_cast<uint32_t>( + capture_time_us * 90 / base::Time::kMicrosecondsPerMillisecond); webrtc::EncodedImage image( reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, @@ -485,7 +491,7 @@ image._encodedWidth = input_visible_size_.width(); image._encodedHeight = input_visible_size_.height(); image._timeStamp = rtp_timestamp; - image.capture_time_ms_ = timestamp.InMilliseconds(); + image.capture_time_ms_ = capture_time_ms; image._frameType = (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); image._completeFrame = true;
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc index 7f46506..2cb2eac 100644 --- a/content/renderer/media/webrtc_audio_device_impl.cc +++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -4,6 +4,7 @@ #include "content/renderer/media/webrtc_audio_device_impl.h" +#include "base/logging.h" #include "base/metrics/histogram.h" #include "base/strings/string_util.h" #include "base/win/windows_version.h" @@ -62,9 +63,15 @@ int sample_rate, int audio_delay_milliseconds, base::TimeDelta* current_time) { - DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); { base::AutoLock auto_lock(lock_); +#if DCHECK_IS_ON() + DCHECK(renderer_->CurrentThreadIsRenderingThread()); + if (!audio_renderer_thread_checker_.CalledOnValidThread()) { + for (const auto& sink : playout_sinks_) + sink->OnRenderThreadChanged(); + } +#endif if (!playing_) { // Force silence to AudioBus after stopping playout in case // there is lingering audio data in AudioBus.
diff --git a/content/renderer/media/webrtc_audio_device_impl.h b/content/renderer/media/webrtc_audio_device_impl.h index 6af4a86..1e3f05f1 100644 --- a/content/renderer/media/webrtc_audio_device_impl.h +++ b/content/renderer/media/webrtc_audio_device_impl.h
@@ -219,7 +219,7 @@ class Sink { public: // Callback to get the playout data. - // Called on the render audio thread. + // Called on the audio render thread. virtual void OnPlayoutData(media::AudioBus* audio_bus, int sample_rate, int audio_delay_milliseconds) = 0; @@ -228,6 +228,11 @@ // Called on the main render thread. virtual void OnPlayoutDataSourceChanged() = 0; + // Called to notify that the audio render thread has changed, and + // OnPlayoutData() will from now on be called on the new thread. + // Called on the new audio render thread. + virtual void OnRenderThreadChanged() = 0; + protected: virtual ~Sink() {} };
diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc index f508a541..d5dec1b 100644 --- a/content/renderer/media/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc_audio_renderer.cc
@@ -208,7 +208,6 @@ WebRtcLogMessage(base::StringPrintf( "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", source_render_frame_id, session_id, sink_params_.effects())); - audio_renderer_thread_checker_.DetachFromThread(); } WebRtcAudioRenderer::~WebRtcAudioRenderer() { @@ -240,7 +239,7 @@ PrepareSink(); { // No need to reassert the preconditions because the other thread accessing - // the fields (checked by |audio_renderer_thread_checker_|) only reads them. + // the fields only reads them. base::AutoLock auto_lock(lock_); source_ = source; @@ -266,6 +265,10 @@ return start_ref_count_ != 0; } +bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { + return sink_->CurrentThreadIsRenderingThread(); +} + void WebRtcAudioRenderer::Start() { DVLOG(1) << "WebRtcAudioRenderer::Start()"; DCHECK(thread_checker_.CalledOnValidThread()); @@ -406,7 +409,6 @@ // callback may currently be executing and trying to grab the lock while we're // stopping the thread on which it runs. sink_->Stop(); - audio_renderer_thread_checker_.DetachFromThread(); sink_ = new_sink; output_device_id_ = device_id; security_origin_ = security_origin; @@ -423,7 +425,7 @@ int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus, uint32_t frames_delayed, uint32_t frames_skipped) { - DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); + DCHECK(sink_->CurrentThreadIsRenderingThread()); base::AutoLock auto_lock(lock_); if (!source_) return 0; @@ -480,7 +482,7 @@ // Called by AudioPullFifo when more data is necessary. void WebRtcAudioRenderer::SourceCallback( int fifo_frame_delay, media::AudioBus* audio_bus) { - DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); + DCHECK(sink_->CurrentThreadIsRenderingThread()); base::TimeTicks start_time = base::TimeTicks::Now(); DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" << fifo_frame_delay << ", "
diff --git a/content/renderer/media/webrtc_audio_renderer.h b/content/renderer/media/webrtc_audio_renderer.h index f13ac8d..1e0a335 100644 --- a/content/renderer/media/webrtc_audio_renderer.h +++ b/content/renderer/media/webrtc_audio_renderer.h
@@ -109,6 +109,9 @@ int sample_rate() const { return sink_params_.sample_rate(); } int frames_per_buffer() const { return sink_params_.frames_per_buffer(); } + // Returns true if called on rendering thread, otherwise false. + bool CurrentThreadIsRenderingThread(); + private: // MediaStreamAudioRenderer implementation. This is private since we want // callers to use proxy objects. @@ -155,7 +158,6 @@ // Used to DCHECK that we are called on the correct thread. base::ThreadChecker thread_checker_; - base::ThreadChecker audio_renderer_thread_checker_; // Flag to keep track the state of the renderer. State state_;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 5f3ab60..b57c63c 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -808,6 +808,10 @@ ssl_status.connection_status); } +bool IsHttpPost(const blink::WebURLRequest& request) { + return request.httpMethod().utf8() == "POST"; +} + #if defined(OS_ANDROID) // Returns true if WMPI should be used for playback, false otherwise. // @@ -2989,8 +2993,9 @@ request.url(), referrer, suggested_name)); } else { - OpenURL(request.url(), referrer, policy, should_replace_current_entry, - false); + OpenURL(request.url(), IsHttpPost(request), + GetRequestBodyForWebURLRequest(request), referrer, policy, + should_replace_current_entry, false); } } @@ -4890,8 +4895,9 @@ if (is_content_initiated && IsTopLevelNavigation(frame_) && render_view_->renderer_preferences_ .browser_handles_all_top_level_requests) { - OpenURL(url, referrer, info.defaultPolicy, info.replacesCurrentHistoryItem, - false); + OpenURL(url, IsHttpPost(info.urlRequest), + GetRequestBodyForWebURLRequest(info.urlRequest), referrer, + info.defaultPolicy, info.replacesCurrentHistoryItem, false); return blink::WebNavigationPolicyIgnore; // Suppress the load here. } @@ -4900,8 +4906,9 @@ // FrameNavigationEntry. If none is found, fall back to the default url. if (SiteIsolationPolicy::UseSubframeNavigationEntries() && info.isHistoryNavigationInNewChildFrame && is_content_initiated) { - OpenURL(url, referrer, info.defaultPolicy, info.replacesCurrentHistoryItem, - true); + OpenURL(url, IsHttpPost(info.urlRequest), + GetRequestBodyForWebURLRequest(info.urlRequest), referrer, + info.defaultPolicy, info.replacesCurrentHistoryItem, true); // Suppress the load in Blink but mark the frame as loading. return blink::WebNavigationPolicyHandledByClient; } @@ -4916,15 +4923,6 @@ // an extension or app origin, leaving a WebUI page, etc). We only care about // top-level navigations (not iframes). But we sometimes navigate to // about:blank to clear a tab, and we want to still allow that. - // - // Note: this is known to break POST submissions when crossing process - // boundaries until http://crbug.com/101395 is fixed. This is better for - // security than loading a WebUI, extension or app page in the wrong process. - // POST requests don't work because this mechanism does not preserve form - // POST data. We will need to send the request's httpBody data up to the - // browser process, and issue a special POST navigation in WebKit (via - // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl - // for examples of how to send the httpBody data. if (!frame_->parent() && is_content_initiated && !url.SchemeIs(url::kAboutScheme)) { bool send_referrer = false; @@ -4964,7 +4962,9 @@ } if (should_fork) { - OpenURL(url, send_referrer ? referrer : Referrer(), info.defaultPolicy, + OpenURL(url, IsHttpPost(info.urlRequest), + GetRequestBodyForWebURLRequest(info.urlRequest), + send_referrer ? referrer : Referrer(), info.defaultPolicy, info.replacesCurrentHistoryItem, false); return blink::WebNavigationPolicyIgnore; // Suppress the load here. } @@ -5004,8 +5004,9 @@ if (is_fork) { // Open the URL via the browser, not via WebKit. - OpenURL(url, Referrer(), info.defaultPolicy, - info.replacesCurrentHistoryItem, false); + OpenURL(url, IsHttpPost(info.urlRequest), + GetRequestBodyForWebURLRequest(info.urlRequest), Referrer(), + info.defaultPolicy, info.replacesCurrentHistoryItem, false); return blink::WebNavigationPolicyIgnore; } @@ -5335,13 +5336,18 @@ #endif #endif -void RenderFrameImpl::OpenURL(const GURL& url, - const Referrer& referrer, - WebNavigationPolicy policy, - bool should_replace_current_entry, - bool is_history_navigation_in_new_child) { +void RenderFrameImpl::OpenURL( + const GURL& url, + bool uses_post, + const scoped_refptr<ResourceRequestBodyImpl>& resource_request_body, + const Referrer& referrer, + WebNavigationPolicy policy, + bool should_replace_current_entry, + bool is_history_navigation_in_new_child) { FrameHostMsg_OpenURL_Params params; params.url = url; + params.uses_post = uses_post; + params.resource_request_body = resource_request_body; params.referrer = referrer; params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 77ab89e..8c2b6010 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -17,6 +17,7 @@ #include "base/id_map.h" #include "base/macros.h" #include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/process/process_handle.h" @@ -852,11 +853,14 @@ // |is_history_navigation_in_new_child| is true, the browser process should // look for a matching FrameNavigationEntry in the last committed entry to use // instead of |url|. - void OpenURL(const GURL& url, - const Referrer& referrer, - blink::WebNavigationPolicy policy, - bool should_replace_current_entry, - bool is_history_navigation_in_new_child); + void OpenURL( + const GURL& url, + bool uses_post, + const scoped_refptr<ResourceRequestBodyImpl>& resource_request_body, + const Referrer& referrer, + blink::WebNavigationPolicy policy, + bool should_replace_current_entry, + bool is_history_navigation_in_new_child); // Performs a navigation in the frame. This provides a unified function for // the current code path and the browser-side navigation path (in
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 1dd8b44..74bcd08 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" +#include "content/child/web_url_request_util.h" #include "content/child/webmessageportchannel_impl.h" #include "content/common/content_security_policy_header.h" #include "content/common/frame_messages.h" @@ -446,6 +447,8 @@ bool should_replace_current_entry) { FrameHostMsg_OpenURL_Params params; params.url = request.url(); + params.uses_post = request.httpMethod().utf8() == "POST"; + params.resource_request_body = GetRequestBodyForWebURLRequest(request); params.referrer = Referrer( blink::WebStringToGURL( request.httpHeaderField(blink::WebString::fromUTF8("Referer"))),
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 61f8529..a59f6e4f 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -197,10 +197,6 @@ if (v8_use_external_startup_data) { deps += [ "//gin:gin" ] } - - if (is_mac) { - deps += [ "//ui/accelerated_widget_mac" ] - } } # browsertest_support can be used by targets that run content_shell based @@ -796,7 +792,6 @@ deps += [ "//third_party/mozilla", "//third_party/ocmock", - "//ui/accelerated_widget_mac", ] } if (is_chromeos) {
diff --git a/content/test/data/form_that_posts_to_echoall.html b/content/test/data/form_that_posts_to_echoall.html new file mode 100644 index 0000000..ddd726e --- /dev/null +++ b/content/test/data/form_that_posts_to_echoall.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> + <head></head> + <body> + <form id="form" method="POST" action="/echoall"> + <input type="text" name="text" value="value"> + <input type="submit"> + </form> + </body> +</html>
diff --git a/device/BUILD.gn b/device/BUILD.gn index dde0cd0..eb63e5e 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -70,6 +70,7 @@ "//device/bluetooth", "//device/bluetooth:mocks", "//device/nfc", + "//device/power_save_blocker", "//device/vr", "//device/vr:fakes", "//device/vr:mojo_bindings",
diff --git a/device/power_save_blocker/BUILD.gn b/device/power_save_blocker/BUILD.gn new file mode 100644 index 0000000..abd1856 --- /dev/null +++ b/device/power_save_blocker/BUILD.gn
@@ -0,0 +1,96 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") +import("//build/config/ui.gni") + +if (is_android) { + import("//build/config/android/rules.gni") +} + +component("power_save_blocker") { + sources = [ + "power_save_blocker.h", + "power_save_blocker_android.cc", + "power_save_blocker_android.h", + "power_save_blocker_chromeos.cc", + "power_save_blocker_impl.cc", + "power_save_blocker_impl.h", + "power_save_blocker_mac.cc", + "power_save_blocker_ozone.cc", + "power_save_blocker_win.cc", + "power_save_blocker_x11.cc", + ] + + defines = [ "DEVICE_POWER_SAVE_BLOCKER_IMPLEMENTATION" ] + + deps = [ + "//base", + ] + + if (use_dbus) { + deps += [ "//dbus" ] + } + + if (use_x11) { + configs += [ "//build/config/linux:x11" ] + if (!is_chromeos) { + configs += [ "//build/config/linux:xscrnsaver" ] + } + deps += [ "//ui/gfx/x" ] + } + + # Dealing with power_save_blocker_{x11,ozone}.cc is a little complicated + # given the interaction between os_chromeos and the feature flags for X11 and + # ozone, so do it all in one spot. + if (is_chromeos || !use_ozone) { + sources -= [ "power_save_blocker_ozone.cc" ] + } + if (is_chromeos || !use_x11) { + sources -= [ "power_save_blocker_x11.cc" ] + } + + if (is_android) { + sources += [ + "power_save_blocker_jni_registrar.cc", + "power_save_blocker_jni_registrar.h", + ] + + deps += [ + ":jni_headers", + "//ui/android", + ] + } + + if (is_chromeos) { + deps += [ + "//chromeos", + "//chromeos:power_manager_proto", + ] + } + + if (is_mac) { + libs = [ + "CoreFoundation.framework", + "IOKit.framework", + ] + } +} + +if (is_android) { + java_sources_needing_jni = [ "android/java/src/org/chromium/device/power_save_blocker/PowerSaveBlocker.java" ] + + generate_jni("jni_headers") { + sources = java_sources_needing_jni + jni_package = "device" + } + + android_library("java") { + java_files = java_sources_needing_jni + deps = [ + "//base:base_java", + "//ui/android:ui_java", + ] + } +}
diff --git a/device/power_save_blocker/DEPS b/device/power_save_blocker/DEPS new file mode 100644 index 0000000..9bc85d9 --- /dev/null +++ b/device/power_save_blocker/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+dbus", + "+jni", + "+ui/android", + "+ui/gfx/x", +]
diff --git a/device/power_save_blocker/OWNERS b/device/power_save_blocker/OWNERS new file mode 100644 index 0000000..9cd2ee4 --- /dev/null +++ b/device/power_save_blocker/OWNERS
@@ -0,0 +1,3 @@ +boliu@chromium.org +hashimoto@chromium.org +scottmg@chromium.org
diff --git a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java b/device/power_save_blocker/android/java/src/org/chromium/device/power_save_blocker/PowerSaveBlocker.java similarity index 94% rename from content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java rename to device/power_save_blocker/android/java/src/org/chromium/device/power_save_blocker/PowerSaveBlocker.java index 915d668d..3638d98 100644 --- a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java +++ b/device/power_save_blocker/android/java/src/org/chromium/device/power_save_blocker/PowerSaveBlocker.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.content.browser; +package org.chromium.device.power_save_blocker; import android.view.View; @@ -12,7 +12,7 @@ import java.lang.ref.WeakReference; -@JNINamespace("content") +@JNINamespace("device") class PowerSaveBlocker { // WeakReference to prevent leaks in Android WebView. private WeakReference<View> mKeepScreenOnView;
diff --git a/device/power_save_blocker/power_save_blocker.gyp b/device/power_save_blocker/power_save_blocker.gyp new file mode 100644 index 0000000..23e779ac --- /dev/null +++ b/device/power_save_blocker/power_save_blocker.gyp
@@ -0,0 +1,54 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + # GN version: //device/power_save_blocker + 'target_name': 'device_power_save_blocker', + 'type': '<(component)', + 'dependencies': [ + '../../base/base.gyp:base', + ], + 'defines': [ + 'DEVICE_POWER_SAVE_BLOCKER_IMPLEMENTATION', + ], + 'sources': [ + # Note: file list duplicated in GN build, other than Android, as gyp + # for Android isn't supported. + 'power_save_blocker.h', + 'power_save_blocker_chromeos.cc', + 'power_save_blocker_impl.cc', + 'power_save_blocker_impl.h', + 'power_save_blocker_mac.cc', + 'power_save_blocker_ozone.cc', + 'power_save_blocker_win.cc', + 'power_save_blocker_x11.cc', + ], + 'conditions': [ + ['chromeos==1', { + 'sources!': [ + 'power_save_blocker_ozone.cc', + 'power_save_blocker_x11.cc', + ], + 'dependencies': [ + '../../chromeos/chromeos.gyp:chromeos', + '../../chromeos/chromeos.gyp:power_manager_proto', + ], + }], + ['OS == "mac"', { + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework', + '$(SDKROOT)/System/Library/Frameworks/IOKit.framework', + ], + }, + }], + ], + }, + ], +}
diff --git a/content/public/browser/power_save_blocker.h b/device/power_save_blocker/power_save_blocker.h similarity index 86% rename from content/public/browser/power_save_blocker.h rename to device/power_save_blocker/power_save_blocker.h index db3c0f2..096d816 100644 --- a/content/public/browser/power_save_blocker.h +++ b/device/power_save_blocker/power_save_blocker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_ -#define CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_ +#ifndef DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_H_ +#define DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_H_ #include <memory> #include <string> @@ -11,13 +11,13 @@ #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" -#include "content/common/content_export.h" +#include "device/power_save_blocker/power_save_blocker_export.h" -namespace content { +namespace device { // A RAII-style class to block the system from entering low-power (sleep) mode. // This class is thread-safe; it may be constructed and deleted on any thread. -class CONTENT_EXPORT PowerSaveBlocker { +class DEVICE_POWER_SAVE_BLOCKER_EXPORT PowerSaveBlocker { public: enum PowerSaveBlockerType { // Prevent the application from being suspended. On some platforms, apps may @@ -59,6 +59,6 @@ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); }; -} // namespace content +} // namespace device -#endif // CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_ +#endif // DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_H_
diff --git a/content/browser/power_save_blocker_android.cc b/device/power_save_blocker/power_save_blocker_android.cc similarity index 94% rename from content/browser/power_save_blocker_android.cc rename to device/power_save_blocker/power_save_blocker_android.cc index 6b46bc3..534ed5d4 100644 --- a/content/browser/power_save_blocker_android.cc +++ b/device/power_save_blocker/power_save_blocker_android.cc
@@ -7,11 +7,11 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include "jni/PowerSaveBlocker_jni.h" #include "ui/android/view_android.h" -namespace content { +namespace device { using base::android::AttachCurrentThread; @@ -46,8 +46,7 @@ java_power_save_blocker_.Reset(Java_PowerSaveBlocker_create(env)); } -PowerSaveBlockerImpl::Delegate::~Delegate() { -} +PowerSaveBlockerImpl::Delegate::~Delegate() {} void PowerSaveBlockerImpl::Delegate::ApplyBlock() { DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); @@ -102,4 +101,4 @@ return RegisterNativesImpl(env); } -} // namespace content +} // namespace device
diff --git a/device/power_save_blocker/power_save_blocker_android.h b/device/power_save_blocker/power_save_blocker_android.h new file mode 100644 index 0000000..3313958 --- /dev/null +++ b/device/power_save_blocker/power_save_blocker_android.h
@@ -0,0 +1,16 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_ANDROID_H_ +#define DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_ANDROID_H_ + +#include <jni.h> + +namespace device { + +bool RegisterPowerSaveBlocker(JNIEnv* env); + +} // namespace device + +#endif // DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_ANDROID_H_
diff --git a/content/browser/power_save_blocker_chromeos.cc b/device/power_save_blocker/power_save_blocker_chromeos.cc similarity index 96% rename from content/browser/power_save_blocker_chromeos.cc rename to device/power_save_blocker/power_save_blocker_chromeos.cc index 2913f09..31803583c 100644 --- a/content/browser/power_save_blocker_chromeos.cc +++ b/device/power_save_blocker/power_save_blocker_chromeos.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include <string> @@ -13,7 +13,7 @@ #include "base/memory/ref_counted.h" #include "chromeos/dbus/power_policy_controller.h" -namespace content { +namespace device { namespace { @@ -109,4 +109,4 @@ base::Bind(&Delegate::RemoveBlock, delegate_)); } -} // namespace content +} // namespace device
diff --git a/device/power_save_blocker/power_save_blocker_export.h b/device/power_save_blocker/power_save_blocker_export.h new file mode 100644 index 0000000..171405f --- /dev/null +++ b/device/power_save_blocker/power_save_blocker_export.h
@@ -0,0 +1,28 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_POWER_SAVE_BLOCKER_DEVICE_POWER_SAVE_BLOCKER_EXPORT_H_ +#define DEVICE_POWER_SAVE_BLOCKER_DEVICE_POWER_SAVE_BLOCKER_EXPORT_H_ + +#if defined(COMPONENT_BUILD) && defined(WIN32) + +#if defined(DEVICE_POWER_SAVE_BLOCKER_IMPLEMENTATION) +#define DEVICE_POWER_SAVE_BLOCKER_EXPORT __declspec(dllexport) +#else +#define DEVICE_POWER_SAVE_BLOCKER_EXPORT __declspec(dllimport) +#endif + +#elif defined(COMPONENT_BUILD) && !defined(WIN32) + +#if defined(DEVICE_POWER_SAVE_BLOCKER_IMPLEMENTATION) +#define DEVICE_POWER_SAVE_BLOCKER_EXPORT __attribute__((visibility("default"))) +#else +#define DEVICE_POWER_SAVE_BLOCKER_EXPORT +#endif + +#else +#define DEVICE_POWER_SAVE_BLOCKER_EXPORT +#endif + +#endif // DEVICE_POWER_SAVE_BLOCKER_DEVICE_POWER_SAVE_BLOCKER_EXPORT_H_
diff --git a/content/browser/power_save_blocker_impl.cc b/device/power_save_blocker/power_save_blocker_impl.cc similarity index 87% rename from content/browser/power_save_blocker_impl.cc rename to device/power_save_blocker/power_save_blocker_impl.cc index 70f536cc..c37e6db 100644 --- a/content/browser/power_save_blocker_impl.cc +++ b/device/power_save_blocker/power_save_blocker_impl.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include "build/build_config.h" -namespace content { +namespace device { PowerSaveBlocker::~PowerSaveBlocker() {} @@ -21,4 +21,4 @@ type, reason, description, ui_task_runner, blocking_task_runner)); } -} // namespace content +} // namespace device
diff --git a/content/browser/power_save_blocker_impl.h b/device/power_save_blocker/power_save_blocker_impl.h similarity index 83% rename from content/browser/power_save_blocker_impl.h rename to device/power_save_blocker/power_save_blocker_impl.h index dcc9e62..2f7cadb 100644 --- a/content/browser/power_save_blocker_impl.h +++ b/device/power_save_blocker/power_save_blocker_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_ -#define CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_ +#ifndef DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_IMPL_H_ +#define DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_IMPL_H_ #include <string> @@ -13,13 +13,14 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" -#include "content/public/browser/power_save_blocker.h" +#include "device/power_save_blocker/power_save_blocker.h" +#include "device/power_save_blocker/power_save_blocker_export.h" #if defined(OS_ANDROID) #include "ui/android/view_android.h" #endif // OS_ANDROID -namespace content { +namespace device { class WebContents; @@ -37,7 +38,7 @@ // On Android, the kPowerSaveBlockPreventDisplaySleep type of // PowerSaveBlocker should associated with a View, so the blocker can be // removed by the platform. - void InitDisplaySleepBlocker( + DEVICE_POWER_SAVE_BLOCKER_EXPORT void InitDisplaySleepBlocker( const base::WeakPtr<ui::ViewAndroid>& view_android); #endif @@ -69,6 +70,6 @@ DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerImpl); }; -} // namespace content +} // namespace device -#endif // CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_ +#endif // DEVICE_POWER_SAVE_BLOCKER_POWER_SAVE_BLOCKER_IMPL_H_
diff --git a/device/power_save_blocker/power_save_blocker_jni_registrar.cc b/device/power_save_blocker/power_save_blocker_jni_registrar.cc new file mode 100644 index 0000000..11afbe9 --- /dev/null +++ b/device/power_save_blocker/power_save_blocker_jni_registrar.cc
@@ -0,0 +1,28 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/power_save_blocker/power_save_blocker_jni_registrar.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/macros.h" +#include "device/power_save_blocker/power_save_blocker_android.h" + +namespace device { +namespace android { +namespace { + +const base::android::RegistrationMethod kRegisteredMethods[] = { + {"PowerSaveBlock", device::RegisterPowerSaveBlocker}, +}; + +} // namespace + +bool RegisterPowerSaveBlockerJni(JNIEnv* env) { + return RegisterNativeMethods(env, kRegisteredMethods, + arraysize(kRegisteredMethods)); +} + +} // namespace android +} // namespace device
diff --git a/device/power_save_blocker/power_save_blocker_jni_registrar.h b/device/power_save_blocker/power_save_blocker_jni_registrar.h new file mode 100644 index 0000000..7e05d366 --- /dev/null +++ b/device/power_save_blocker/power_save_blocker_jni_registrar.h
@@ -0,0 +1,24 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_POWER_SAVE_BLOCKER_ANDROID_POWER_SAVE_BLOCKER_JNI_REGISTRAR_H_ +#define DEVICE_POWER_SAVE_BLOCKER_ANDROID_POWER_SAVE_BLOCKER_JNI_REGISTRAR_H_ + +#include <jni.h> + +#include "device/power_save_blocker/power_save_blocker_export.h" + +namespace device { +namespace android { + +// Registers C++ methods in device/power_save_blocker classes with JNI. +// See https://www.chromium.org/developers/design-documents/android-jni +// +// Must be called before classes in the Bluetooth module are used. +DEVICE_POWER_SAVE_BLOCKER_EXPORT bool RegisterPowerSaveBlockerJni(JNIEnv* env); + +} // namespace android +} // namespace device + +#endif // DEVICE_POWER_SAVE_BLOCKER_ANDROID_POWER_SAVE_BLOCKER_JNI_REGISTRAR_H_
diff --git a/content/browser/power_save_blocker_mac.cc b/device/power_save_blocker/power_save_blocker_mac.cc similarity index 85% rename from content/browser/power_save_blocker_mac.cc rename to device/power_save_blocker/power_save_blocker_mac.cc index 581e9b9..251cc22 100644 --- a/content/browser/power_save_blocker_mac.cc +++ b/device/power_save_blocker/power_save_blocker_mac.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include <IOKit/pwr_mgt/IOPMLib.h> @@ -13,13 +13,14 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread.h" -namespace content { +namespace device { namespace { // Power management cannot be done on the UI thread. IOPMAssertionCreate does a // synchronous MIG call to configd, so if it is called on the main thread the UI // is at the mercy of another process. See http://crbug.com/79559 and -// http://www.opensource.apple.com/source/IOKitUser/IOKitUser-514.16.31/pwr_mgt.subproj/IOPMLibPrivate.c . +// http://www.opensource.apple.com/source/IOKitUser/IOKitUser-514.16.31/pwr_mgt.subproj/IOPMLibPrivate.c +// . struct PowerSaveBlockerLazyInstanceTraits { static const bool kRegisterOnExit = false; #ifndef NDEBUG @@ -31,7 +32,7 @@ thread->Start(); return thread; } - static void Delete(base::Thread* instance) { } + static void Delete(base::Thread* instance) {} }; base::LazyInstance<base::Thread, PowerSaveBlockerLazyInstanceTraits> g_power_thread = LAZY_INSTANCE_INITIALIZER; @@ -81,8 +82,8 @@ base::SysUTF8ToCFStringRef(description_)); IOReturn result = IOPMAssertionCreateWithName(level, kIOPMAssertionLevelOn, cf_description, &assertion_); - LOG_IF(ERROR, result != kIOReturnSuccess) - << "IOPMAssertionCreate: " << result; + LOG_IF(ERROR, result != kIOReturnSuccess) << "IOPMAssertionCreate: " + << result; } } @@ -92,8 +93,8 @@ if (assertion_ != kIOPMNullAssertionID) { IOReturn result = IOPMAssertionRelease(assertion_); - LOG_IF(ERROR, result != kIOReturnSuccess) - << "IOPMAssertionRelease: " << result; + LOG_IF(ERROR, result != kIOReturnSuccess) << "IOPMAssertionRelease: " + << result; } } @@ -107,14 +108,12 @@ ui_task_runner_(ui_task_runner), blocking_task_runner_(blocking_task_runner) { g_power_thread.Pointer()->message_loop()->PostTask( - FROM_HERE, - base::Bind(&Delegate::ApplyBlock, delegate_)); + FROM_HERE, base::Bind(&Delegate::ApplyBlock, delegate_)); } PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { g_power_thread.Pointer()->message_loop()->PostTask( - FROM_HERE, - base::Bind(&Delegate::RemoveBlock, delegate_)); + FROM_HERE, base::Bind(&Delegate::RemoveBlock, delegate_)); } -} // namespace content +} // namespace device
diff --git a/content/browser/power_save_blocker_ozone.cc b/device/power_save_blocker/power_save_blocker_ozone.cc similarity index 87% rename from content/browser/power_save_blocker_ozone.cc rename to device/power_save_blocker/power_save_blocker_ozone.cc index 1618a85..caf15a5 100644 --- a/content/browser/power_save_blocker_ozone.cc +++ b/device/power_save_blocker/power_save_blocker_ozone.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -namespace content { +namespace device { // TODO(derat): Consider renaming this file; '_ozone' is a misnomer as power // save is OS-specific, not display-system-specific. This implementation @@ -35,6 +35,6 @@ ui_task_runner_(ui_task_runner), blocking_task_runner_(blocking_task_runner) {} -PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { } +PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {} -} // namespace content +} // namespace device
diff --git a/content/browser/power_save_blocker_win.cc b/device/power_save_blocker/power_save_blocker_win.cc similarity index 96% rename from content/browser/power_save_blocker_win.cc rename to device/power_save_blocker/power_save_blocker_win.cc index e9650a5..8464c210 100644 --- a/content/browser/power_save_blocker_win.cc +++ b/device/power_save_blocker/power_save_blocker_win.cc
@@ -10,9 +10,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" -namespace content { +namespace device { namespace { int g_blocker_count[2]; @@ -57,8 +57,7 @@ DCHECK(success); } -void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type, - int delta) { +void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type, int delta) { g_blocker_count[type] += delta; DCHECK_GE(g_blocker_count[type], 0); @@ -157,4 +156,4 @@ base::Bind(&Delegate::RemoveBlock, delegate_)); } -} // namespace content +} // namespace device
diff --git a/content/browser/power_save_blocker_x11.cc b/device/power_save_blocker/power_save_blocker_x11.cc similarity index 97% rename from content/browser/power_save_blocker_x11.cc rename to device/power_save_blocker/power_save_blocker_x11.cc index a177e39..ed66813 100644 --- a/content/browser/power_save_blocker_x11.cc +++ b/device/power_save_blocker/power_save_blocker_x11.cc
@@ -9,7 +9,7 @@ #include <memory> -#include "content/browser/power_save_blocker_impl.h" +#include "device/power_save_blocker/power_save_blocker_impl.h" // Xlib #defines Status, but we can't have that for some of our headers. #ifdef Status #undef Status @@ -45,9 +45,9 @@ // Can be OR'd together and passed as argument to the Inhibit() method // to specify which power management features we want to suspend. enum GnomeAPIInhibitFlags { - INHIBIT_LOGOUT = 1, - INHIBIT_SWITCH_USER = 2, - INHIBIT_SUSPEND_SESSION = 4, + INHIBIT_LOGOUT = 1, + INHIBIT_SWITCH_USER = 2, + INHIBIT_SUSPEND_SESSION = 4, INHIBIT_MARK_SESSION_IDLE = 8 }; @@ -68,7 +68,7 @@ } // namespace -namespace content { +namespace device { class PowerSaveBlockerImpl::Delegate : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { @@ -256,8 +256,7 @@ return; case GNOME_API: object_proxy = bus_->GetObjectProxy( - kGnomeAPIServiceName, - dbus::ObjectPath(kGnomeAPIObjectPath)); + kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath)); method_call.reset( new dbus::MethodCall(kGnomeAPIInterfaceName, "Inhibit")); message_writer.reset(new dbus::MessageWriter(method_call.get())); @@ -366,8 +365,7 @@ return; case GNOME_API: object_proxy = bus_->GetObjectProxy( - kGnomeAPIServiceName, - dbus::ObjectPath(kGnomeAPIObjectPath)); + kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath)); method_call.reset( new dbus::MethodCall(kGnomeAPIInterfaceName, "Uninhibit")); break; @@ -505,4 +503,4 @@ freedesktop_suspend_delegate_->CleanUp(); } -} // namespace content +} // namespace device
diff --git a/device/test/run_all_unittests.cc b/device/test/run_all_unittests.cc index 06b32a8..3048912 100644 --- a/device/test/run_all_unittests.cc +++ b/device/test/run_all_unittests.cc
@@ -11,12 +11,15 @@ #if defined(OS_ANDROID) #include "base/android/jni_android.h" #include "device/bluetooth/android/bluetooth_jni_registrar.h" +#include "device/power_save_blocker/power_save_blocker_jni_registrar.h" #include "device/usb/android/usb_jni_registrar.h" #endif int main(int argc, char** argv) { #if defined(OS_ANDROID) device::android::RegisterBluetoothJni(base::android::AttachCurrentThread()); + device::android::RegisterPowerSaveBlockerJni( + base::android::AttachCurrentThread()); device::android::RegisterUsbJni(base::android::AttachCurrentThread()); #endif
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index cbaecf3..bf4d6d9 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -62,6 +62,7 @@ "//device/bluetooth", "//device/core", "//device/hid", + "//device/power_save_blocker", "//device/serial", "//device/usb", "//extensions/common/api/cast_channel:cast_channel_proto",
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS index 4d6eaeb..1fb5effd 100644 --- a/extensions/browser/DEPS +++ b/extensions/browser/DEPS
@@ -13,6 +13,7 @@ "+components/zoom", "+content/public/browser", "+device/bluetooth", + "+device/power_save_blocker", "+device/serial", "+device/usb", "+google_apis/gaia",
diff --git a/extensions/browser/api/power/power_api.cc b/extensions/browser/api/power/power_api.cc index c12d86b..8190896 100644 --- a/extensions/browser/api/power/power_api.cc +++ b/extensions/browser/api/power/power_api.cc
@@ -6,7 +6,8 @@ #include "base/bind.h" #include "base/lazy_instance.h" -#include "content/public/browser/power_save_blocker_factory.h" +#include "content/public/browser/browser_thread.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/api/power.h" #include "extensions/common/extension.h" @@ -17,17 +18,17 @@ const char kPowerSaveBlockerDescription[] = "extension"; -content::PowerSaveBlocker::PowerSaveBlockerType LevelToPowerSaveBlockerType( +device::PowerSaveBlocker::PowerSaveBlockerType LevelToPowerSaveBlockerType( api::power::Level level) { switch (level) { case api::power::LEVEL_SYSTEM: - return content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension; + return device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension; case api::power::LEVEL_DISPLAY: // fallthrough case api::power::LEVEL_NONE: - return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; + return device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; } NOTREACHED() << "Unhandled level " << level; - return content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; + return device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep; } base::LazyInstance<BrowserContextKeyedAPIFactory<PowerAPI>> g_factory = @@ -72,9 +73,10 @@ void PowerAPI::SetCreateBlockerFunctionForTesting( CreateBlockerFunction function) { - create_blocker_function_ = !function.is_null() - ? function - : base::Bind(&content::CreatePowerSaveBlocker); + create_blocker_function_ = + !function.is_null() + ? function + : base::Bind(&device::PowerSaveBlocker::CreateWithTaskRunners); } void PowerAPI::OnExtensionUnloaded(content::BrowserContext* browser_context, @@ -86,7 +88,8 @@ PowerAPI::PowerAPI(content::BrowserContext* context) : browser_context_(context), - create_blocker_function_(base::Bind(&content::CreatePowerSaveBlocker)), + create_blocker_function_( + base::Bind(&device::PowerSaveBlocker::CreateWithTaskRunners)), current_level_(api::power::LEVEL_SYSTEM) { ExtensionRegistry::Get(browser_context_)->AddObserver(this); } @@ -111,12 +114,16 @@ // to ensure that there isn't a brief period where power management is // unblocked. if (!power_save_blocker_ || new_level != current_level_) { - content::PowerSaveBlocker::PowerSaveBlockerType type = + device::PowerSaveBlocker::PowerSaveBlockerType type = LevelToPowerSaveBlockerType(new_level); - std::unique_ptr<content::PowerSaveBlocker> new_blocker( - create_blocker_function_.Run(type, - content::PowerSaveBlocker::kReasonOther, - kPowerSaveBlockerDescription)); + std::unique_ptr<device::PowerSaveBlocker> new_blocker( + create_blocker_function_.Run( + type, device::PowerSaveBlocker::kReasonOther, + kPowerSaveBlockerDescription, + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::UI), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE))); power_save_blocker_.swap(new_blocker); current_level_ = new_level; }
diff --git a/extensions/browser/api/power/power_api.h b/extensions/browser/api/power/power_api.h index e68bd57..73db136 100644 --- a/extensions/browser/api/power/power_api.h +++ b/extensions/browser/api/power/power_api.h
@@ -11,7 +11,7 @@ #include "base/callback.h" #include "base/macros.h" -#include "content/public/browser/power_save_blocker.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_function.h" #include "extensions/browser/extension_registry_observer.h" @@ -53,10 +53,12 @@ class PowerAPI : public BrowserContextKeyedAPI, public extensions::ExtensionRegistryObserver { public: - typedef base::Callback<std::unique_ptr<content::PowerSaveBlocker>( - content::PowerSaveBlocker::PowerSaveBlockerType, - content::PowerSaveBlocker::Reason, - const std::string&)> + typedef base::Callback<std::unique_ptr<device::PowerSaveBlocker>( + device::PowerSaveBlocker::PowerSaveBlockerType, + device::PowerSaveBlocker::Reason, + const std::string&, + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)> CreateBlockerFunction; static PowerAPI* Get(content::BrowserContext* context); @@ -104,7 +106,7 @@ // actually changing the system power-saving settings. CreateBlockerFunction create_blocker_function_; - std::unique_ptr<content::PowerSaveBlocker> power_save_blocker_; + std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; // Current level used by |power_save_blocker_|. Meaningless if // |power_save_blocker_| is NULL.
diff --git a/extensions/browser/api/power/power_api_unittest.cc b/extensions/browser/api/power/power_api_unittest.cc index 54b8403d..06e4d8f3 100644 --- a/extensions/browser/api/power/power_api_unittest.cc +++ b/extensions/browser/api/power/power_api_unittest.cc
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "content/public/browser/power_save_blocker.h" +#include "device/power_save_blocker/power_save_blocker.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/api_unittest.h" #include "extensions/common/extension.h" @@ -38,9 +38,9 @@ NONE, }; -// Stub implementation of content::PowerSaveBlocker that just runs a -// callback on destruction. -class PowerSaveBlockerStub : public content::PowerSaveBlocker { +// Stub implementation of device::PowerSaveBlocker that just runs a callback on +// destruction. +class PowerSaveBlockerStub : public device::PowerSaveBlocker { public: explicit PowerSaveBlockerStub(base::Closure unblock_callback) : unblock_callback_(unblock_callback) { @@ -88,22 +88,24 @@ private: // Creates a new PowerSaveBlockerStub of type |type|. - std::unique_ptr<content::PowerSaveBlocker> CreateStub( - content::PowerSaveBlocker::PowerSaveBlockerType type, - content::PowerSaveBlocker::Reason reason, - const std::string& description) { + std::unique_ptr<device::PowerSaveBlocker> CreateStub( + device::PowerSaveBlocker::PowerSaveBlockerType type, + device::PowerSaveBlocker::Reason reason, + const std::string& description, + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) { Request unblock_request = NONE; switch (type) { - case content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension: + case device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension: requests_.push_back(BLOCK_APP_SUSPENSION); unblock_request = UNBLOCK_APP_SUSPENSION; break; - case content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep: + case device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep: requests_.push_back(BLOCK_DISPLAY_SLEEP); unblock_request = UNBLOCK_DISPLAY_SLEEP; break; } - return std::unique_ptr<content::PowerSaveBlocker>(new PowerSaveBlockerStub( + return std::unique_ptr<device::PowerSaveBlocker>(new PowerSaveBlockerStub( base::Bind(&PowerSaveBlockerStubManager::AppendRequest, weak_ptr_factory_.GetWeakPtr(), unblock_request))); }
diff --git a/extensions/common/permissions/settings_override_permission.cc b/extensions/common/permissions/settings_override_permission.cc index 263f9dc..b44d8810 100644 --- a/extensions/common/permissions/settings_override_permission.cc +++ b/extensions/common/permissions/settings_override_permission.cc
@@ -51,7 +51,14 @@ const base::Value* value, std::string* /*error*/, std::vector<std::string>* unhandled_permissions) { - return value && value->GetAsString(&setting_value_); + // Ugly hack: |value| being null should be an error. But before M46 beta, we + // didn't store the parameter for settings override permissions in prefs. + // See crbug.com/533086 and crbug.com/619759. + // TODO(treib,devlin): Remove this for M56, when hopefully all users will have + // updated prefs. + // This should read: + // return value && value->GetAsString(&setting_value_); + return !value || value->GetAsString(&setting_value_); } std::unique_ptr<base::Value> SettingsOverrideAPIPermission::ToValue() const {
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index b37a4bd..73e248c 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp
@@ -57,6 +57,7 @@ '../device/bluetooth/bluetooth.gyp:device_bluetooth', # For Mojo generated headers for generated_api.cc. '../device/serial/serial.gyp:device_serial_mojo', + '../device/power_save_blocker/power_save_blocker.gyp:device_power_save_blocker', '../device/usb/usb.gyp:device_usb', '../ipc/ipc.gyp:ipc', '../net/net.gyp:net',
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index c19fa7e7..0dbf9d0 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -54,6 +54,8 @@ "gl_state_restorer_impl.h", "gl_utils.cc", "gl_utils.h", + "gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc", + "gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h", "gles2_cmd_clear_framebuffer.cc", "gles2_cmd_clear_framebuffer.h", "gles2_cmd_copy_tex_image.cc",
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 06bb664..ee805dd 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -89,6 +89,7 @@ multisampled_render_to_texture(false), use_img_for_multisampled_render_to_texture(false), chromium_screen_space_antialiasing(false), + use_chromium_screen_space_antialiasing_via_shaders(false), oes_standard_derivatives(false), oes_egl_image_external(false), nv_egl_stream_consumer_external(false), @@ -179,6 +180,9 @@ disable_shader_translator_ = command_line->HasSwitch(switches::kDisableGLSLTranslator); + enable_cmaa_shaders_switch_ = + command_line->HasSwitch(switches::kEnableCMAAShaders); + unsafe_es3_apis_enabled_ = false; // Default context_type_ to a GLES2 Context. @@ -881,6 +885,17 @@ if (extensions.Contains("GL_INTEL_framebuffer_CMAA")) { feature_flags_.chromium_screen_space_antialiasing = true; AddExtensionString("GL_CHROMIUM_screen_space_antialiasing"); + } else if (enable_cmaa_shaders_switch_ && + (gl_version_info_->IsAtLeastGLES(3, 1) || + (gl_version_info_->IsAtLeastGL(3, 0) && + extensions.Contains("GL_ARB_shading_language_420pack") && + extensions.Contains("GL_ARB_texture_gather") && + extensions.Contains("GL_ARB_explicit_uniform_location") && + extensions.Contains("GL_ARB_explicit_attrib_location") && + extensions.Contains("GL_ARB_shader_image_load_store")))) { + feature_flags_.chromium_screen_space_antialiasing = true; + feature_flags_.use_chromium_screen_space_antialiasing_via_shaders = true; + AddExtensionString("GL_CHROMIUM_screen_space_antialiasing"); } if (extensions.Contains("GL_OES_depth24") || gl::HasDesktopGLFeatures() ||
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index ff6b354..c8ea959 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -42,6 +42,7 @@ // Use the IMG GLenum values and functions rather than EXT. bool use_img_for_multisampled_render_to_texture; bool chromium_screen_space_antialiasing; + bool use_chromium_screen_space_antialiasing_via_shaders; bool oes_standard_derivatives; bool oes_egl_image_external; bool nv_egl_stream_consumer_external; @@ -191,6 +192,9 @@ bool disable_shader_translator_; std::unique_ptr<gl::GLVersionInfo> gl_version_info_; + // Whether the command line switch kEnableCMAAShaders is passed in. + bool enable_cmaa_shaders_switch_; + DISALLOW_COPY_AND_ASSIGN(FeatureInfo); };
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc new file mode 100644 index 0000000..56490303a --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
@@ -0,0 +1,1826 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h" + +#include "base/logging.h" +#include "gpu/command_buffer/service/framebuffer_manager.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_gl_api_implementation.h" +#include "ui/gl/gl_version_info.h" + +namespace gpu { + +ApplyFramebufferAttachmentCMAAINTELResourceManager:: + ApplyFramebufferAttachmentCMAAINTELResourceManager() + : initialized_(false), + textures_initialized_(false), + is_in_gamma_correct_mode_(false), + supports_usampler_(true), + supports_r8_image_(true), + supports_r8_read_format_(true), + is_gles31_compatible_(false), + frame_id_(0), + width_(0), + height_(0), + copy_to_framebuffer_shader_(0), + copy_to_image_shader_(0), + edges0_shader_(0), + edges1_shader_(0), + edges_combine_shader_(0), + process_and_apply_shader_(0), + debug_display_edges_shader_(0), + cmaa_framebuffer_(0), + copy_framebuffer_(0), + rgba8_texture_(0), + working_color_texture_(0), + edges0_texture_(0), + edges1_texture_(0), + mini4_edge_texture_(0), + mini4_edge_depth_texture_(0), + edges1_shader_result_texture_float4_slot1_(0), + edges1_shader_result_texture_(0), + edges_combine_shader_result_texture_float4_slot1_(0), + process_and_apply_shader_result_texture_float4_slot1_(0), + edges_combine_shader_result_texture_slot2_(0), + copy_to_image_shader_outTexture_(0) {} + +ApplyFramebufferAttachmentCMAAINTELResourceManager:: + ~ApplyFramebufferAttachmentCMAAINTELResourceManager() { + Destroy(); +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::Initialize( + gles2::GLES2Decoder* decoder) { + DCHECK(decoder); + is_gles31_compatible_ = + decoder->GetGLContext()->GetVersionInfo()->IsAtLeastGLES(3, 1); + + copy_to_image_shader_ = CreateProgram("", vert_str_, copy_frag_str_); + copy_to_framebuffer_shader_ = + CreateProgram("#define OUT_FBO 1\n", vert_str_, copy_frag_str_); + + // Check if RGBA8UI is supported as an FBO colour target with depth. + // If not supported, GLSL needs to convert the data to/from float so there is + // a small extra cost. + { + GLuint rgba8ui_texture = 0, depth_texture = 0; + glGenTextures(1, &rgba8ui_texture); + glBindTexture(GL_TEXTURE_2D, rgba8ui_texture); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8UI, 4, 4); + + glGenTextures(1, &depth_texture); + glBindTexture(GL_TEXTURE_2D, depth_texture); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, 4, 4); + + // Create the FBO + GLuint rgba8ui_framebuffer = 0; + glGenFramebuffersEXT(1, &rgba8ui_framebuffer); + glBindFramebufferEXT(GL_FRAMEBUFFER, rgba8ui_framebuffer); + + // Bind to the FBO to test support + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, rgba8ui_texture, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, depth_texture, 0); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + + supports_usampler_ = (status == GL_FRAMEBUFFER_COMPLETE); + + glDeleteFramebuffersEXT(1, &rgba8ui_framebuffer); + glDeleteTextures(1, &rgba8ui_texture); + glDeleteTextures(1, &depth_texture); + } + + // Check to see if R8 images are supported + // If not supported, images are bound as R32F for write targets, not R8. + { + GLuint r8_texture = 0; + glGenTextures(1, &r8_texture); + glBindTexture(GL_TEXTURE_2D, r8_texture); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_R8, 4, 4); + + glGetError(); // reset all previous errors + glBindImageTextureEXT(0, r8_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8); + if (glGetError() != GL_NO_ERROR) + supports_r8_image_ = false; + + glDeleteTextures(1, &r8_texture); + } + + // Check if R8 GLSL read formats are supported. + // If not supported, r32f is used instead. + { + const char shader_source[] = + "layout(r8) restrict writeonly uniform highp image2D g_r8Image; \n" + "void main() \n" + "{ \n" + " imageStore(g_r8Image, ivec2(0, 0), vec4(1.0, 0.0, 0.0, 0.0)); \n" + "} \n"; + + GLuint shader = CreateShader(GL_FRAGMENT_SHADER, "", shader_source); + supports_r8_read_format_ = (shader != 0); + if (shader != 0) { + glDeleteShader(shader); + } + } + + VLOG(1) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "Supports USampler is " << (supports_usampler_ ? "true" : "false"); + VLOG(1) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "Supports R8 Images is " + << (supports_r8_image_ ? "true" : "false"); + VLOG(1) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "Supports R8 Read Format is " + << (supports_r8_read_format_ ? "true" : "false"); + + // Create the shaders + std::ostringstream defines, edge1, edge2, combineEdges, blur, displayEdges, + cmaa_frag; + + cmaa_frag << cmaa_frag_s1_ << cmaa_frag_s2_; + std::string cmaa_frag_string = cmaa_frag.str(); + const char* cmaa_frag_c_str = cmaa_frag_string.c_str(); + + if (supports_usampler_) { + defines << "#define SUPPORTS_USAMPLER2D\n"; + } + + if (is_in_gamma_correct_mode_) { + defines << "#define IN_GAMMA_CORRECT_MODE\n"; + } + + if (supports_r8_read_format_) { + defines << "#define EDGE_READ_FORMAT r8\n"; + } else { + defines << "#define EDGE_READ_FORMAT r32f\n"; + } + + displayEdges << defines.str() << "#define DISPLAY_EDGES\n"; + debug_display_edges_shader_ = + CreateProgram(displayEdges.str().c_str(), vert_str_, cmaa_frag_c_str); + + edge1 << defines.str() << "#define DETECT_EDGES1\n"; + edges0_shader_ = + CreateProgram(edge1.str().c_str(), vert_str_, cmaa_frag_c_str); + + edge2 << defines.str() << "#define DETECT_EDGES2\n"; + edges1_shader_ = + CreateProgram(edge2.str().c_str(), vert_str_, cmaa_frag_c_str); + + combineEdges << defines.str() << "#define COMBINE_EDGES\n"; + edges_combine_shader_ = + CreateProgram(combineEdges.str().c_str(), vert_str_, cmaa_frag_c_str); + + blur << defines.str() << "#define BLUR_EDGES\n"; + process_and_apply_shader_ = + CreateProgram(blur.str().c_str(), vert_str_, cmaa_frag_c_str); + + edges1_shader_result_texture_float4_slot1_ = + glGetUniformLocation(edges0_shader_, "g_resultTextureFlt4Slot1"); + edges1_shader_result_texture_ = + glGetUniformLocation(edges1_shader_, "g_resultTexture"); + edges_combine_shader_result_texture_float4_slot1_ = + glGetUniformLocation(edges_combine_shader_, "g_resultTextureFlt4Slot1"); + edges_combine_shader_result_texture_slot2_ = + glGetUniformLocation(edges_combine_shader_, "g_resultTextureSlot2"); + process_and_apply_shader_result_texture_float4_slot1_ = glGetUniformLocation( + process_and_apply_shader_, "g_resultTextureFlt4Slot1"); + copy_to_image_shader_outTexture_ = + glGetUniformLocation(copy_to_image_shader_, "outTexture"); + + initialized_ = true; +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::Destroy() { + if (!initialized_) + return; + + ReleaseTextures(); + + glDeleteProgram(copy_to_image_shader_); + glDeleteProgram(copy_to_framebuffer_shader_); + glDeleteProgram(process_and_apply_shader_); + glDeleteProgram(edges_combine_shader_); + glDeleteProgram(edges1_shader_); + glDeleteProgram(edges0_shader_); + glDeleteProgram(debug_display_edges_shader_); + + initialized_ = false; +} + +// Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the +// color attachments of currently bound draw framebuffer. +// Reference GL_INTEL_framebuffer_CMAA for details. +void ApplyFramebufferAttachmentCMAAINTELResourceManager:: + ApplyFramebufferAttachmentCMAAINTEL(gles2::GLES2Decoder* decoder, + gles2::Framebuffer* framebuffer) { + DCHECK(decoder); + DCHECK(initialized_); + if (!framebuffer) + return; + + GLuint last_framebuffer = framebuffer->service_id(); + + // Process each color attachment of the current draw framebuffer. + uint32_t max_draw_buffers = decoder->GetContextGroup()->max_draw_buffers(); + for (uint32_t i = 0; i < max_draw_buffers; i++) { + const gles2::Framebuffer::Attachment* attachment = + framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0 + i); + if (attachment && attachment->IsTextureAttachment()) { + // Get the texture info. + GLuint source_texture_client_id = attachment->object_name(); + GLuint source_texture = 0; + if (!decoder->GetServiceTextureId(source_texture_client_id, + &source_texture)) + continue; + GLsizei width = attachment->width(); + GLsizei height = attachment->height(); + GLenum internal_format = attachment->internal_format(); + + // Resize internal structures - only if needed. + OnSize(width, height); + + // CMAA internally expects GL_RGBA8 textures. + // Process using a GL_RGBA8 copy if this is not the case. + bool do_copy = internal_format != GL_RGBA8; + + // Copy source_texture to rgba8_texture_ + if (do_copy) { + CopyTexture(source_texture, rgba8_texture_, false); + } + + // CMAA Effect + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, last_framebuffer); + if (do_copy) { + ApplyCMAAEffectTexture(rgba8_texture_, rgba8_texture_); + } else { + ApplyCMAAEffectTexture(source_texture, source_texture); + } + + // Copy rgba8_texture_ to source_texture + if (do_copy) { + // Move source_texture to the first color attachment of the copy fbo. + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, last_framebuffer); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_TEXTURE_2D, 0, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER, copy_framebuffer_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, source_texture, 0); + + CopyTexture(rgba8_texture_, source_texture, true); + + // Restore color attachments + glBindFramebufferEXT(GL_FRAMEBUFFER, copy_framebuffer_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, rgba8_texture_, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, last_framebuffer); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_TEXTURE_2D, source_texture, 0); + } + } + } + + // Restore state + decoder->RestoreAllAttributes(); + decoder->RestoreTextureUnitBindings(0); + decoder->RestoreTextureUnitBindings(1); + decoder->RestoreActiveTexture(); + decoder->RestoreProgramBindings(); + decoder->RestoreBufferBindings(); + decoder->RestoreFramebufferBindings(); + decoder->RestoreGlobalState(); +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::ApplyCMAAEffectTexture( + GLuint source_texture, + GLuint dest_texture) { + frame_id_++; + + GLuint edge_texture_a; + GLuint edge_texture_b; + + // Flip flop - One pass clears the texture that needs clearing for the other + // one (actually it's only important that it clears the highest bit) + if ((frame_id_ % 2) == 0) { + edge_texture_a = edges0_texture_; + edge_texture_b = edges1_texture_; + } else { + edge_texture_a = edges1_texture_; + edge_texture_b = edges0_texture_; + } + + // Setup the main fbo + glBindFramebufferEXT(GL_FRAMEBUFFER, cmaa_framebuffer_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mini4_edge_texture_, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, + mini4_edge_depth_texture_, 0); +#if DCHECK_IS_ON() + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + DLOG(ERROR) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "Incomplete framebuffer."; + Destroy(); + return; + } +#endif + + // Setup the viewport to match the fbo + glViewport(0, 0, (width_ + 1) / 2, (height_ + 1) / 2); + glEnable(GL_DEPTH_TEST); + + // Detect edges Pass 0 + // - For every pixel detect edges to the right and down and output depth + // mask where edges detected (1 - far, for detected, 0-near for empty + // pixels) + + // Inputs + // g_screenTexture source_texture tex0 + // Outputs + // gl_FragDepth mini4_edge_depth_texture_ fbo.depth + // out uvec4 outEdges mini4_edge_texture_ fbo.col + // image2D g_resultTextureFlt4Slot1 working_color_texture_ image1 + GLenum edge_format = supports_r8_image_ ? GL_R8 : GL_R32F; + + { + glUseProgram(edges0_shader_); + glUniform1f(0, 1.0f); + glUniform2f(1, 1.0f / width_, 1.0f / height_); + glDepthMask(GL_TRUE); + glDepthFunc(GL_ALWAYS); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (!is_gles31_compatible_) { + glUniform1i(edges1_shader_result_texture_float4_slot1_, 1); + } + glBindImageTextureEXT(1, working_color_texture_, 0, GL_FALSE, 0, + GL_WRITE_ONLY, GL_RGBA8); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, source_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glDrawArrays(GL_TRIANGLES, 0, 3); + } + + // Detect edges Pass 1 (finish the previous pass edge processing). + // Do the culling of non-dominant local edges (leave mainly locally dominant + // edges) and merge Right and Bottom edges into TopRightBottomLeft + + // Inputs + // g_src0Texture4Uint mini4_edge_texture_ tex1 + // Outputs + // image2D g_resultTexture edge_texture_b image0 + { + glUseProgram(edges1_shader_); + glUniform1f(0, 0.0f); + glUniform2f(1, 1.0f / width_, 1.0f / height_); + glDepthMask(GL_FALSE); + glDepthFunc(GL_LESS); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + if (!is_gles31_compatible_) { + glUniform1i(edges1_shader_result_texture_, 0); + } + glBindImageTextureEXT(0, edge_texture_b, 0, GL_FALSE, 0, GL_WRITE_ONLY, + edge_format); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, mini4_edge_texture_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glDrawArrays(GL_TRIANGLES, 0, 3); + } + + // - Combine RightBottom (.xy) edges from previous pass into + // RightBottomLeftTop (.xyzw) edges and output it into the mask (have to + // fill in the whole buffer including empty ones for the line length + // detection to work correctly). + // - On all pixels with any edge, input buffer into a temporary color buffer + // needed for correct blending in the next pass (other pixels not needed + // so not copied to avoid bandwidth use). + // - On all pixels with 2 or more edges output positive depth mask for the + // next pass. + + // Inputs + // g_src0TextureFlt edge_texture_b tex1 //ps + // Outputs + // image2D g_resultTextureSlot2 edge_texture_a image2 + // gl_FragDepth mini4_edge_texture_ fbo.depth + { + // Combine edges: each pixel will now contain info on all (top, right, + // bottom, left) edges; also create depth mask as above depth and mark + // potential Z sAND also copy source color data but only on edge pixels + glUseProgram(edges_combine_shader_); + glUniform1f(0, 1.0f); + glUniform2f(1, 1.0f / width_, 1.0f / height_); + glDepthMask(GL_TRUE); + glDepthFunc(GL_ALWAYS); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + if (!is_gles31_compatible_) { + glUniform1i(edges_combine_shader_result_texture_float4_slot1_, 1); + glUniform1i(edges_combine_shader_result_texture_slot2_, 2); + } + glBindImageTextureEXT(1, dest_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, + GL_RGBA8); + glBindImageTextureEXT(2, edge_texture_a, 0, GL_FALSE, 0, GL_WRITE_ONLY, + edge_format); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, edge_texture_b); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glDrawArrays(GL_TRIANGLES, 0, 3); + } + + // Using depth mask and [earlydepthstencil] to work on pixels with 2, 3, 4 + // edges: + // - First blend simple blur map for 2,3,4 edge pixels + // - Then do the lines (line length counter -should- guarantee no overlap + // with other pixels - pixels with 1 edge are excluded in the previous + // pass and the pixels with 2 parallel edges are excluded in the simple + // blur) + + // Inputs + // g_screenTexture working_color_texture_ tex0 + // g_src0TextureFlt edge_texture_a tex1 //ps + // sampled + // Outputs + // g_resultTextureFlt4Slot1 dest_texture image1 + // gl_FragDepth mini4_edge_texture_ fbo.depth + { + glUseProgram(process_and_apply_shader_); + glUniform1f(0, 0.0f); + glUniform2f(1, 1.0f / width_, 1.0f / height_); + glDepthMask(GL_FALSE); + glDepthFunc(GL_LESS); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + if (!is_gles31_compatible_) { + glUniform1i(process_and_apply_shader_result_texture_float4_slot1_, 1); + } + glBindImageTextureEXT(1, dest_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, + GL_RGBA8); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, working_color_texture_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, edge_texture_a); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glDrawArrays(GL_TRIANGLES, 0, 3); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glActiveTexture(GL_TEXTURE0); +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::OnSize(GLint width, + GLint height) { + if (height_ == height && width_ == width) + return; + + ReleaseTextures(); + + height_ = height; + width_ = width; + + glGenFramebuffersEXT(1, ©_framebuffer_); + glGenTextures(1, &rgba8_texture_); + glBindTexture(GL_TEXTURE_2D, rgba8_texture_); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); + + // Edges texture - R8 + // OpenGLES has no single component 8/16-bit image support, so needs to be R32 + // Although CHT does support R8. + GLenum edge_format = supports_r8_image_ ? GL_R8 : GL_R32F; + glGenTextures(1, &edges0_texture_); + glBindTexture(GL_TEXTURE_2D, edges0_texture_); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, edge_format, width, height); + + glGenTextures(1, &edges1_texture_); + glBindTexture(GL_TEXTURE_2D, edges1_texture_); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, edge_format, width, height); + + // Color working texture - RGBA8 + glGenTextures(1, &working_color_texture_); + glBindTexture(GL_TEXTURE_2D, working_color_texture_); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); + + // Half*half compressed 4-edge-per-pixel texture - RGBA8 + glGenTextures(1, &mini4_edge_texture_); + glBindTexture(GL_TEXTURE_2D, mini4_edge_texture_); + GLenum format = GL_RGBA8UI; + if (!supports_usampler_) { + format = GL_RGBA8; + } + glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, (width + 1) / 2, + (height + 1) / 2); + + // Depth + glGenTextures(1, &mini4_edge_depth_texture_); + glBindTexture(GL_TEXTURE_2D, mini4_edge_depth_texture_); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, (width + 1) / 2, + (height + 1) / 2); + + // Create the FBO + glGenFramebuffersEXT(1, &cmaa_framebuffer_); + glBindFramebufferEXT(GL_FRAMEBUFFER, cmaa_framebuffer_); + + // We need to clear the textures before they are first used. + // The algorithm self-clears them later. + glViewport(0, 0, width_, height_); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glBindFramebufferEXT(GL_FRAMEBUFFER, cmaa_framebuffer_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + edges0_texture_, 0); + glClear(GL_COLOR_BUFFER_BIT); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + edges1_texture_, 0); + glClear(GL_COLOR_BUFFER_BIT); + + textures_initialized_ = true; +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::ReleaseTextures() { + if (textures_initialized_) { + glDeleteFramebuffersEXT(1, ©_framebuffer_); + glDeleteFramebuffersEXT(1, &cmaa_framebuffer_); + glDeleteTextures(1, &rgba8_texture_); + glDeleteTextures(1, &edges0_texture_); + glDeleteTextures(1, &edges1_texture_); + glDeleteTextures(1, &mini4_edge_texture_); + glDeleteTextures(1, &mini4_edge_depth_texture_); + glDeleteTextures(1, &working_color_texture_); + } + textures_initialized_ = false; +} + +void ApplyFramebufferAttachmentCMAAINTELResourceManager::CopyTexture( + GLint source, + GLint dest, + bool via_fbo) { + glViewport(0, 0, width_, height_); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, source); + + if (!via_fbo) { + glUseProgram(copy_to_image_shader_); + if (!is_gles31_compatible_) { + glUniform1i(copy_to_image_shader_outTexture_, 0); + } + glBindImageTextureEXT(0, dest, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); + } else { + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_CULL_FACE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + glUseProgram(copy_to_framebuffer_shader_); + } + + glDrawArrays(GL_TRIANGLES, 0, 3); + glUseProgram(0); + glBindTexture(GL_TEXTURE_2D, 0); +} + +GLuint ApplyFramebufferAttachmentCMAAINTELResourceManager::CreateProgram( + const char* defines, + const char* vs_source, + const char* fs_source) { + GLuint program = glCreateProgram(); + + GLuint vs = CreateShader(GL_VERTEX_SHADER, defines, vs_source); + GLuint fs = CreateShader(GL_FRAGMENT_SHADER, defines, fs_source); + + glAttachShader(program, vs); + glDeleteShader(vs); + glAttachShader(program, fs); + glDeleteShader(fs); + + glLinkProgram(program); + GLint link_status; + glGetProgramiv(program, GL_LINK_STATUS, &link_status); + + if (link_status == 0) { +#if DCHECK_IS_ON() + GLint info_log_length; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length); + std::vector<GLchar> info_log(info_log_length); + glGetProgramInfoLog(program, static_cast<GLsizei>(info_log.size()), NULL, + &info_log[0]); + DLOG(ERROR) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "program link failed: " << &info_log[0]; +#endif + glDeleteProgram(program); + program = 0; + } + + return program; +} + +GLuint ApplyFramebufferAttachmentCMAAINTELResourceManager::CreateShader( + GLenum type, + const char* defines, + const char* source) { + GLuint shader = glCreateShader(type); + + const char header_es31[] = + "#version 310 es \n"; + const char header_gl30[] = + "#version 130 \n" + "#extension GL_ARB_shading_language_420pack : require \n" + "#extension GL_ARB_texture_gather : require \n" + "#extension GL_ARB_explicit_uniform_location : require \n" + "#extension GL_ARB_explicit_attrib_location : require \n" + "#extension GL_ARB_shader_image_load_store : require \n"; + + const char* header = NULL; + if (is_gles31_compatible_) { + header = header_es31; + } else { + header = header_gl30; + } + + const char* source_array[4] = {header, defines, "\n", source}; + glShaderSource(shader, 4, source_array, NULL); + + glCompileShader(shader); + + GLint compile_result; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_result); + if (compile_result == 0) { +#if DCHECK_IS_ON() + GLint info_log_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length); + std::vector<GLchar> info_log(info_log_length); + glGetShaderInfoLog(shader, static_cast<GLsizei>(info_log.size()), NULL, + &info_log[0]); + DLOG(ERROR) << "ApplyFramebufferAttachmentCMAAINTEL: " + << "shader compilation failed: " + << (type == GL_VERTEX_SHADER + ? "GL_VERTEX_SHADER" + : (type == GL_FRAGMENT_SHADER ? "GL_FRAGMENT_SHADER" + : "UNKNOWN_SHADER")) + << " shader compilation failed: " << &info_log[0]; +#endif + glDeleteShader(shader); + shader = 0; + } + + return shader; +} + +// Shaders used in the CMAA algorithm. +const char ApplyFramebufferAttachmentCMAAINTELResourceManager::vert_str_[] = + "precision highp float; \n" + "layout(location = 0) uniform float g_Depth; \n" + "// No input data. \n" + "// Verts are autogenerated. \n" + "// \n" + "// vertexID 0,1,2 should generate \n" + "// POS: (-1,-1), (+3,-1), (-1,+3) \n" + "// \n" + "// This generates a triangle that completely covers the -1->1 viewport \n" + "// \n" + "void main() \n" + "{ \n" + " float x = -1.0 + float((gl_VertexID & 1) << 2); \n" + " float y = -1.0 + float((gl_VertexID & 2) << 1); \n" + " gl_Position = vec4(x, y, g_Depth, 1.0); \n" + "} \n" + " \n"; + +const char ApplyFramebufferAttachmentCMAAINTELResourceManager::cmaa_frag_s1_[] = + "precision highp float; \n" + "precision highp int; \n" + " \n" + "#define SETTINGS_ALLOW_SHORT_Zs 1 \n" + "#define EDGE_DETECT_THRESHOLD 13.0f \n" + " \n" + "#define saturate(x) clamp((x), 0.0, 1.0) \n" + " \n" + "// bind to location 0 \n" + "layout(location = 0) uniform float g_Depth; \n" + "// bind to a uniform buffer bind point 0 \n" + "layout(location = 1) uniform vec2 g_OneOverScreenSize; \n" + "#ifndef EDGE_DETECT_THRESHOLD \n" + "layout(location = 2) uniform float g_ColorThreshold; \n" + "#endif \n" + " \n" + "#ifdef SUPPORTS_USAMPLER2D \n" + "#define USAMPLER usampler2D \n" + "#define UVEC4 uvec4 \n" + "#define LOAD_UINT(arg) arg \n" + "#define STORE_UVEC4(arg) arg \n" + "#else \n" + "#define USAMPLER sampler2D \n" + "#define UVEC4 vec4 \n" + "#define LOAD_UINT(arg) uint(arg * 255.0f) \n" + "#define STORE_UVEC4(arg) vec4(float(arg.x) / 255.0f, \n" + " float(arg.y) / 255.0f, \n" + " float(arg.z) / 255.0f, \n" + " float(arg.w) / 255.0f) \n" + "#endif \n" + " \n" + "// bind to texture stage 0/1 \n" + "layout(binding = 0) uniform highp sampler2D g_screenTexture; \n" + "layout(binding = 1) uniform highp sampler2D g_src0TextureFlt; \n" + "layout(binding = 1) uniform highp USAMPLER g_src0Texture4Uint; \n" + " \n" + "// bind to image stage 0/1/2 \n" + "#ifdef GL_ES \n" + "layout(binding = 0, EDGE_READ_FORMAT) restrict writeonly uniform highp \n" + " image2D g_resultTexture; \n" + "layout(binding = 1, rgba8) restrict writeonly uniform highp \n" + " image2D g_resultTextureFlt4Slot1; \n" + "layout(binding = 2, EDGE_READ_FORMAT) restrict writeonly uniform highp \n" + " image2D g_resultTextureSlot2; \n" + "#else \n" + "layout(EDGE_READ_FORMAT) restrict writeonly uniform highp \n" + " image2D g_resultTexture; \n" + "layout(rgba8) restrict writeonly uniform highp \n" + " image2D g_resultTextureFlt4Slot1; \n" + "layout(EDGE_READ_FORMAT) restrict writeonly uniform highp \n" + " image2D g_resultTextureSlot2; \n" + "#endif \n" + " \n" + "// Constants \n" + "const vec4 c_lumWeights = vec4(0.2126f, 0.7152f, 0.0722f, 0.0000f); \n" + " \n" + "#ifdef EDGE_DETECT_THRESHOLD \n" + "const float c_ColorThreshold = 1.0f / EDGE_DETECT_THRESHOLD; \n" + "#endif \n" + " \n" + "// Must be even number; Will work with ~16 pretty good too for \n" + "// additional performance, or with ~64 for highest quality. \n" + "const int c_maxLineLength = 64; \n" + " \n" + "const vec4 c_edgeDebugColours[5] = vec4[5](vec4(0.5, 0.5, 0.5, 0.4), \n" + " vec4(1.0, 0.1, 1.0, 0.8), \n" + " vec4(0.9, 0.0, 0.0, 0.8), \n" + " vec4(0.0, 0.9, 0.0, 0.8), \n" + " vec4(0.0, 0.0, 0.9, 0.8)); \n" + " \n" + "// this isn't needed if colour UAV is _SRGB but that doesn't work \n" + "// everywhere \n" + "#ifdef IN_GAMMA_CORRECT_MODE \n" + "///////////////////////////////////////////////////////////////////////\n" + "// \n" + "// SRGB Helper Functions taken from D3DX_DXGIFormatConvert.inl \n" + "float D3DX_FLOAT_to_SRGB(float val) { \n" + " if (val < 0.0031308f) \n" + " val *= 12.92f; \n" + " else { \n" + " val = 1.055f * pow(val, 1.0f / 2.4f) - 0.055f; \n" + " } \n" + " return val; \n" + "} \n" + "// \n" + "vec3 D3DX_FLOAT3_to_SRGB(vec3 val) { \n" + " vec3 outVal; \n" + " outVal.x = D3DX_FLOAT_to_SRGB(val.x); \n" + " outVal.y = D3DX_FLOAT_to_SRGB(val.y); \n" + " outVal.z = D3DX_FLOAT_to_SRGB(val.z); \n" + " return outVal; \n" + "} \n" + "// \n" + "///////////////////////////////////////////////////////////////////////\n" + "#endif // IN_GAMMA_CORRECT_MODE \n" + " \n" + "// how .rgba channels from the edge texture maps to pixel edges: \n" + "// \n" + "// A - 0x08 \n" + "// |¯¯¯¯¯¯¯¯¯| \n" + "// | | \n" + "// 0x04 - B | pixel | R - 0x01 \n" + "// | | \n" + "// |_________| \n" + "// G - 0x02 \n" + "// \n" + "// (A - there's an edge between us and a pixel above us) \n" + "// (R - there's an edge between us and a pixel to the right) \n" + "// (G - there's an edge between us and a pixel at the bottom) \n" + "// (B - there's an edge between us and a pixel to the left) \n" + " \n" + "// Expecting values of 1 and 0 only! \n" + "uint PackEdge(uvec4 edges) { \n" + " return (edges.x << 0u) | (edges.y << 1u) | (edges.z << 2u) | \n" + " (edges.w << 3u); \n" + "} \n" + " \n" + "uvec4 UnpackEdge(uint value) { \n" + " uvec4 ret; \n" + " ret.x = (value & 0x01u) != 0u ? 1u : 0u; \n" + " ret.y = (value & 0x02u) != 0u ? 1u : 0u; \n" + " ret.z = (value & 0x04u) != 0u ? 1u : 0u; \n" + " ret.w = (value & 0x08u) != 0u ? 1u : 0u; \n" + " return ret; \n" + "} \n" + " \n" + "uint PackZ(const uvec2 screenPos, const bool invertedZShape) { \n" + " uint retVal = screenPos.x | (screenPos.y << 15u); \n" + " if (invertedZShape) \n" + " retVal |= (1u << 30u); \n" + " return retVal; \n" + "} \n" + " \n" + "void UnpackZ(uint packedZ, out uvec2 screenPos, \n" + " out bool invertedZShape) \n" + "{ \n" + " screenPos.x = packedZ & 0x7FFFu; \n" + " screenPos.y = (packedZ >> 15u) & 0x7FFFu; \n" + " invertedZShape = (packedZ >> 30u) == 1u; \n" + "} \n" + " \n" + "uint PackZ(const uvec2 screenPos, \n" + " const bool invertedZShape, \n" + " const bool horizontal) { \n" + " uint retVal = screenPos.x | (screenPos.y << 15u); \n" + " if (invertedZShape) \n" + " retVal |= (1u << 30u); \n" + " if (horizontal) \n" + " retVal |= (1u << 31u); \n" + " return retVal; \n" + "} \n" + " \n" + "void UnpackZ(uint packedZ, \n" + " out uvec2 screenPos, \n" + " out bool invertedZShape, \n" + " out bool horizontal) { \n" + " screenPos.x = packedZ & 0x7FFFu; \n" + " screenPos.y = (packedZ >> 15u) & 0x7FFFu; \n" + " invertedZShape = (packedZ & (1u << 30u)) != 0u; \n" + " horizontal = (packedZ & (1u << 31u)) != 0u; \n" + "} \n" + " \n" + "vec4 PackBlurAAInfo(ivec2 pixelPos, uint shapeType) { \n" + " uint packedEdges = uint( \n" + " texelFetch(g_src0TextureFlt, pixelPos, 0).r * 255.5); \n" + " \n" + " float retval = float(packedEdges + (shapeType << 4u)); \n" + " \n" + " return vec4(retval / 255.0); \n" + "} \n" + " \n" + "void UnpackBlurAAInfo(float packedValue, out uint edges, \n" + " out uint shapeType) { \n" + " uint packedValueInt = uint(packedValue * 255.5); \n" + " edges = packedValueInt & 0xFu; \n" + " shapeType = packedValueInt >> 4u; \n" + "} \n" + " \n" + "float EdgeDetectColorCalcDiff(vec3 colorA, vec3 colorB) { \n" + "#ifdef IN_BGR_MODE \n" + " vec3 LumWeights = c_lumWeights.bgr; \n" + "#else \n" + " vec3 LumWeights = c_lumWeights.rgb; \n" + "#endif \n" + " \n" + " return dot(abs(colorA.rgb - colorB.rgb), LumWeights); \n" + "} \n" + " \n" + "bool EdgeDetectColor(vec3 colorA, vec3 colorB) { \n" + "#ifdef EDGE_DETECT_THRESHOLD \n" + " return EdgeDetectColorCalcDiff(colorA, colorB) > c_ColorThreshold; \n" + "#else \n" + " return EdgeDetectColorCalcDiff(colorA, colorB) > g_ColorThreshold; \n" + "#endif \n" + "} \n" + " \n" + "void FindLineLength(out int lineLengthLeft, \n" + " out int lineLengthRight, \n" + " ivec2 screenPos, \n" + " const bool horizontal, \n" + " const bool invertedZShape, \n" + " const ivec2 stepRight) { \n" + " // TODO: there must be a cleaner and faster way to get to these - \n" + " // a precalculated array indexing maybe? \n" + " uint maskLeft, bitsContinueLeft, maskRight, bitsContinueRight; \n" + " { \n" + " // Horizontal (vertical is the same, just rotated 90º \n" + " // counter-clockwise) \n" + " // Inverted Z case: // Normal Z case: \n" + " // __ // __ \n" + " // X| // X| \n" + " // -- // -- \n" + " // \n" + " uint maskTraceLeft, maskTraceRight; \n" + " uint maskStopLeft, maskStopRight; \n" + " if (horizontal) { \n" + " if (invertedZShape) { \n" + " maskTraceLeft = 0x02u; // tracing bottom edge \n" + " maskTraceRight = 0x08u; // tracing top edge \n" + " } else { \n" + " maskTraceLeft = 0x08u; // tracing top edge \n" + " maskTraceRight = 0x02u; // tracing bottom edge \n" + " } \n" + " maskStopLeft = 0x01u; // stop on right edge \n" + " maskStopRight = 0x04u; // stop on left edge \n" + " } else { \n" + " if (invertedZShape) { \n" + " maskTraceLeft = 0x01u; // tracing right edge \n" + " maskTraceRight = 0x04u; // tracing left edge \n" + " } else { \n" + " maskTraceLeft = 0x04u; // tracing left edge \n" + " maskTraceRight = 0x01u; // tracing right edge \n" + " } \n" + " maskStopLeft = 0x08u; // stop on top edge \n" + " maskStopRight = 0x02u; // stop on bottom edge \n" + " } \n" + " \n" + " maskLeft = maskTraceLeft | maskStopLeft; \n" + " bitsContinueLeft = maskTraceLeft; \n" + " maskRight = maskTraceRight | maskStopRight; \n" + " bitsContinueRight = maskTraceRight; \n" + " } \n" + "///////////////////////////////////////////////////////////////////////\n" + " \n" + "#ifdef SETTINGS_ALLOW_SHORT_Zs \n" + " int i = 1; \n" + "#else \n" + " int i = 2; // starting from 2 because we already know it's at least 2\n" + "#endif \n" + " for (; i < c_maxLineLength; i++) { \n" + " uint edgeLeft = uint( \n" + " texelFetch(g_src0TextureFlt, \n" + " ivec2(screenPos.xy - stepRight * i), 0).r * 255.5); \n" + " uint edgeRight = uint( \n" + " texelFetch(g_src0TextureFlt, \n" + " ivec2(screenPos.xy + stepRight * (i + 1)), \n" + " 0).r * 255.5); \n" + " \n" + " // stop on encountering 'stopping' edge (as defined by masks) \n" + " int stopLeft = (edgeLeft & maskLeft) != bitsContinueLeft ? 1 : 0; \n" + " int stopRight = \n" + " (edgeRight & maskRight) != bitsContinueRight ? 1 : 0; \n" + " \n" + " if (bool(stopLeft) || bool(stopRight)) { \n" + " lineLengthLeft = 1 + i - stopLeft; \n" + " lineLengthRight = 1 + i - stopRight; \n" + " return; \n" + " } \n" + " } \n" + " lineLengthLeft = lineLengthRight = i; \n" + " return; \n" + "} \n" + " \n" + "void ProcessDetectedZ(ivec2 screenPos, bool horizontal, \n" + " bool invertedZShape) { \n" + " int lineLengthLeft, lineLengthRight; \n" + " \n" + " ivec2 stepRight = (horizontal) ? (ivec2(1, 0)) : (ivec2(0, -1)); \n" + " vec2 blendDir = (horizontal) ? (vec2(0, -1)) : (vec2(-1, 0)); \n" + " \n" + " FindLineLength(lineLengthLeft, lineLengthRight, screenPos, \n" + " horizontal, invertedZShape, stepRight); \n" + " \n" + " vec2 pixelSize = g_OneOverScreenSize; \n" + " \n" + " float leftOdd = 0.15 * float(lineLengthLeft % 2); \n" + " float rightOdd = 0.15 * float(lineLengthRight % 2); \n" + " \n" + " int loopFrom = -int((lineLengthLeft + 1) / 2) + 1; \n" + " int loopTo = int((lineLengthRight + 1) / 2); \n" + " \n" + " float totalLength = float(loopTo - loopFrom) + 1.0 - leftOdd - \n" + " rightOdd; \n" + " \n" + " for (int i = loopFrom; i <= loopTo; i++) { \n" + " highp ivec2 pixelPos = screenPos + stepRight * i; \n" + " vec2 pixelPosFlt = vec2(float(pixelPos.x) + 0.5, \n" + " float(pixelPos.y) + 0.5); \n" + " \n" + "#ifdef DEBUG_OUTPUT_AAINFO \n" + " imageStore(g_resultTextureSlot2, pixelPos, \n" + " PackBlurAAInfo(pixelPos, 1u)); \n" + "#endif \n" + " \n" + " float m = (float(i) + 0.5 - leftOdd - float(loopFrom)) / \n" + " totalLength; \n" + " m = saturate(m); \n" + " float k = m - ((i > 0) ? 1.0 : 0.0); \n" + " k = (invertedZShape) ? (-k) : (k); \n" + " \n" + " vec4 color = textureLod(g_screenTexture, \n" + " (pixelPosFlt + blendDir * k) * pixelSize, \n" + " 0.0); \n" + " \n" + "#ifdef IN_GAMMA_CORRECT_MODE \n" + " color.rgb = D3DX_FLOAT3_to_SRGB(color.rgb); \n" + "#endif \n" + " imageStore(g_resultTextureFlt4Slot1, pixelPos, color); \n" + " } \n" + "} \n" + " \n" + "vec4 CalcDbgDisplayColor(const vec4 blurMap) { \n" + " vec3 pixelC = vec3(0.0, 0.0, 0.0); \n" + " vec3 pixelL = vec3(0.0, 0.0, 1.0); \n" + " vec3 pixelT = vec3(1.0, 0.0, 0.0); \n" + " vec3 pixelR = vec3(0.0, 1.0, 0.0); \n" + " vec3 pixelB = vec3(0.8, 0.8, 0.0); \n" + " \n" + " const float centerWeight = 1.0; \n" + " float fromBelowWeight = (1.0 / (1.0 - blurMap.x)) - 1.0; \n" + " float fromAboveWeight = (1.0 / (1.0 - blurMap.y)) - 1.0; \n" + " float fromRightWeight = (1.0 / (1.0 - blurMap.z)) - 1.0; \n" + " float fromLeftWeight = (1.0 / (1.0 - blurMap.w)) - 1.0; \n" + " \n" + " float weightSum = centerWeight + dot(vec4(fromBelowWeight, \n" + " fromAboveWeight, \n" + " fromRightWeight, \n" + " fromLeftWeight), \n" + " vec4(1, 1, 1, 1)); \n" + " \n" + " vec4 pixel; \n" + " \n" + " pixel.rgb = pixelC.rgb + fromAboveWeight * pixelT + \n" + " fromBelowWeight * pixelB + \n" + " fromLeftWeight * pixelL + \n" + " fromRightWeight * pixelR; \n" + " pixel.rgb /= weightSum; \n" + " \n" + " pixel.a = dot(pixel.rgb, vec3(1, 1, 1)) * 100.0; \n" + " \n" + " return saturate(pixel); \n" + "} \n" + " \n" + "#ifdef DETECT_EDGES1 \n" + "layout(location = 0) out UVEC4 outEdges; \n" + "void DetectEdges1() { \n" + " uvec4 outputEdges; \n" + " ivec2 screenPosI = ivec2(gl_FragCoord.xy) * ivec2(2, 2); \n" + " \n" + " // .rgb contains colour, .a contains flag whether to output it to \n" + " // working colour texture \n" + " vec4 pixel00 = texelFetch(g_screenTexture, screenPosI.xy, 0); \n" + " vec4 pixel10 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 0));\n" + " vec4 pixel20 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(2, 0));\n" + " vec4 pixel01 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, 1));\n" + " vec4 pixel11 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 1));\n" + " vec4 pixel21 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(2, 1));\n" + " vec4 pixel02 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, 2));\n" + " vec4 pixel12 = \n" + " texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 2));\n" + " \n" + " float storeFlagPixel00 = 0.0; \n" + " float storeFlagPixel10 = 0.0; \n" + " float storeFlagPixel20 = 0.0; \n" + " float storeFlagPixel01 = 0.0; \n" + " float storeFlagPixel11 = 0.0; \n" + " float storeFlagPixel21 = 0.0; \n" + " float storeFlagPixel02 = 0.0; \n" + " float storeFlagPixel12 = 0.0; \n" + " \n" + " vec2 et; \n" + " \n" + "#ifdef EDGE_DETECT_THRESHOLD \n" + " float threshold = c_ColorThreshold; \n" + "#else \n" + " float threshold = g_ColorThreshold; \n" + "#endif \n" + " \n" + " { \n" + " et.x = EdgeDetectColorCalcDiff(pixel00.rgb, pixel10.rgb); \n" + " et.y = EdgeDetectColorCalcDiff(pixel00.rgb, pixel01.rgb); \n" + " et = saturate(et - threshold); \n" + " ivec2 eti = ivec2(et * 15.0 + 0.99); \n" + " outputEdges.x = uint(eti.x | (eti.y << 4)); \n" + " \n" + " storeFlagPixel00 += et.x; \n" + " storeFlagPixel00 += et.y; \n" + " storeFlagPixel10 += et.x; \n" + " storeFlagPixel01 += et.y; \n" + " } \n" + " \n" + " { \n" + " et.x = EdgeDetectColorCalcDiff(pixel10.rgb, pixel20.rgb); \n" + " et.y = EdgeDetectColorCalcDiff(pixel10.rgb, pixel11.rgb); \n" + " et = saturate(et - threshold); \n" + " ivec2 eti = ivec2(et * 15.0 + 0.99); \n" + " outputEdges.y = uint(eti.x | (eti.y << 4)); \n" + " \n" + " storeFlagPixel10 += et.x; \n" + " storeFlagPixel10 += et.y; \n" + " storeFlagPixel20 += et.x; \n" + " storeFlagPixel11 += et.y; \n" + " } \n" + " \n" + " { \n" + " et.x = EdgeDetectColorCalcDiff(pixel01.rgb, pixel11.rgb); \n" + " et.y = EdgeDetectColorCalcDiff(pixel01.rgb, pixel02.rgb); \n" + " et = saturate(et - threshold); \n" + " ivec2 eti = ivec2(et * 15.0 + 0.99); \n" + " outputEdges.z = uint(eti.x | (eti.y << 4)); \n" + " \n" + " storeFlagPixel01 += et.x; \n" + " storeFlagPixel01 += et.y; \n" + " storeFlagPixel11 += et.x; \n" + " storeFlagPixel02 += et.y; \n" + " } \n" + " \n" + " { \n" + " et.x = EdgeDetectColorCalcDiff(pixel11.rgb, pixel21.rgb); \n" + " et.y = EdgeDetectColorCalcDiff(pixel11.rgb, pixel12.rgb); \n" + " et = saturate(et - threshold); \n" + " ivec2 eti = ivec2(et * 15.0 + 0.99); \n" + " outputEdges.w = uint(eti.x | (eti.y << 4)); \n" + " \n" + " storeFlagPixel11 += et.x; \n" + " storeFlagPixel11 += et.y; \n" + " storeFlagPixel21 += et.x; \n" + " storeFlagPixel12 += et.y; \n" + " } \n" + " \n" + " gl_FragDepth = any(bvec4(outputEdges)) ? 1.0 : 0.0; \n" + " \n" + " if (gl_FragDepth != 0.0) { \n" + " if (storeFlagPixel00 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(0, 0),\n" + " pixel00); \n" + " if (storeFlagPixel10 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(1, 0),\n" + " pixel10); \n" + " if (storeFlagPixel20 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(2, 0),\n" + " pixel20); \n" + " if (storeFlagPixel01 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(0, 1),\n" + " pixel01); \n" + " if (storeFlagPixel02 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(0, 2),\n" + " pixel02); \n" + " if (storeFlagPixel11 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(1, 1),\n" + " pixel11); \n" + " if (storeFlagPixel21 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(2, 1),\n" + " pixel21); \n" + " if (storeFlagPixel12 != 0.0) \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy + ivec2(1, 2),\n" + " pixel12); \n" + " } \n" + " outEdges = STORE_UVEC4(outputEdges); \n" + "} \n" + "#endif // DETECT_EDGES1 \n" + " \n" + "vec2 UnpackThresholds(uint val) { \n" + " return vec2(val & 0x0Fu, val >> 4u) / 15.0f; \n" + "} \n" + " \n" + "uint PruneNonDominantEdges(vec4 edges[3]) { \n" + " vec4 maxE4 = vec4(0.0, 0.0, 0.0, 0.0); \n" + " \n" + " float avg = 0.0; \n" + " \n" + " for (int i = 0; i < 3; i++) { \n" + " maxE4 = max(maxE4, edges[i]); \n" + " \n" + " avg = dot(edges[i], vec4(1, 1, 1, 1) / (3.0 * 4.0)); \n" + " } \n" + " \n" + " vec2 maxE2 = max(maxE4.xy, maxE4.zw); \n" + " float maxE = max(maxE2.x, maxE2.y); \n" + " \n" + " float threshold = avg * 0.65 + maxE * 0.35; \n" + " \n" + " // threshold = 0.0001; // this disables non-dominant edge pruning! \n" + " \n" + " uint cx = edges[0].x >= threshold ? 1u : 0u; \n" + " uint cy = edges[0].y >= threshold ? 1u : 0u; \n" + " return PackEdge(uvec4(cx, cy, 0, 0)); \n" + "} \n" + " \n" + "void CollectEdges(int offX, \n" + " int offY, \n" + " out vec4 edges[3], \n" + " const uint packedVals[6 * 6]) { \n" + " vec2 pixelP0P0 = UnpackThresholds(packedVals[(offX)*6+(offY)]); \n" + " vec2 pixelP1P0 = UnpackThresholds(packedVals[(offX+1)*6+(offY)]); \n" + " vec2 pixelP0P1 = UnpackThresholds(packedVals[(offX)*6+(offY+1)]); \n" + " vec2 pixelM1P0 = UnpackThresholds(packedVals[(offX-1)*6 +(offY)]); \n" + " vec2 pixelP0M1 = UnpackThresholds(packedVals[(offX)*6+(offY-1)]); \n" + " vec2 pixelP1M1 = UnpackThresholds(packedVals[(offX+1)*6 +(offY-1)]); \n" + " vec2 pixelM1P1 = UnpackThresholds(packedVals[(offX-1)*6+(offY+1)]); \n" + " \n" + " edges[0].x = pixelP0P0.x; \n" + " edges[0].y = pixelP0P0.y; \n" + " edges[0].z = pixelP1P0.x; \n" + " edges[0].w = pixelP1P0.y; \n" + " edges[1].x = pixelP0P1.x; \n" + " edges[1].y = pixelP0P1.y; \n" + " edges[1].z = pixelM1P0.x; \n" + " edges[1].w = pixelM1P0.y; \n" + " edges[2].x = pixelP0M1.x; \n" + " edges[2].y = pixelP0M1.y; \n" + " edges[2].z = pixelP1M1.y; \n" + " edges[2].w = pixelM1P1.x; \n" + "} \n" + " \n" + "#ifdef DETECT_EDGES2 \n" + "layout(early_fragment_tests) in; \n" + "void DetectEdges2() { \n" + " ivec2 screenPosI = ivec2(gl_FragCoord.xy); \n" + " \n" + " // source : edge differences from previous pass \n" + " uint packedVals[6 * 6]; \n" + " \n" + " // center pixel (our output) \n" + " UVEC4 packedQ4 = texelFetch(g_src0Texture4Uint, screenPosI.xy, 0); \n" + " packedVals[(2) * 6 + (2)] = LOAD_UINT(packedQ4.x); \n" + " packedVals[(3) * 6 + (2)] = LOAD_UINT(packedQ4.y); \n" + " packedVals[(2) * 6 + (3)] = LOAD_UINT(packedQ4.z); \n" + " packedVals[(3) * 6 + (3)] = LOAD_UINT(packedQ4.w); \n" + " \n" + " vec4 edges[3]; \n" + " if (bool(packedVals[(2) * 6 + (2)]) || \n" + " bool(packedVals[(3) * 6 + (2)])) { \n" + " UVEC4 packedQ1 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(0, -1)); \n" + " packedVals[(2) * 6 + (0)] = LOAD_UINT(packedQ1.x); \n" + " packedVals[(3) * 6 + (0)] = LOAD_UINT(packedQ1.y); \n" + " packedVals[(2) * 6 + (1)] = LOAD_UINT(packedQ1.z); \n" + " packedVals[(3) * 6 + (1)] = LOAD_UINT(packedQ1.w); \n" + " } \n" + " \n" + " if (bool(packedVals[(2) * 6 + (2)]) || \n" + " bool(packedVals[(2) * 6 + (3)])) { \n" + " UVEC4 packedQ3 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(-1, 0)); \n" + " packedVals[(0) * 6 + (2)] = LOAD_UINT(packedQ3.x); \n" + " packedVals[(1) * 6 + (2)] = LOAD_UINT(packedQ3.y); \n" + " packedVals[(0) * 6 + (3)] = LOAD_UINT(packedQ3.z); \n" + " packedVals[(1) * 6 + (3)] = LOAD_UINT(packedQ3.w); \n" + " } \n" + " \n" + " if (bool(packedVals[(2) * 6 + (2)])) { \n" + " CollectEdges(2, 2, edges, packedVals); \n" + " uint pe = PruneNonDominantEdges(edges); \n" + " if (pe != 0u) { \n" + " imageStore(g_resultTexture, 2 * screenPosI.xy + ivec2(0, 0), \n" + " vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); \n" + " } \n" + " } \n" + " \n" + " if (bool(packedVals[(3) * 6 + (2)]) || \n" + " bool(packedVals[(3) * 6 + (3)])) { \n" + " UVEC4 packedQ5 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(1, 0)); \n" + " packedVals[(4) * 6 + (2)] = LOAD_UINT(packedQ5.x); \n" + " packedVals[(5) * 6 + (2)] = LOAD_UINT(packedQ5.y); \n" + " packedVals[(4) * 6 + (3)] = LOAD_UINT(packedQ5.z); \n" + " packedVals[(5) * 6 + (3)] = LOAD_UINT(packedQ5.w); \n" + " } \n" + " \n" + " if (bool(packedVals[(3) * 6 + (2)])) { \n" + " UVEC4 packedQ2 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(1, -1)); \n" + " packedVals[(4) * 6 + (0)] = LOAD_UINT(packedQ2.x); \n" + " packedVals[(5) * 6 + (0)] = LOAD_UINT(packedQ2.y); \n" + " packedVals[(4) * 6 + (1)] = LOAD_UINT(packedQ2.z); \n" + " packedVals[(5) * 6 + (1)] = LOAD_UINT(packedQ2.w); \n" + " \n" + " CollectEdges(3, 2, edges, packedVals); \n" + " uint pe = PruneNonDominantEdges(edges); \n" + " if (pe != 0u) { \n" + " imageStore(g_resultTexture, 2 * screenPosI.xy + ivec2(1, 0), \n" + " vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); \n" + " } \n" + " } \n" + " \n" + " if (bool(packedVals[(2) * 6 + (3)]) || \n" + " bool(packedVals[(3) * 6 + (3)])) { \n" + " UVEC4 packedQ7 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(0, 1)); \n" + " packedVals[(2) * 6 + (4)] = LOAD_UINT(packedQ7.x); \n" + " packedVals[(3) * 6 + (4)] = LOAD_UINT(packedQ7.y); \n" + " packedVals[(2) * 6 + (5)] = LOAD_UINT(packedQ7.z); \n" + " packedVals[(3) * 6 + (5)] = LOAD_UINT(packedQ7.w); \n" + " } \n" + " \n" + " if (bool(packedVals[(2) * 6 + (3)])) { \n" + " UVEC4 packedQ6 = texelFetchOffset(g_src0Texture4Uint, \n" + " screenPosI.xy, 0, ivec2(-1, -1));\n" + " packedVals[(0) * 6 + (4)] = LOAD_UINT(packedQ6.x); \n" + " packedVals[(1) * 6 + (4)] = LOAD_UINT(packedQ6.y); \n" + " packedVals[(0) * 6 + (5)] = LOAD_UINT(packedQ6.z); \n" + " packedVals[(1) * 6 + (5)] = LOAD_UINT(packedQ6.w); \n" + " \n" + " CollectEdges(2, 3, edges, packedVals); \n" + " uint pe = PruneNonDominantEdges(edges); \n" + " if (pe != 0u) { \n" + " imageStore(g_resultTexture, 2 * screenPosI.xy + ivec2(0, 1), \n" + " vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); \n" + " } \n" + " } \n" + " \n" + " if (bool(packedVals[(3) * 6 + (3)])) { \n" + " CollectEdges(3, 3, edges, packedVals); \n" + " uint pe = PruneNonDominantEdges(edges); \n" + " if (pe != 0u) { \n" + " imageStore(g_resultTexture, 2 * screenPosI.xy + ivec2(1, 1), \n" + " vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); \n" + " } \n" + " } \n" + "} \n" + "#endif // DETECT_EDGES2 \n" + " \n"; + +const char ApplyFramebufferAttachmentCMAAINTELResourceManager::cmaa_frag_s2_[] = + "#ifdef COMBINE_EDGES \n" + "void CombineEdges() { \n" + " ivec3 screenPosIBase = ivec3(ivec2(gl_FragCoord.xy) * 2, 0); \n" + " vec3 screenPosBase = vec3(screenPosIBase); \n" + " uint packedEdgesArray[3 * 3]; \n" + " \n" + " // use only if it has the 'prev frame' flag:[sample * 255.0 - 127.5] \n" + " //-> if it has the last bit flag (128), it's going to stay above 0 \n" + " uvec4 sampA = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(1, 0)) * 255.0 - 127.5); \n" + " uvec4 sampB = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(0, 1)) * 255.0 - 127.5); \n" + " uint sampC = uint( \n" + " texelFetchOffset(g_src0TextureFlt, screenPosIBase.xy, 0, \n" + " ivec2(1, 1)).r * 255.0 - 127.5); \n" + " \n" + " packedEdgesArray[(0) * 3 + (0)] = 0u; \n" + " packedEdgesArray[(1) * 3 + (0)] = sampA.w; \n" + " packedEdgesArray[(2) * 3 + (0)] = sampA.z; \n" + " packedEdgesArray[(1) * 3 + (1)] = sampA.x; \n" + " packedEdgesArray[(2) * 3 + (1)] = sampA.y; \n" + " packedEdgesArray[(0) * 3 + (1)] = sampB.w; \n" + " packedEdgesArray[(0) * 3 + (2)] = sampB.x; \n" + " packedEdgesArray[(1) * 3 + (2)] = sampB.y; \n" + " packedEdgesArray[(2) * 3 + (2)] = sampC; \n" + " \n" + " uvec4 pixelsC = uvec4(packedEdgesArray[(1 + 0) * 3 + (1 + 0)], \n" + " packedEdgesArray[(1 + 1) * 3 + (1 + 0)], \n" + " packedEdgesArray[(1 + 0) * 3 + (1 + 1)], \n" + " packedEdgesArray[(1 + 1) * 3 + (1 + 1)]); \n" + " uvec4 pixelsL = uvec4(packedEdgesArray[(0 + 0) * 3 + (1 + 0)], \n" + " packedEdgesArray[(0 + 1) * 3 + (1 + 0)], \n" + " packedEdgesArray[(0 + 0) * 3 + (1 + 1)], \n" + " packedEdgesArray[(0 + 1) * 3 + (1 + 1)]); \n" + " uvec4 pixelsU = uvec4(packedEdgesArray[(1 + 0) * 3 + (0 + 0)], \n" + " packedEdgesArray[(1 + 1) * 3 + (0 + 0)], \n" + " packedEdgesArray[(1 + 0) * 3 + (0 + 1)], \n" + " packedEdgesArray[(1 + 1) * 3 + (0 + 1)]); \n" + " \n" + " uvec4 outEdge4 = \n" + " pixelsC | ((pixelsL & 0x01u) << 2u) | ((pixelsU & 0x02u) << 2u); \n" + " vec4 outEdge4Flt = vec4(outEdge4) / 255.0; \n" + " \n" + " imageStore(g_resultTextureSlot2, screenPosIBase.xy + ivec2(0, 0), \n" + " outEdge4Flt.xxxx); \n" + " imageStore(g_resultTextureSlot2, screenPosIBase.xy + ivec2(1, 0), \n" + " outEdge4Flt.yyyy); \n" + " imageStore(g_resultTextureSlot2, screenPosIBase.xy + ivec2(0, 1), \n" + " outEdge4Flt.zzzz); \n" + " imageStore(g_resultTextureSlot2, screenPosIBase.xy + ivec2(1, 1), \n" + " outEdge4Flt.wwww); \n" + " \n" + " // uvec4 numberOfEdges4 = uvec4(bitCount(outEdge4)); \n" + " // gl_FragDepth = \n" + " // any(greaterThan(numberOfEdges4, uvec4(1))) ? 1.0 : 0.0; \n" + " \n" + " gl_FragDepth = \n" + " any(greaterThan(outEdge4, uvec4(1))) ? 1.0 : 0.0; \n" + "} \n" + "#endif // COMBINE_EDGES \n" + " \n" + "#ifdef BLUR_EDGES \n" + "layout(early_fragment_tests) in; \n" + "void BlurEdges() { \n" + " int _i; \n" + " \n" + " ivec3 screenPosIBase = ivec3(ivec2(gl_FragCoord.xy) * 2, 0); \n" + " vec3 screenPosBase = vec3(screenPosIBase); \n" + " uint forFollowUpCount = 0u; \n" + " ivec4 forFollowUpCoords[4]; \n" + " \n" + " uint packedEdgesArray[4 * 4]; \n" + " \n" + " uvec4 sampA = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(0, 0)) *255.5); \n" + " uvec4 sampB = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(2, 0)) *255.5); \n" + " uvec4 sampC = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(0, 2)) *255.5); \n" + " uvec4 sampD = uvec4( \n" + " textureGatherOffset(g_src0TextureFlt, \n" + " screenPosBase.xy * g_OneOverScreenSize, \n" + " ivec2(2, 2)) *255.5); \n" + " \n" + " packedEdgesArray[(0) * 4 + (0)] = sampA.w; \n" + " packedEdgesArray[(1) * 4 + (0)] = sampA.z; \n" + " packedEdgesArray[(0) * 4 + (1)] = sampA.x; \n" + " packedEdgesArray[(1) * 4 + (1)] = sampA.y; \n" + " packedEdgesArray[(2) * 4 + (0)] = sampB.w; \n" + " packedEdgesArray[(3) * 4 + (0)] = sampB.z; \n" + " packedEdgesArray[(2) * 4 + (1)] = sampB.x; \n" + " packedEdgesArray[(3) * 4 + (1)] = sampB.y; \n" + " packedEdgesArray[(0) * 4 + (2)] = sampC.w; \n" + " packedEdgesArray[(1) * 4 + (2)] = sampC.z; \n" + " packedEdgesArray[(0) * 4 + (3)] = sampC.x; \n" + " packedEdgesArray[(1) * 4 + (3)] = sampC.y; \n" + " packedEdgesArray[(2) * 4 + (2)] = sampD.w; \n" + " packedEdgesArray[(3) * 4 + (2)] = sampD.z; \n" + " packedEdgesArray[(2) * 4 + (3)] = sampD.x; \n" + " packedEdgesArray[(3) * 4 + (3)] = sampD.y; \n" + " \n" + " for (_i = 0; _i < 4; _i++) { \n" + " int _x = _i % 2; \n" + " int _y = _i / 2; \n" + " \n" + " ivec3 screenPosI = screenPosIBase + ivec3(_x, _y, 0); \n" + " \n" + " uint packedEdgesC = packedEdgesArray[(1 + _x) * 4 + (1 + _y)]; \n" + " \n" + " uvec4 edges = UnpackEdge(packedEdgesC); \n" + " vec4 edgesFlt = vec4(edges); \n" + " \n" + " float numberOfEdges = dot(edgesFlt, vec4(1, 1, 1, 1)); \n" + " if (numberOfEdges < 2.0) \n" + " continue; \n" + " \n" + " float fromRight = edgesFlt.r; \n" + " float fromBelow = edgesFlt.g; \n" + " float fromLeft = edgesFlt.b; \n" + " float fromAbove = edgesFlt.a; \n" + " \n" + " vec4 xFroms = vec4(fromBelow, fromAbove, fromRight, fromLeft); \n" + " \n" + " float blurCoeff = 0.0; \n" + " \n" + " // These are additional blurs that complement the main line-based \n" + " // blurring; Unlike line-based, these do not necessarily preserve \n" + " // the total amount of screen colour as they will take \n" + " // neighbouring pixel colours and apply them to the one currently \n" + " // processed. \n" + " \n" + " // 1.) L-like shape. \n" + " // For this shape, the total amount of screen colour will be \n" + " // preserved when this is a part of a (zigzag) diagonal line as the\n" + " // corners from the other side will do the same and take some of \n" + " // the current pixel's colour in return. \n" + " // However, in the case when this is an actual corner, the pixel's \n" + " // colour will be partially overwritten by it's 2 neighbours. \n" + " // if( numberOfEdges > 1.0 ) \n" + " { \n" + " // with value of 0.15, the pixel will retain approx 77% of its \n" + " // colour and the remaining 23% will come from its 2 neighbours \n" + " // (which are likely to be blurred too in the opposite direction)\n" + " blurCoeff = 0.08; \n" + " \n" + " // Only do blending if it's L shape - if we're between two \n" + " // parallel edges, don't do anything \n" + " blurCoeff *= (1.0 - fromBelow * fromAbove) * \n" + " (1.0 - fromRight * fromLeft); \n" + " } \n" + " \n" + " // 2.) U-like shape (surrounded with edges from 3 sides) \n" + " if (numberOfEdges > 2.0) { \n" + " // with value of 0.13, the pixel will retain approx 72% of its \n" + " // colour and the remaining 28% will be picked from its 3 \n" + " // neighbours (which are unlikely to be blurred too but could be)\n" + " blurCoeff = 0.11; \n" + " } \n" + " \n" + " // 3.) Completely surrounded with edges from all 4 sides \n" + " if (numberOfEdges > 3.0) { \n" + " // with value of 0.07, the pixel will retain 78% of its colour \n" + " // and the remaining 22% will come from its 4 neighbours (which \n" + " // are unlikely to be blurred) \n" + " blurCoeff = 0.05; \n" + " } \n" + " \n" + " if (blurCoeff == 0.0) { \n" + " // this avoids Z search below as well but that's ok because a Z \n" + " // shape will also always have some blurCoeff \n" + " continue; \n" + " } \n" + " \n" + " vec4 blurMap = xFroms * blurCoeff; \n" + " \n" + " vec4 pixelC = texelFetch(g_screenTexture, screenPosI.xy, 0); \n" + " \n" + " const float centerWeight = 1.0; \n" + " float fromBelowWeight = blurMap.x; \n" + " float fromAboveWeight = blurMap.y; \n" + " float fromRightWeight = blurMap.z; \n" + " float fromLeftWeight = blurMap.w; \n" + " \n" + " // this would be the proper math for blending if we were handling \n" + " // lines (Zs) and mini kernel smoothing here, but since we're doing\n" + " // lines separately, no need to complicate, just tweak the settings\n" + " // float fromBelowWeight = (1.0 / (1.0 - blurMap.x)) - 1.0; \n" + " // float fromAboveWeight = (1.0 / (1.0 - blurMap.y)) - 1.0; \n" + " // float fromRightWeight = (1.0 / (1.0 - blurMap.z)) - 1.0; \n" + " // float fromLeftWeight = (1.0 / (1.0 - blurMap.w)) - 1.0; \n" + " \n" + " float fourWeightSum = dot(blurMap, vec4(1, 1, 1, 1)); \n" + " float allWeightSum = centerWeight + fourWeightSum; \n" + " \n" + " vec4 color = vec4(0, 0, 0, 0); \n" + " if (fromLeftWeight > 0.0) { \n" + " vec3 pixelL = texelFetchOffset(g_screenTexture, screenPosI.xy, 0,\n" + " ivec2(-1, 0)).rgb; \n" + " color.rgb += fromLeftWeight * pixelL; \n" + " } \n" + " if (fromAboveWeight > 0.0) { \n" + " vec3 pixelT = texelFetchOffset(g_screenTexture, screenPosI.xy, 0,\n" + " ivec2(0, -1)).rgb; \n" + " color.rgb += fromAboveWeight * pixelT; \n" + " } \n" + " if (fromRightWeight > 0.0) { \n" + " vec3 pixelR = texelFetchOffset(g_screenTexture, screenPosI.xy, 0,\n" + " ivec2(1, 0)).rgb; \n" + " color.rgb += fromRightWeight * pixelR; \n" + " } \n" + " if (fromBelowWeight > 0.0) { \n" + " vec3 pixelB = texelFetchOffset(g_screenTexture, screenPosI.xy, 0,\n" + " ivec2(0, 1)).rgb; \n" + " color.rgb += fromBelowWeight * pixelB; \n" + " } \n" + " \n" + " color /= fourWeightSum + 0.0001; \n" + " color.a = 1.0 - centerWeight / allWeightSum; \n" + " \n" + " color.rgb = mix(pixelC.rgb, color.rgb, color.a).rgb; \n" + "#ifdef IN_GAMMA_CORRECT_MODE \n" + " color.rgb = D3DX_FLOAT3_to_SRGB(color.rgb); \n" + "#endif \n" + " \n" + "#ifdef DEBUG_OUTPUT_AAINFO \n" + " imageStore(g_resultTextureSlot2, screenPosI.xy, \n" + " PackBlurAAInfo(screenPosI.xy, uint(numberOfEdges))); \n" + "#endif \n" + " imageStore(g_resultTextureFlt4Slot1, screenPosI.xy, \n" + " vec4(color.rgb, pixelC.a)); \n" + " \n" + " if (numberOfEdges == 2.0) { \n" + " uint packedEdgesL = packedEdgesArray[(0 + _x) * 4 + (1 + _y)]; \n" + " uint packedEdgesT = packedEdgesArray[(1 + _x) * 4 + (0 + _y)]; \n" + " uint packedEdgesR = packedEdgesArray[(2 + _x) * 4 + (1 + _y)]; \n" + " uint packedEdgesB = packedEdgesArray[(1 + _x) * 4 + (2 + _y)]; \n" + " \n" + " bool isHorizontalA = ((packedEdgesC) == (0x01u | 0x02u)) && \n" + " ((packedEdgesR & (0x01u | 0x08u)) == (0x08u)); \n" + " bool isHorizontalB = ((packedEdgesC) == (0x01u | 0x08u)) && \n" + " ((packedEdgesR & (0x01u | 0x02u)) == (0x02u)); \n" + " \n" + " bool isHCandidate = isHorizontalA || isHorizontalB; \n" + " \n" + " bool isVerticalA = ((packedEdgesC) == (0x08u | 0x01u)) && \n" + " ((packedEdgesT & (0x08u | 0x04u)) == (0x04u)); \n" + " bool isVerticalB = ((packedEdgesC) == (0x08u | 0x04u)) && \n" + " ((packedEdgesT & (0x08u | 0x01u)) == (0x01u)); \n" + " bool isVCandidate = isVerticalA || isVerticalB; \n" + " \n" + " bool isCandidate = isHCandidate || isVCandidate; \n" + " \n" + " if (!isCandidate) \n" + " continue; \n" + " \n" + " bool horizontal = isHCandidate; \n" + " \n" + " // what if both are candidates? do additional pruning (still not \n" + " // 100% but gets rid of worst case errors) \n" + " if (isHCandidate && isVCandidate) \n" + " horizontal = \n" + " (isHorizontalA && ((packedEdgesL & 0x02u) == 0x02u)) || \n" + " (isHorizontalB && ((packedEdgesL & 0x08u) == 0x08u)); \n" + " \n" + " ivec2 offsetC; \n" + " uint packedEdgesM1P0; \n" + " uint packedEdgesP1P0; \n" + " if (horizontal) { \n" + " packedEdgesM1P0 = packedEdgesL; \n" + " packedEdgesP1P0 = packedEdgesR; \n" + " offsetC = ivec2(2, 0); \n" + " } else { \n" + " packedEdgesM1P0 = packedEdgesB; \n" + " packedEdgesP1P0 = packedEdgesT; \n" + " offsetC = ivec2(0, -2); \n" + " } \n" + " \n" + " uvec4 edgesM1P0 = UnpackEdge(packedEdgesM1P0); \n" + " uvec4 edgesP1P0 = UnpackEdge(packedEdgesP1P0); \n" + " uvec4 edgesP2P0 = UnpackEdge(uint(texelFetch( \n" + " g_src0TextureFlt, screenPosI.xy + offsetC, 0).r * 255.5)); \n" + " \n" + " uvec4 arg0; \n" + " uvec4 arg1; \n" + " uvec4 arg2; \n" + " uvec4 arg3; \n" + " bool arg4; \n" + " \n" + " if (horizontal) { \n" + " arg0 = uvec4(edges); \n" + " arg1 = edgesM1P0; \n" + " arg2 = edgesP1P0; \n" + " arg3 = edgesP2P0; \n" + " arg4 = true; \n" + " } else { \n" + " // Reuse the same code for vertical (used for horizontal above)\n" + " // but rotate input data 90º counter-clockwise, so that: \n" + " // left becomes bottom \n" + " // top becomes left \n" + " // right becomes top \n" + " // bottom becomes right \n" + " \n" + " // we also have to rotate edges, thus .argb \n" + " arg0 = uvec4(edges.argb); \n" + " arg1 = edgesM1P0.argb; \n" + " arg2 = edgesP1P0.argb; \n" + " arg3 = edgesP2P0.argb; \n" + " arg4 = false; \n" + " } \n" + " \n" + " { \n" + " ivec2 screenPos = screenPosI.xy; \n" + " uvec4 _edges = arg0; \n" + " uvec4 _edgesM1P0 = arg1; \n" + " uvec4 _edgesP1P0 = arg2; \n" + " uvec4 _edgesP2P0 = arg3; \n" + " bool horizontal = arg4; \n" + " // Inverted Z case: \n" + " // __ \n" + " // X| \n" + " // ¯¯ \n" + " bool isInvertedZ = false; \n" + " bool isNormalZ = false; \n" + " { \n" + "#ifndef SETTINGS_ALLOW_SHORT_Zs \n" + " // (1u-_edges.a) constraint can be removed; it was added for \n" + " // some rare cases \n" + " uint isZShape = _edges.r * _edges.g * _edgesM1P0.g * \n" + " _edgesP1P0.a *_edgesP2P0.a * (1u - _edges.b) * \n" + " (1u - _edgesP1P0.r) * (1u - _edges.a) * \n" + " (1u - _edgesP1P0.g); \n" + "#else \n" + " uint isZShape = _edges.r * _edges.g * _edgesP1P0.a * \n" + " (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.a) *\n" + " (1u - _edgesP1P0.g); \n" + " isZShape *= (_edgesM1P0.g + _edgesP2P0.a); \n" + " // and at least one of these need to be there\n" + "#endif \n" + " if (isZShape > 0u) { \n" + " isInvertedZ = true; \n" + " } \n" + " } \n" + " \n" + " // Normal Z case: \n" + " // __ \n" + " // X| \n" + " // ¯¯ \n" + " { \n" + "#ifndef SETTINGS_ALLOW_SHORT_Zs \n" + " uint isZShape = _edges.r * _edges.a * _edgesM1P0.a * \n" + " _edgesP1P0.g * _edgesP2P0.g * (1u - _edges.b) * \n" + " (1u - _edgesP1P0.r) * (1u - _edges.g) * \n" + " (1u - _edgesP1P0.a); \n" + "#else \n" + " uint isZShape = _edges.r * _edges.a * _edgesP1P0.g * \n" + " (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.g) *\n" + " (1u - _edgesP1P0.a); \n" + " isZShape *= \n" + " (_edgesM1P0.a + _edgesP2P0.g); \n" + " // and at least one of these need to be there\n" + "#endif \n" + " \n" + " if (isZShape > 0u) { \n" + " isNormalZ = true; \n" + " } \n" + " } \n" + " \n" + " bool isZ = isInvertedZ || isNormalZ; \n" + " if (isZ) { \n" + " forFollowUpCoords[forFollowUpCount++] = \n" + " ivec4(screenPosI.xy, horizontal, isInvertedZ); \n" + " } \n" + " } \n" + " } \n" + " } \n" + " \n" + " // This code below is the only potential bug with this algorithm : \n" + " // it HAS to be executed after the simple shapes above. It used to be\n" + " // executed as separate compute shader (by storing the packed \n" + " // 'forFollowUpCoords' in an append buffer and consuming it later) \n" + " // but the whole thing (append/consume buffers, using CS) appears to \n" + " // be too inefficient on most hardware. \n" + " // However, it seems to execute fairly efficiently here and without \n" + " // any issues, although there is no 100% guarantee that this code \n" + " // below will execute across all pixels (it has a c_maxLineLength \n" + " // wide kernel) after other shaders processing same pixels have done \n" + " // solving simple shapes. It appears to work regardless, across all \n" + " // hardware; pixels with 1-edge or two opposing edges are ignored by \n" + " // simple shapes anyway and other shapes stop the long line \n" + " // algorithm from executing the only danger appears to be simple \n" + " // shape L's colliding with Z shapes from neighbouring pixels but I \n" + " // couldn't reproduce any problems on any hardware. \n" + " for (uint _i = 0u; _i < forFollowUpCount; _i++) { \n" + " ivec4 data = forFollowUpCoords[_i]; \n" + " ProcessDetectedZ(data.xy, bool(data.z), bool(data.w)); \n" + " } \n" + "} \n" + "#endif // BLUR_EDGES \n" + " \n" + "#ifdef DISPLAY_EDGES \n" + "layout(location = 0) out vec4 color; \n" + "layout(location = 1) out vec4 hasEdges; \n" + "void DisplayEdges() { \n" + " ivec2 screenPosI = ivec2(gl_FragCoord.xy); \n" + " \n" + " uint packedEdges, shapeType; \n" + " UnpackBlurAAInfo(texelFetch(g_src0TextureFlt, screenPosI, 0).r, \n" + " packedEdges, shapeType); \n" + " \n" + " vec4 edges = vec4(UnpackEdge(packedEdges)); \n" + " if (any(greaterThan(edges.xyzw, vec4(0)))) { \n" + "#ifdef IN_BGR_MODE \n" + " color = c_edgeDebugColours[shapeType].bgra; \n" + "#else \n" + " color = c_edgeDebugColours[shapeType]; \n" + "#endif \n" + " hasEdges = vec4(1.0); \n" + " } else { \n" + " color = vec4(0); \n" + " hasEdges = vec4(0.0); \n" + " } \n" + "} \n" + "#endif // DISPLAY_EDGES \n" + " \n" + "void main() { \n" + "#ifdef DETECT_EDGES1 \n" + " DetectEdges1(); \n" + "#endif \n" + "#if defined DETECT_EDGES2 \n" + " DetectEdges2(); \n" + "#endif \n" + "#if defined COMBINE_EDGES \n" + " CombineEdges(); \n" + "#endif \n" + "#if defined BLUR_EDGES \n" + " BlurEdges(); \n" + "#endif \n" + "#if defined DISPLAY_EDGES \n" + " DisplayEdges(); \n" + "#endif \n" + "} \n"; + +const char + ApplyFramebufferAttachmentCMAAINTELResourceManager::copy_frag_str_[] = + "precision highp float; \n" + "layout(binding = 0) uniform highp sampler2D inTexture; \n" + "layout(location = 0) out vec4 outColor; \n" + "#ifdef GL_ES \n" + "layout(binding = 0, rgba8) restrict writeonly uniform highp \n" + " image2D outTexture; \n" + "#else \n" + "layout(rgba8) restrict writeonly uniform highp image2D outTexture; \n" + "#endif \n" + " \n" + "void main() { \n" + " ivec2 screenPosI = ivec2( gl_FragCoord.xy ); \n" + " vec4 pixel = texelFetch(inTexture, screenPosI, 0); \n" + "#ifdef OUT_FBO \n" + " outColor = pixel; \n" + "#else \n" + " imageStore(outTexture, screenPosI, pixel); \n" + "#endif \n" + "} \n"; + +} // namespace gpu \ No newline at end of file
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h new file mode 100644 index 0000000..4f5b4833 --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h
@@ -0,0 +1,102 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_APPLY_FRAMEBUFFER_ATTACHMENT_CMAA_INTEL_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_APPLY_FRAMEBUFFER_ATTACHMENT_CMAA_INTEL_H_ + +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/gpu_export.h" + +namespace { +class CMAAEffect; +} + +namespace gpu { +namespace gles2 { +class GLES2Decoder; +class Framebuffer; +} + +// This class encapsulates the resources required to implement the +// GL_INTEL_framebuffer_CMAA extension via shaders. +// +// The CMAA Conservative Morphological Anti-Aliasing) algorithm is applied to +// all color attachments of the currently bound draw framebuffer. +// +// Reference GL_INTEL_framebuffer_CMAA for details. +class GPU_EXPORT ApplyFramebufferAttachmentCMAAINTELResourceManager { + public: + ApplyFramebufferAttachmentCMAAINTELResourceManager(); + ~ApplyFramebufferAttachmentCMAAINTELResourceManager(); + + void Initialize(gles2::GLES2Decoder* decoder); + void Destroy(); + + // Applies the algorithm to the color attachments of the currently bound draw + // framebuffer. + void ApplyFramebufferAttachmentCMAAINTEL(gles2::GLES2Decoder* decoder, + gles2::Framebuffer* framebuffer); + + private: + // Applies the CMAA algorithm to a texture. + void ApplyCMAAEffectTexture(GLuint source_texture, GLuint dest_texture); + + void OnSize(GLint width, GLint height); + void ReleaseTextures(); + + void CopyTexture(GLint source, GLint dest, bool via_fbo); + GLuint CreateProgram(const char* defines, + const char* vs_source, + const char* fs_source); + GLuint CreateShader(GLenum type, const char* defines, const char* source); + + bool initialized_; + bool textures_initialized_; + bool is_in_gamma_correct_mode_; + bool supports_usampler_; + bool supports_r8_image_; + bool supports_r8_read_format_; + bool is_gles31_compatible_; + + int frame_id_; + + GLint width_; + GLint height_; + + GLuint copy_to_framebuffer_shader_; + GLuint copy_to_image_shader_; + GLuint edges0_shader_; + GLuint edges1_shader_; + GLuint edges_combine_shader_; + GLuint process_and_apply_shader_; + GLuint debug_display_edges_shader_; + + GLuint cmaa_framebuffer_; + GLuint copy_framebuffer_; + + GLuint rgba8_texture_; + GLuint working_color_texture_; + GLuint edges0_texture_; + GLuint edges1_texture_; + GLuint mini4_edge_texture_; + GLuint mini4_edge_depth_texture_; + + GLuint edges1_shader_result_texture_float4_slot1_; + GLuint edges1_shader_result_texture_; + GLuint edges_combine_shader_result_texture_float4_slot1_; + GLuint process_and_apply_shader_result_texture_float4_slot1_; + GLuint edges_combine_shader_result_texture_slot2_; + GLuint copy_to_image_shader_outTexture_; + + static const char vert_str_[]; + static const char cmaa_frag_s1_[]; + static const char cmaa_frag_s2_[]; + static const char copy_frag_str_[]; + + DISALLOW_COPY_AND_ASSIGN(ApplyFramebufferAttachmentCMAAINTELResourceManager); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_APPLY_FRAMEBUFFER_ATTACHMENT_CMAA_INTEL_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index cc703d4e..71ee18f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -39,6 +39,7 @@ #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gl_stream_texture_image.h" #include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h" #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h" #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" @@ -2159,6 +2160,8 @@ // Log extra info. bool service_logging_; + std::unique_ptr<ApplyFramebufferAttachmentCMAAINTELResourceManager> + apply_framebuffer_attachment_cmaa_intel_; std::unique_ptr<CopyTexImageResourceManager> copy_tex_image_blit_; std::unique_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; std::unique_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_; @@ -4286,6 +4289,11 @@ } ReleaseAllBackTextures(); if (have_context) { + if (apply_framebuffer_attachment_cmaa_intel_.get()) { + apply_framebuffer_attachment_cmaa_intel_->Destroy(); + apply_framebuffer_attachment_cmaa_intel_.reset(); + } + if (copy_tex_image_blit_.get()) { copy_tex_image_blit_->Destroy(); copy_tex_image_blit_.reset(); @@ -4362,6 +4370,7 @@ // state_.current_program object. state_.current_program = NULL; + apply_framebuffer_attachment_cmaa_intel_.reset(); copy_tex_image_blit_.reset(); copy_texture_CHROMIUM_.reset(); clear_framebuffer_blit_.reset(); @@ -15313,7 +15322,28 @@ // Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the // color attachments of currently bound draw framebuffer. // Reference GL_INTEL_framebuffer_CMAA for details. - glApplyFramebufferAttachmentCMAAINTEL(); + // Use platform version if available. + if (!feature_info_->feature_flags() + .use_chromium_screen_space_antialiasing_via_shaders) { + glApplyFramebufferAttachmentCMAAINTEL(); + } else { + // Defer initializing the CopyTextureCHROMIUMResourceManager until it is + // needed because it takes ??s of milliseconds to initialize. + if (!apply_framebuffer_attachment_cmaa_intel_.get()) { + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER( + "glApplyFramebufferAttachmentCMAAINTEL"); + apply_framebuffer_attachment_cmaa_intel_.reset( + new ApplyFramebufferAttachmentCMAAINTELResourceManager()); + apply_framebuffer_attachment_cmaa_intel_->Initialize(this); + RestoreCurrentFramebufferBindings(); + if (LOCAL_PEEK_GL_ERROR("glApplyFramebufferAttachmentCMAAINTEL") != + GL_NO_ERROR) + return; + } + apply_framebuffer_attachment_cmaa_intel_ + ->ApplyFramebufferAttachmentCMAAINTEL( + this, GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER)); + } } void GLES2DecoderImpl::DoInsertEventMarkerEXT(
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index c75c35e..c419cb5 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi
@@ -58,6 +58,8 @@ 'command_buffer/service/gl_state_restorer_impl.h', 'command_buffer/service/gl_utils.cc', 'command_buffer/service/gl_utils.h', + 'command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc', + 'command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h', 'command_buffer/service/gles2_cmd_clear_framebuffer.cc', 'command_buffer/service/gles2_cmd_clear_framebuffer.h', 'command_buffer/service/gles2_cmd_copy_tex_image.cc',
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_ntp_snippets_service_factory.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_ntp_snippets_service_factory.cc index eef5186a..c4cb4251 100644 --- a/ios/chrome/browser/ntp_snippets/ios_chrome_ntp_snippets_service_factory.cc +++ b/ios/chrome/browser/ntp_snippets/ios_chrome_ntp_snippets_service_factory.cc
@@ -11,6 +11,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "components/browser_sync/browser/profile_sync_service.h" +#include "components/image_fetcher/image_decoder.h" #include "components/image_fetcher/image_fetcher.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "components/ntp_snippets/ntp_snippets_constants.h" @@ -109,6 +110,8 @@ base::SequencedWorkerPool::GetSequenceToken(), base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); + // TODO(treib,markusheintz): Inject an image_fetcher::ImageDecoder once that's + // implemented on iOS. crbug.com/609127 return base::WrapUnique(new ntp_snippets::NTPSnippetsService( false /* enabled */, chrome_browser_state->GetPrefs(), sync_service, suggestions_service, GetApplicationContext()->GetApplicationLocale(), @@ -118,6 +121,7 @@ GetChannel() == version_info::Channel::STABLE)), base::WrapUnique(new ImageFetcherImpl(request_context.get(), web::WebThread::GetBlockingPool())), + nullptr, /* image_decoder */ base::WrapUnique( new ntp_snippets::NTPSnippetsDatabase(database_dir, task_runner)))); }
diff --git a/media/audio/audio_device_thread.cc b/media/audio/audio_device_thread.cc index 20874599..5d0767a 100644 --- a/media/audio/audio_device_thread.cc +++ b/media/audio/audio_device_thread.cc
@@ -230,11 +230,17 @@ CHECK_GT(total_segments_, 0); CHECK_EQ(memory_length_ % total_segments_, 0); segment_length_ = memory_length_ / total_segments_; + thread_checker_.DetachFromThread(); } AudioDeviceThread::Callback::~Callback() {} void AudioDeviceThread::Callback::InitializeOnAudioThread() { + // Normally this function is called before the thread checker is used + // elsewhere, but it's not guaranteed. DCHECK to ensure it was not used on + // another thread before we get here. + DCHECK(thread_checker_.CalledOnValidThread()) + << "Thread checker was attached on the wrong thread"; MapSharedMemory(); CHECK(shared_memory_.memory()); }
diff --git a/media/audio/audio_device_thread.h b/media/audio/audio_device_thread.h index 61e5e872..1ffefc5 100644 --- a/media/audio/audio_device_thread.h +++ b/media/audio/audio_device_thread.h
@@ -12,6 +12,7 @@ #include "base/memory/shared_memory.h" #include "base/sync_socket.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "media/base/audio_parameters.h" #include "media/base/media_export.h" @@ -68,6 +69,11 @@ const int total_segments_; int segment_length_; + // Detached in constructor and attached in InitializeOnAudioThread() which + // is called on the audio device thread. Sub-classes can then use it for + // various thread checking purposes. + base::ThreadChecker thread_checker_; + private: DISALLOW_COPY_AND_ASSIGN(Callback); };
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc index 12d102c..e618b3b 100644 --- a/media/audio/audio_output_device.cc +++ b/media/audio/audio_output_device.cc
@@ -41,6 +41,10 @@ // Called whenever we receive notifications about pending data. void Process(uint32_t pending_data) override; + // Returns whether the current thread is the audio device thread or not. + // Will always return true if DCHECKs are not enabled. + bool CurrentThreadIsAudioDeviceThread(); + private: AudioRendererSink::RenderCallback* render_callback_; std::unique_ptr<AudioBus> output_bus_; @@ -154,6 +158,13 @@ device_status_, output_params_); } +bool AudioOutputDevice::CurrentThreadIsRenderingThread() { + // Since this function is supposed to be called on the rendering thread, + // it's safe to access |audio_callback_| here. It will always be valid when + // the rendering thread is running. + return audio_callback_->CurrentThreadIsAudioDeviceThread(); +} + void AudioOutputDevice::RequestDeviceAuthorizationOnIOThread() { DCHECK(task_runner()->BelongsToCurrentThread()); DCHECK_EQ(state_, IDLE); @@ -477,4 +488,9 @@ frames_skipped); } +bool AudioOutputDevice::AudioThreadCallback:: + CurrentThreadIsAudioDeviceThread() { + return thread_checker_.CalledOnValidThread(); +} + } // namespace media
diff --git a/media/audio/audio_output_device.h b/media/audio/audio_output_device.h index c0faacd..23f416c8 100644 --- a/media/audio/audio_output_device.h +++ b/media/audio/audio_output_device.h
@@ -109,6 +109,7 @@ void Pause() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + bool CurrentThreadIsRenderingThread() override; // Methods called on IO thread ---------------------------------------------- // AudioOutputIPCDelegate methods.
diff --git a/media/audio/audio_output_stream_sink.cc b/media/audio/audio_output_stream_sink.cc index 3acc6a8..b94e2d2 100644 --- a/media/audio/audio_output_stream_sink.cc +++ b/media/audio/audio_output_stream_sink.cc
@@ -77,6 +77,11 @@ return OutputDeviceInfo(); } +bool AudioOutputStreamSink::CurrentThreadIsRenderingThread() { + NOTIMPLEMENTED(); + return false; +} + int AudioOutputStreamSink::OnMoreData(AudioBus* dest, uint32_t total_bytes_delay, uint32_t frames_skipped) {
diff --git a/media/audio/audio_output_stream_sink.h b/media/audio/audio_output_stream_sink.h index d8656ee..672c3a05 100644 --- a/media/audio/audio_output_stream_sink.h +++ b/media/audio/audio_output_stream_sink.h
@@ -40,6 +40,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + bool CurrentThreadIsRenderingThread() override; // AudioSourceCallback implementation. int OnMoreData(AudioBus* dest,
diff --git a/media/audio/clockless_audio_sink.cc b/media/audio/clockless_audio_sink.cc index 91de5e0..d0dd7e94 100644 --- a/media/audio/clockless_audio_sink.cc +++ b/media/audio/clockless_audio_sink.cc
@@ -133,6 +133,11 @@ return device_info_; } +bool ClocklessAudioSink::CurrentThreadIsRenderingThread() { + NOTIMPLEMENTED(); + return false; +} + void ClocklessAudioSink::StartAudioHashForTesting() { DCHECK(!initialized_); hashing_ = true;
diff --git a/media/audio/clockless_audio_sink.h b/media/audio/clockless_audio_sink.h index a6db62c5..2b60d83 100644 --- a/media/audio/clockless_audio_sink.h +++ b/media/audio/clockless_audio_sink.h
@@ -37,6 +37,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + bool CurrentThreadIsRenderingThread() override; // Returns the time taken to consume all the audio. base::TimeDelta render_time() { return playback_time_; }
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc index 6d40c93..43221998 100644 --- a/media/audio/null_audio_sink.cc +++ b/media/audio/null_audio_sink.cc
@@ -79,6 +79,10 @@ return OutputDeviceInfo(); } +bool NullAudioSink::CurrentThreadIsRenderingThread() { + return task_runner_->BelongsToCurrentThread(); +} + void NullAudioSink::SwitchOutputDevice(const std::string& device_id, const url::Origin& security_origin, const OutputDeviceStatusCB& callback) {
diff --git a/media/audio/null_audio_sink.h b/media/audio/null_audio_sink.h index 6d24fbe..b9c9c80 100644 --- a/media/audio/null_audio_sink.h +++ b/media/audio/null_audio_sink.h
@@ -34,6 +34,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + bool CurrentThreadIsRenderingThread() override; void SwitchOutputDevice(const std::string& device_id, const url::Origin& security_origin, const OutputDeviceStatusCB& callback) override;
diff --git a/media/base/audio_renderer_mixer_input.cc b/media/base/audio_renderer_mixer_input.cc index 921a0174..3d2263f 100644 --- a/media/base/audio_renderer_mixer_input.cc +++ b/media/base/audio_renderer_mixer_input.cc
@@ -122,6 +122,11 @@ device_id_, security_origin_); } +bool AudioRendererMixerInput::CurrentThreadIsRenderingThread() { + NOTIMPLEMENTED(); + return false; +} + void AudioRendererMixerInput::SwitchOutputDevice( const std::string& device_id, const url::Origin& security_origin,
diff --git a/media/base/audio_renderer_mixer_input.h b/media/base/audio_renderer_mixer_input.h index 042fe06..23be849 100644 --- a/media/base/audio_renderer_mixer_input.h +++ b/media/base/audio_renderer_mixer_input.h
@@ -51,6 +51,7 @@ void SwitchOutputDevice(const std::string& device_id, const url::Origin& security_origin, const OutputDeviceStatusCB& callback) override; + bool CurrentThreadIsRenderingThread() override; // Called by AudioRendererMixer when an error occurs. void OnRenderError();
diff --git a/media/base/audio_renderer_sink.h b/media/base/audio_renderer_sink.h index b0b5f26..268b9b6c4 100644 --- a/media/base/audio_renderer_sink.h +++ b/media/base/audio_renderer_sink.h
@@ -70,6 +70,11 @@ // Must never be called on the IO thread. virtual OutputDeviceInfo GetOutputDeviceInfo() = 0; + // If DCHECKs are enabled, this function returns true if called on rendering + // thread, otherwise false. With DCHECKs disabled, it returns true. Thus, it + // is intended to be used for DCHECKing. + virtual bool CurrentThreadIsRenderingThread() = 0; + protected: friend class base::RefCountedThreadSafe<AudioRendererSink>; virtual ~AudioRendererSink() {}
diff --git a/media/base/fake_audio_renderer_sink.cc b/media/base/fake_audio_renderer_sink.cc index 6cc0201..f21eb71c 100644 --- a/media/base/fake_audio_renderer_sink.cc +++ b/media/base/fake_audio_renderer_sink.cc
@@ -69,6 +69,11 @@ return output_device_info_; } +bool FakeAudioRendererSink::CurrentThreadIsRenderingThread() { + NOTIMPLEMENTED(); + return false; +} + bool FakeAudioRendererSink::Render(AudioBus* dest, uint32_t frames_delayed, int* frames_written) {
diff --git a/media/base/fake_audio_renderer_sink.h b/media/base/fake_audio_renderer_sink.h index 3fc95d6b..2a90600b 100644 --- a/media/base/fake_audio_renderer_sink.h +++ b/media/base/fake_audio_renderer_sink.h
@@ -39,6 +39,7 @@ void Play() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; + bool CurrentThreadIsRenderingThread() override; // Attempts to call Render() on the callback provided to // Initialize() with |dest| and |frames_delayed|.
diff --git a/media/base/mock_audio_renderer_sink.h b/media/base/mock_audio_renderer_sink.h index a7185080..68ba2a4 100644 --- a/media/base/mock_audio_renderer_sink.h +++ b/media/base/mock_audio_renderer_sink.h
@@ -29,6 +29,7 @@ MOCK_METHOD0(Pause, void()); MOCK_METHOD0(Play, void()); MOCK_METHOD1(SetVolume, bool(double volume)); + MOCK_METHOD0(CurrentThreadIsRenderingThread, bool()); OutputDeviceInfo GetOutputDeviceInfo();
diff --git a/media/blink/webaudiosourceprovider_impl.cc b/media/blink/webaudiosourceprovider_impl.cc index 6d998e5..e54dbc8 100644 --- a/media/blink/webaudiosourceprovider_impl.cc +++ b/media/blink/webaudiosourceprovider_impl.cc
@@ -163,6 +163,19 @@ bus_wrapper_->Scale(volume_); } +void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params, + RenderCallback* renderer) { + base::AutoLock auto_lock(sink_lock_); + DCHECK_EQ(state_, kStopped); + + tee_filter_->Initialize(renderer, params.channels(), params.sample_rate()); + + sink_->Initialize(params, tee_filter_.get()); + + if (!set_format_cb_.is_null()) + base::ResetAndReturn(&set_format_cb_).Run(); +} + void WebAudioSourceProviderImpl::Start() { base::AutoLock auto_lock(sink_lock_); DCHECK(tee_filter_); @@ -208,6 +221,11 @@ return sink_->GetOutputDeviceInfo(); } +bool WebAudioSourceProviderImpl::CurrentThreadIsRenderingThread() { + NOTIMPLEMENTED(); + return false; +} + void WebAudioSourceProviderImpl::SwitchOutputDevice( const std::string& device_id, const url::Origin& security_origin, @@ -219,19 +237,6 @@ sink_->SwitchOutputDevice(device_id, security_origin, callback); } -void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params, - RenderCallback* renderer) { - base::AutoLock auto_lock(sink_lock_); - DCHECK_EQ(state_, kStopped); - - tee_filter_->Initialize(renderer, params.channels(), params.sample_rate()); - - sink_->Initialize(params, tee_filter_.get()); - - if (!set_format_cb_.is_null()) - base::ResetAndReturn(&set_format_cb_).Run(); -} - void WebAudioSourceProviderImpl::SetCopyAudioCallback( const CopyAudioCB& callback) { DCHECK(!callback.is_null());
diff --git a/media/blink/webaudiosourceprovider_impl.h b/media/blink/webaudiosourceprovider_impl.h index c3844b9e..1ffdd90 100644 --- a/media/blink/webaudiosourceprovider_impl.h +++ b/media/blink/webaudiosourceprovider_impl.h
@@ -56,14 +56,15 @@ size_t number_of_frames) override; // RestartableAudioRendererSink implementation. + void Initialize(const AudioParameters& params, + RenderCallback* renderer) override; void Start() override; void Stop() override; void Play() override; void Pause() override; bool SetVolume(double volume) override; OutputDeviceInfo GetOutputDeviceInfo() override; - void Initialize(const AudioParameters& params, - RenderCallback* renderer) override; + bool CurrentThreadIsRenderingThread() override; void SwitchOutputDevice(const std::string& device_id, const url::Origin& security_origin, const OutputDeviceStatusCB& callback) override;
diff --git a/net/url_request/sdch_dictionary_fetcher.cc b/net/url_request/sdch_dictionary_fetcher.cc index 040e9c2..a3d3565 100644 --- a/net/url_request/sdch_dictionary_fetcher.cc +++ b/net/url_request/sdch_dictionary_fetcher.cc
@@ -308,10 +308,8 @@ // If there's been an error, abort the current request. if (rv != OK) { - current_request_.reset(); - buffer_ = NULL; + ResetRequest(); next_state_ = STATE_SEND_REQUEST; - return OK; } @@ -343,8 +341,7 @@ // An error; abort the current request. if (rv < 0) { - current_request_.reset(); - buffer_ = NULL; + ResetRequest(); next_state_ = STATE_SEND_REQUEST; return OK; }
diff --git a/net/url_request/sdch_dictionary_fetcher_unittest.cc b/net/url_request/sdch_dictionary_fetcher_unittest.cc index 0dc3d1f..02a9987 100644 --- a/net/url_request/sdch_dictionary_fetcher_unittest.cc +++ b/net/url_request/sdch_dictionary_fetcher_unittest.cc
@@ -4,6 +4,7 @@ #include "net/url_request/sdch_dictionary_fetcher.h" +#include <algorithm> #include <string> #include <utility> #include <vector> @@ -13,14 +14,16 @@ #include "base/logging.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "net/base/load_flags.h" +#include "net/base/net_errors.h" #include "net/base/sdch_manager.h" #include "net/http/http_response_headers.h" -#include "net/url_request/url_request_data_job.h" #include "net/url_request/url_request_filter.h" #include "net/url_request/url_request_interceptor.h" +#include "net/url_request/url_request_job.h" #include "net/url_request/url_request_redirect_job.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,7 +36,10 @@ const char kTestDomain1[] = "top.domain.test"; const char kTestDomain2[] = "top2.domain.test"; -class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { +// A URLRequestJob that returns a fixed response body, based on the URL, with +// the specified HttpResponseInfo. Can also be made to return an error after the +// response body has been read. +class URLRequestSpecifiedResponseJob : public URLRequestJob { public: // Called on destruction with load flags used for this request. typedef base::Callback<void(int)> DestructionCallback; @@ -43,13 +49,45 @@ NetworkDelegate* network_delegate, const HttpResponseInfo& response_info_to_return, const DestructionCallback& destruction_callback) - : URLRequestSimpleJob(request, network_delegate), + : URLRequestJob(request, network_delegate), response_info_to_return_(response_info_to_return), last_load_flags_seen_(request->load_flags()), - destruction_callback_(destruction_callback) { + destruction_callback_(destruction_callback), + bytes_read_(0), + final_read_result_(OK), + weak_factory_(this) { DCHECK(!destruction_callback.is_null()); } + ~URLRequestSpecifiedResponseJob() override { + destruction_callback_.Run(last_load_flags_seen_); + } + + // Sets the result of the final read, after the entire body has been read. + // Defaults to OK. + void set_final_read_result(Error final_read_result) { + final_read_result_ = final_read_result; + } + + // URLRequestJob implementation: + void Start() override { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&URLRequestSpecifiedResponseJob::StartAsync, + weak_factory_.GetWeakPtr())); + } + + int ReadRawData(IOBuffer* buf, int buf_size) override { + std::string response = ExpectedResponseForURL(request_->url()); + response = response.substr(bytes_read_); + size_t bytes_to_copy = + std::min(static_cast<size_t>(buf_size), response.size()); + if (bytes_to_copy == 0) + return final_read_result_; + memcpy(buf->data(), response.c_str(), bytes_to_copy); + bytes_read_ += bytes_to_copy; + return bytes_to_copy; + } + static std::string ExpectedResponseForURL(const GURL& url) { return base::StringPrintf("Response for %s\n%s\nEnd Response for %s\n", url.spec().c_str(), @@ -57,30 +95,22 @@ url.spec().c_str()); } - // URLRequestJob void GetResponseInfo(HttpResponseInfo* info) override { *info = response_info_to_return_; } private: - ~URLRequestSpecifiedResponseJob() override { - destruction_callback_.Run(last_load_flags_seen_); - } - - // URLRequestSimpleJob implementation: - int GetData(std::string* mime_type, - std::string* charset, - std::string* data, - const CompletionCallback& callback) const override { - GURL url(request_->url()); - *data = ExpectedResponseForURL(url); - return OK; - } + void StartAsync() { NotifyHeadersComplete(); } const HttpResponseInfo response_info_to_return_; int last_load_flags_seen_; const DestructionCallback destruction_callback_; + int bytes_read_; + Error final_read_result_; + + base::WeakPtrFactory<URLRequestSpecifiedResponseJob> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(URLRequestSpecifiedResponseJob); }; @@ -105,7 +135,9 @@ const base::Closure destruction_callback_; }; -static const char* redirect_signal = "/redirect/"; +const char kRedirectPath[] = "/redirect/"; +const char kBodyErrorPath[] = "/body_error/"; + class SDCHTestRequestInterceptor : public URLRequestInterceptor { public: // A callback to be called whenever a URLRequestJob child of this @@ -137,16 +169,20 @@ lifecycle_callback_.Run(1, 0); std::string path = request->url().path(); - if (path.substr(0, strlen(redirect_signal)) == redirect_signal) { + if (base::StartsWith(path, kRedirectPath, base::CompareCase::SENSITIVE)) { return new TestURLRequestRedirectJob( - request, network_delegate, GURL(path.substr(strlen(redirect_signal))), + request, network_delegate, GURL(path.substr(strlen(kRedirectPath))), URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "testing", base::Bind(lifecycle_callback_, -1, 0)); } - return new URLRequestSpecifiedResponseJob( - request, network_delegate, *http_response_info_, - base::Bind(lifecycle_callback_, -1)); + std::unique_ptr<URLRequestSpecifiedResponseJob> job( + new URLRequestSpecifiedResponseJob( + request, network_delegate, *http_response_info_, + base::Bind(lifecycle_callback_, -1))); + if (base::StartsWith(path, kBodyErrorPath, base::CompareCase::SENSITIVE)) + job->set_final_read_result(net::ERR_FAILED); + return job.release(); } // The caller must ensure that both |*http_response_info| and the @@ -518,6 +554,26 @@ EXPECT_FALSE(last_load_flags_seen() & LOAD_ONLY_FROM_CACHE); } +// Check the case of two requests for different URLs, where the first request +// fails after receiving body data. +TEST_F(SdchDictionaryFetcherTest, TwoDictionariesFirstFails) { + GURL dictionary_with_error_url(PathToGurl("body_error/")); + GURL dictionary_url(PathToGurl("dictionary")); + EXPECT_TRUE( + fetcher()->Schedule(dictionary_with_error_url, GetDefaultCallback())); + EXPECT_TRUE(fetcher()->Schedule(dictionary_url, GetDefaultCallback())); + WaitForNoJobs(); + + EXPECT_EQ(2, jobs_requested()); + std::vector<DictionaryAdditions> additions; + GetDictionaryAdditions(&additions); + // Should only have a dictionary for the successful request. + ASSERT_EQ(1u, additions.size()); + EXPECT_EQ( + URLRequestSpecifiedResponseJob::ExpectedResponseForURL(dictionary_url), + additions[0].dictionary_text); +} + } // namespace } // namespace net
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn index 89eaaed..60bb499a 100644 --- a/sandbox/win/BUILD.gn +++ b/sandbox/win/BUILD.gn
@@ -205,11 +205,14 @@ "tests/common/test_utils.cc", "tests/common/test_utils.h", "tests/integration_tests/integration_tests.cc", + "tests/integration_tests/integration_tests_common.h", "tests/integration_tests/integration_tests_test.cc", ] deps = [ ":sandbox", + ":sbox_integration_test_hook_dll", + ":sbox_integration_test_win_proc", "//base/test:test_support", "//testing/gtest", ] @@ -217,6 +220,23 @@ libs = [ "dxva2.lib" ] } +loadable_module("sbox_integration_test_hook_dll") { + sources = [ + "tests/integration_tests/hooking_dll.cc", + "tests/integration_tests/integration_tests_common.h", + ] +} + +executable("sbox_integration_test_win_proc") { + sources = [ + "tests/integration_tests/hooking_win_proc.cc", + "tests/integration_tests/integration_tests_common.h", + ] + + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] +} + test("sbox_validation_tests") { sources = [ "tests/common/controller.cc",
diff --git a/sandbox/win/sandbox_win.gypi b/sandbox/win/sandbox_win.gypi index 8ac9e59..e9673aa9 100644 --- a/sandbox/win/sandbox_win.gypi +++ b/sandbox/win/sandbox_win.gypi
@@ -197,6 +197,8 @@ 'type': 'executable', 'dependencies': [ 'sandbox', + 'sbox_integration_test_hook_dll', + 'sbox_integration_test_win_proc', '../base/base.gyp:test_support_base', '../testing/gtest.gyp:gtest', ], @@ -224,6 +226,7 @@ 'tests/common/test_utils.cc', 'tests/common/test_utils.h', 'tests/integration_tests/integration_tests.cc', + 'tests/integration_tests/integration_tests_common.h', ], 'link_settings': { 'libraries': [ @@ -232,6 +235,31 @@ }, }, { + 'target_name': 'sbox_integration_test_hook_dll', + 'type': 'shared_library', + 'dependencies': [ + ], + 'sources': [ + 'tests/integration_tests/hooking_dll.cc', + 'tests/integration_tests/integration_tests_common.h', + ], + }, + { + 'target_name': 'sbox_integration_test_win_proc', + 'type': 'executable', + 'dependencies': [ + ], + 'sources': [ + 'tests/integration_tests/hooking_win_proc.cc', + 'tests/integration_tests/integration_tests_common.h', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS + }, + }, + }, + { 'target_name': 'sbox_validation_tests', 'type': 'executable', 'dependencies': [
diff --git a/sandbox/win/src/process_mitigations.cc b/sandbox/win/src/process_mitigations.cc index adcc17c9..1fa5209 100644 --- a/sandbox/win/src/process_mitigations.cc +++ b/sandbox/win/src/process_mitigations.cc
@@ -137,8 +137,8 @@ } } - // Enable dll extension policies. - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { + // Enable extension point policies. + if (flags & MITIGATION_EXTENSION_POINT_DISABLE) { PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; policy.DisableExtensionPoints = true; @@ -254,7 +254,7 @@ PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; } - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { + if (flags & MITIGATION_EXTENSION_POINT_DISABLE) { *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; } @@ -333,7 +333,7 @@ MITIGATION_RELOCATE_IMAGE_REQUIRED | MITIGATION_BOTTOM_UP_ASLR | MITIGATION_STRICT_HANDLE_CHECKS | - MITIGATION_EXTENSION_DLL_DISABLE | + MITIGATION_EXTENSION_POINT_DISABLE | MITIGATION_DLL_SEARCH_ORDER | MITIGATION_HARDEN_TOKEN_IL_POLICY | MITIGATION_WIN32K_DISABLE |
diff --git a/sandbox/win/src/process_mitigations_test.cc b/sandbox/win/src/process_mitigations_test.cc index 97636bcd..bf89a9a 100644 --- a/sandbox/win/src/process_mitigations_test.cc +++ b/sandbox/win/src/process_mitigations_test.cc
@@ -1,36 +1,48 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2011 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 <initguid.h> +#include "sandbox/win/src/process_mitigations.h" + #include <d3d9.h> -#include <Opmapi.h> +#include <initguid.h> +#include <opmapi.h> +#include <psapi.h> #include <windows.h> #include <map> #include <string> +#include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "base/process/launch.h" +#include "base/scoped_native_library.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_timeouts.h" +#include "base/win/registry.h" #include "base/win/scoped_handle.h" +#include "base/win/startup_information.h" +#include "base/win/win_util.h" #include "base/win/windows_version.h" #include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/process_mitigations.h" #include "sandbox/win/src/process_mitigations_win32k_policy.h" #include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/target_services.h" -#include "sandbox/win/src/win_utils.h" #include "sandbox/win/tests/common/controller.h" +#include "sandbox/win/tests/integration_tests/integration_tests_common.h" #include "testing/gtest/include/gtest/gtest.h" namespace { +// Timeouts for synchronization. +#define event_timeout \ + static_cast<DWORD>((TestTimeouts::action_timeout()).InMillisecondsRoundedUp()) + // API defined in winbase.h. typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; @@ -43,6 +55,10 @@ typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; +// APIs defined in integration_tests_common.h +typedef decltype(WasHookCalled)* WasHookCalledFunction; +typedef decltype(SetHook)* SetHookFunction; + #if !defined(_WIN64) bool CheckWin8DepPolicy() { PROCESS_MITIGATION_DEP_POLICY policy = {}; @@ -59,7 +75,7 @@ PROCESS_MITIGATION_ASLR_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, &policy, sizeof(policy))) { - return false; + return false; } return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; } @@ -68,9 +84,9 @@ bool CheckWin8StrictHandlePolicy() { PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessStrictHandleCheckPolicy, - &policy, sizeof(policy))) { - return false; + ProcessStrictHandleCheckPolicy, &policy, + sizeof(policy))) { + return false; } return policy.RaiseExceptionOnInvalidHandleReference && policy.HandleExceptionsPermanentlyEnabled; @@ -79,19 +95,19 @@ bool CheckWin8Win32CallPolicy() { PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessSystemCallDisablePolicy, - &policy, sizeof(policy))) { - return false; + ProcessSystemCallDisablePolicy, &policy, + sizeof(policy))) { + return false; } return policy.DisallowWin32kSystemCalls; } -bool CheckWin8DllExtensionPolicy() { +bool CheckWin8ExtensionPointPolicy() { PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessExtensionPointDisablePolicy, &policy, sizeof(policy))) { - return false; + return false; } return policy.DisableExtensionPoints; } @@ -116,8 +132,309 @@ return policy.NoRemoteImages; } +// Spawn Windows process (with or without mitigation enabled). +bool SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) { + base::win::StartupInformation startup_info; + DWORD creation_flags = 0; + + if (!success_test) { + DWORD64 flags = + PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; + // This test only runs on >= Win8, so don't have to handle + // illegal 64-bit flags on 32-bit <= Win7. + size_t flags_size = sizeof(flags); + + if (!startup_info.InitializeProcThreadAttributeList(1) || + !startup_info.UpdateProcThreadAttribute( + PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)) { + ADD_FAILURE(); + return false; + } + creation_flags = EXTENDED_STARTUPINFO_PRESENT; + } + + // Command line must be writable. + base::string16 cmd_writeable(g_winproc_file); + + if (!::CreateProcessW(NULL, &cmd_writeable[0], NULL, NULL, FALSE, + creation_flags, NULL, NULL, startup_info.startup_info(), + pi)) { + ADD_FAILURE(); + return false; + } + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_timeout)); + + return true; +} + +//------------------------------------------------------------------------------ +// 1. Spawn a Windows process (with or without mitigation enabled). +// 2. Load the hook Dll locally. +// 3. Create a global named event for the hook to trigger. +// 4. Start the hook (for the specific WinProc or globally). +// 5. Send a keystroke event. +// 6. Ask the hook Dll if it received a hook callback. +// 7. Cleanup the hooking. +// 8. Signal the Windows process to shutdown. +// +// Do NOT use any ASSERTs in this function. Cleanup required. +//------------------------------------------------------------------------------ +void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) { + // Set up a couple global events that this test will use. + HANDLE winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); + if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + return; + } + base::win::ScopedHandle scoped_winproc_event(winproc_event); + + HANDLE hook_event = ::CreateEventW(NULL, FALSE, FALSE, g_hook_event); + if (hook_event == NULL || hook_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + return; + } + base::win::ScopedHandle scoped_hook_event(hook_event); + + // 1. Spawn WinProc. + PROCESS_INFORMATION proc_info = {}; + if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) + return; + + // From this point on, no return on failure. Cleanup required. + bool all_good = true; + + // 2. Load the hook DLL. + base::FilePath hook_dll_path(g_hook_dll_file); + base::ScopedNativeLibrary dll(hook_dll_path); + EXPECT_TRUE(dll.is_valid()); + + HOOKPROC hook_proc = + reinterpret_cast<HOOKPROC>(dll.GetFunctionPointer(g_hook_handler_func)); + WasHookCalledFunction was_hook_called = + reinterpret_cast<WasHookCalledFunction>( + dll.GetFunctionPointer(g_was_hook_called_func)); + SetHookFunction set_hook = reinterpret_cast<SetHookFunction>( + dll.GetFunctionPointer(g_set_hook_func)); + if (!hook_proc || !was_hook_called || !set_hook) { + ADD_FAILURE(); + all_good = false; + } + + // 3. Try installing the hook (either on a remote target thread, + // or globally). + HHOOK hook = nullptr; + if (all_good) { + DWORD target = 0; + if (!global_hook) + target = proc_info.dwThreadId; + hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll.get(), target); + if (!hook) { + ADD_FAILURE(); + all_good = false; + } else + // Pass the hook DLL the hook handle. + set_hook(hook); + } + + // 4. Inject a keyboard event. + if (all_good) { + // Note: that PostThreadMessage and SendMessage APIs will not deliver + // a keystroke in such a way that triggers a "legitimate" hook. + // Have to use targetless SendInput or keybd_event. The latter is + // less code and easier to work with. + keybd_event(VkKeyScan(L'A'), 0, 0, 0); + keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0); + // Give it a chance to hit the hook handler... + ::WaitForSingleObject(hook_event, event_timeout); + + // 5. Did the hook get hit? Was it expected to? + if (global_hook) + EXPECT_EQ((is_success_test ? true : false), was_hook_called()); + else + // ***IMPORTANT: when targeting a specific thread id, the + // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE + // mitigation does NOT disable the hook API. It ONLY + // stops global hooks from running in a process. Hence, + // the hook will hit (TRUE) even in the "failure" + // case for a non-global/targeted hook. + EXPECT_EQ((is_success_test ? true : true), was_hook_called()); + } + + // 6. Disable hook. + if (hook) + EXPECT_TRUE(::UnhookWindowsHookEx(hook)); + + // 7. Trigger shutdown of WinProc. + if (proc_info.hProcess) { + if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { + // Note: The combination/perfect-storm of a Global Hook, in a + // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the + // use of the SendInput or keybd_event API to inject a keystroke, + // results in the target becoming unresponsive. If any one of these + // states are changed, the problem does not occur. This means the WM_QUIT + // message is not handled and the call to WaitForSingleObject times out. + // Therefore not checking the return val. + ::WaitForSingleObject(winproc_event, event_timeout); + } else { + // Ensure no strays. + ::TerminateProcess(proc_info.hProcess, 0); + ADD_FAILURE(); + } + EXPECT_TRUE(::CloseHandle(proc_info.hThread)); + EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); + } +} + +//------------------------------------------------------------------------------ +// 1. Set up the AppInit Dll in registry settings. (Enable) +// 2. Spawn a Windows process (with or without mitigation enabled). +// 3. Check if the AppInit Dll got loaded in the Windows process or not. +// 4. Signal the Windows process to shutdown. +// 5. Restore original reg settings. +// +// Do NOT use any ASSERTs in this function. Cleanup required. +//------------------------------------------------------------------------------ +void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) { + // 0.5 Get path of current module. The appropriate build of the + // AppInit DLL will be in the same directory (and the + // full path is needed for reg). + wchar_t path[MAX_PATH]; + if (!::GetModuleFileNameW(NULL, path, MAX_PATH)) { + ADD_FAILURE(); + return; + } + // Only want the directory. Switch file name for the AppInit DLL. + base::FilePath full_dll_path(path); + full_dll_path = full_dll_path.DirName(); + full_dll_path = full_dll_path.Append(g_hook_dll_file); + wchar_t* non_const = const_cast<wchar_t*>(full_dll_path.value().c_str()); + // Now make sure the path is in "short-name" form for registry. + DWORD length = ::GetShortPathNameW(non_const, NULL, 0); + std::vector<wchar_t> short_name(length); + if (!::GetShortPathNameW(non_const, &short_name[0], length)) { + ADD_FAILURE(); + return; + } + + // 1. Reg setup. + const wchar_t* app_init_reg_path = + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; + const wchar_t* dlls_value_name = L"AppInit_DLLs"; + const wchar_t* enabled_value_name = L"LoadAppInit_DLLs"; + const wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs"; + std::wstring orig_dlls; + std::wstring new_dlls; + DWORD orig_enabled_value = 0; + DWORD orig_signing_value = 0; + base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path, + KEY_QUERY_VALUE | KEY_SET_VALUE); + // Backup the existing settings. + if (!app_init_key.Valid() || !app_init_key.HasValue(dlls_value_name) || + !app_init_key.HasValue(enabled_value_name) || + ERROR_SUCCESS != app_init_key.ReadValue(dlls_value_name, &orig_dlls) || + ERROR_SUCCESS != + app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)) { + ADD_FAILURE(); + return; + } + if (app_init_key.HasValue(signing_value_name)) { + if (ERROR_SUCCESS != + app_init_key.ReadValueDW(signing_value_name, &orig_signing_value)) { + ADD_FAILURE(); + return; + } + } + + // Set the new settings (obviously requires local admin privileges). + new_dlls = orig_dlls; + if (!orig_dlls.empty()) + new_dlls.append(L","); + new_dlls.append(short_name.data()); + + // From this point on, no return on failure. Cleanup required. + bool all_good = true; + + if (app_init_key.HasValue(signing_value_name)) { + if (ERROR_SUCCESS != + app_init_key.WriteValue(signing_value_name, static_cast<DWORD>(0))) { + ADD_FAILURE(); + all_good = false; + } + } + if (ERROR_SUCCESS != + app_init_key.WriteValue(dlls_value_name, new_dlls.c_str()) || + ERROR_SUCCESS != + app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))) { + ADD_FAILURE(); + all_good = false; + } + + // 2. Spawn WinProc. + HANDLE winproc_event = INVALID_HANDLE_VALUE; + base::win::ScopedHandle scoped_event; + PROCESS_INFORMATION proc_info = {}; + if (all_good) { + winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); + if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + all_good = false; + } else { + scoped_event.Set(winproc_event); + if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) + all_good = false; + } + } + + // 3. Check loaded modules in WinProc to see if the AppInit dll is loaded. + bool dll_loaded = false; + if (all_good) { + std::vector<HMODULE>(modules); + if (!base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)) { + ADD_FAILURE(); + all_good = false; + } else { + for (auto module : modules) { + wchar_t name[MAX_PATH] = {}; + if (::GetModuleFileNameExW(proc_info.hProcess, module, name, + MAX_PATH) && + ::wcsstr(name, g_hook_dll_file)) { + // Found it. + dll_loaded = true; + break; + } + } + } + } + + // Was the test result as expected? + if (all_good) + EXPECT_EQ((is_success_test ? true : false), dll_loaded); + + // 4. Trigger shutdown of WinProc. + if (proc_info.hProcess) { + if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { + ::WaitForSingleObject(winproc_event, event_timeout); + } else { + // Ensure no strays. + ::TerminateProcess(proc_info.hProcess, 0); + ADD_FAILURE(); + } + EXPECT_TRUE(::CloseHandle(proc_info.hThread)); + EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); + } + + // 5. Reg Restore + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(enabled_value_name, orig_enabled_value)); + if (app_init_key.HasValue(signing_value_name)) + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(signing_value_name, orig_signing_value)); + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str())); +} + void TestWin10ImageLoadRemote(bool is_success_test) { - // ***Insert your manual testing share UNC path here! + // ***Insert a manual testing share UNC path here! // E.g.: \\\\hostname\\sharename\\calc.exe std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; @@ -526,17 +843,15 @@ //------------------------------------------------------------------------------ // Win8 Checks: // MITIGATION_DEP(_NO_ATL_THUNK) -// MITIGATION_EXTENSION_DLL_DISABLE // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only // MITIGATION_STRICT_HANDLE_CHECKS // >= Win8 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t** argv) { get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); + reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); if (!get_process_mitigation_policy) return SBOX_TEST_NOT_FOUND; @@ -553,9 +868,6 @@ if (!CheckWin8StrictHandlePolicy()) return SBOX_TEST_THIRD_ERROR; - if (!CheckWin8DllExtensionPolicy()) - return SBOX_TEST_FIFTH_ERROR; - return SBOX_TEST_SUCCEEDED; } @@ -566,12 +878,10 @@ TestRunner runner; sandbox::TargetPolicy* policy = runner.GetPolicy(); - sandbox::MitigationFlags mitigations = MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_EXTENSION_DLL_DISABLE; + sandbox::MitigationFlags mitigations = + MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK; #if defined(NDEBUG) // ASLR cannot be forced in debug builds. - mitigations |= MITIGATION_RELOCATE_IMAGE | - MITIGATION_RELOCATE_IMAGE_REQUIRED; + mitigations |= MITIGATION_RELOCATE_IMAGE | MITIGATION_RELOCATE_IMAGE_REQUIRED; #endif EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); @@ -588,17 +898,16 @@ // < Win8 x86 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t** argv) { GetProcessDEPPolicyFunction get_process_dep_policy = - reinterpret_cast<GetProcessDEPPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessDEPPolicy")); + reinterpret_cast<GetProcessDEPPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy")); if (get_process_dep_policy) { BOOL is_permanent = FALSE; DWORD dep_flags = 0; if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, - &is_permanent)) { + &is_permanent)) { return SBOX_TEST_FIRST_ERROR; } @@ -608,7 +917,7 @@ } else { NtQueryInformationProcessFunction query_information_process = NULL; ResolveNTFunctionPtr("NtQueryInformationProcess", - &query_information_process); + &query_information_process); if (!query_information_process) return SBOX_TEST_NOT_FOUND; @@ -624,8 +933,8 @@ static const int MEM_EXECUTE_OPTION_PERMANENT = 8; dep_flags &= 0xff; - if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | - MEM_EXECUTE_OPTION_PERMANENT)) { + if (dep_flags != + (MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT)) { return SBOX_TEST_FOURTH_ERROR; } } @@ -641,10 +950,9 @@ TestRunner runner; sandbox::TargetPolicy* policy = runner.GetPolicy(); - EXPECT_EQ(policy->SetProcessMitigations( - MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_SEHOP), + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_DEP | + MITIGATION_DEP_NO_ATL_THUNK | + MITIGATION_SEHOP), SBOX_ALL_OK); EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); } @@ -655,11 +963,10 @@ // >= Win8 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t** argv) { get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); + reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); if (!get_process_mitigation_policy) return SBOX_TEST_NOT_FOUND; @@ -1029,6 +1336,158 @@ } //------------------------------------------------------------------------------ +// Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE). +// >= Win8 +//------------------------------------------------------------------------------ +SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(int argc, + wchar_t** argv) { + get_process_mitigation_policy = + reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); + if (!get_process_mitigation_policy) + return SBOX_TEST_NOT_FOUND; + + if (!CheckWin8ExtensionPointPolicy()) + return SBOX_TEST_FIRST_ERROR; + return SBOX_TEST_SUCCEEDED; +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation enables the setting on a process. +TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + TestRunner runner; + sandbox::TargetPolicy* policy = runner.GetPolicy(); + + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE), + SBOX_ALL_OK); + EXPECT_EQ(SBOX_TEST_SUCCEEDED, + runner.RunTest(L"CheckWin8ExtensionPointSetting")); +} + +// This test validates that a "legitimate" global hook CAN be set on the +// sandboxed proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation is not set. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, + DISABLED_CheckWin8ExtensionPoint_GlobalHook_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(true, true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation prevents a global hook on WinProc. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, + DISABLED_CheckWin8ExtensionPoint_GlobalHook_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(false, true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that a "legitimate" hook CAN be set on the sandboxed +// proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(true, false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent +// hooks targetted at a specific thread id. It only prevents +// global hooks. So this test does NOT actually expect the hook +// to fail (see TestWin8ExtensionPointHookWrapper function) even +// with the mitigation on. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(false, false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that an AppInit Dll CAN be added to a target +// WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. +// +// MANUAL testing only. +// Must run this test as admin/elevated. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + TestWin8ExtensionPointAppInitWrapper(true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation prevents the loading of any AppInit Dll into WinProc. +// +// MANUAL testing only. +// Must run this test as admin/elevated. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + TestWin8ExtensionPointAppInitWrapper(false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +//------------------------------------------------------------------------------ // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) // >= Win10 //------------------------------------------------------------------------------ @@ -1193,7 +1652,7 @@ // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE // mitigation is NOT set. // -// DISABLED for automated testing bots. Enable for manual testing. +// MANUAL testing only. TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) return; @@ -1205,7 +1664,7 @@ // mitigation prevents creating a new process from a remote // UNC device. // -// DISABLED for automated testing bots. Enable for manual testing. +// MANUAL testing only. TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) return;
diff --git a/sandbox/win/src/security_level.h b/sandbox/win/src/security_level.h index 87abdebad..d8524c1 100644 --- a/sandbox/win/src/security_level.h +++ b/sandbox/win/src/security_level.h
@@ -187,10 +187,14 @@ // PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON. const MitigationFlags MITIGATION_WIN32K_DISABLE = 0x00000200; -// Disables common DLL injection methods (e.g. window hooks and -// App_InitDLLs). Corresponds to +// Prevents certain built-in third party extension points from being used. +// - App_Init DLLs +// - Winsock Layered Service Providers (LSPs) +// - Global Windows Hooks (NOT thread-targeted hooks) +// - Legacy Input Method Editors (IMEs). +// I.e.: Disable legacy hooking mechanisms. Corresponds to // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON. -const MitigationFlags MITIGATION_EXTENSION_DLL_DISABLE = 0x00000400; +const MitigationFlags MITIGATION_EXTENSION_POINT_DISABLE = 0x00000400; // Prevents the process from loading non-system fonts into GDI. // Corresponds to
diff --git a/sandbox/win/tests/integration_tests/hooking_dll.cc b/sandbox/win/tests/integration_tests/hooking_dll.cc new file mode 100644 index 0000000..f275ae6 --- /dev/null +++ b/sandbox/win/tests/integration_tests/hooking_dll.cc
@@ -0,0 +1,64 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdio.h> +#include <windows.h> + +#define _DLL_EXPORTING +#include "integration_tests_common.h" + +// This data section creates a common area that is accessible +// to all instances of the DLL (in every process). They map to +// the same physical memory location. +// **Note that each instance of this DLL runs in the context of +// the process it's injected into, so things like pointers and +// addresses won't work. +// **Note that any variables must be initialized to put them in +// the specified segment, otherwise they will end up in the +// default data segment. +#pragma data_seg(".hook") +HHOOK hook = NULL; +bool hook_called = false; +#pragma data_seg() +#pragma comment(linker, "/SECTION:.hook,RWS") + +namespace { + +HANDLE event = NULL; +} + +void SetHook(HHOOK hook_handle) { + hook = hook_handle; + + return; +} + +bool WasHookCalled() { + return hook_called; +} + +LRESULT HookProc(int code, WPARAM w_param, LPARAM l_param) { + hook_called = true; + if (event) + ::SetEvent(event); + + // Recent versions of Windows do not require the HHOOK to be passed along, + // but I'm doing it here to show the shared use of the HHOOK variable in + // the shared data segment. It is set by the instance of the DLL in the + // main test process. + return CallNextHookEx(hook, code, w_param, l_param); +} + +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { + if (reason == DLL_PROCESS_ATTACH) { + // The testing process should have set up this named event already + // (if the test needs this event to be signaled). + event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE, g_hook_event); + } + + if (reason == DLL_PROCESS_DETACH) + ::CloseHandle(event); + + return TRUE; +}
diff --git a/sandbox/win/tests/integration_tests/hooking_win_proc.cc b/sandbox/win/tests/integration_tests/hooking_win_proc.cc new file mode 100644 index 0000000..3c6770abff --- /dev/null +++ b/sandbox/win/tests/integration_tests/hooking_win_proc.cc
@@ -0,0 +1,87 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "integration_tests_common.h" + +#include <windows.h> + +LRESULT CALLBACK WndProc(HWND window, + UINT message, + WPARAM w_param, + LPARAM l_param) { + // Injected keystroke via PostThreadMessage won't be dispatched to here. + // Have to use SendMessage or SendInput to trigger the keyboard hook. + switch (message) { + case WM_KEYDOWN: + break; + case WM_KEYUP: + break; + case WM_CLOSE: + ::DestroyWindow(window); + break; + case WM_DESTROY: + ::PostQuitMessage(0); + break; + default: + return ::DefWindowProc(window, message, w_param, l_param); + } + return 0; +} + +int WINAPI WinMain(HINSTANCE instance, + HINSTANCE prev_instance, + LPSTR cmd_line, + int cmd_show) { + // The parent process should have set up this named event already. + HANDLE event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE, g_winproc_event); + if (event == NULL || event == INVALID_HANDLE_VALUE) + return 1; + + // Step 1: Registering the Window Class. + WNDCLASSEX window_class; + window_class.cbSize = sizeof(WNDCLASSEX); + window_class.style = 0; + window_class.lpfnWndProc = WndProc; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = instance; + window_class.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); + window_class.hCursor = ::LoadCursor(NULL, IDC_ARROW); + window_class.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOWFRAME); + window_class.lpszMenuName = NULL; + window_class.lpszClassName = g_winproc_class_name; + window_class.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION); + + if (!::RegisterClassEx(&window_class)) + return 1; + + // Step 2: Create the Window. + HWND window = ::CreateWindowExW(WS_EX_CLIENTEDGE, g_winproc_class_name, + g_winproc_window_name, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, + NULL, instance, NULL); + + if (window == NULL) + return 1; + + ::ShowWindow(window, cmd_show); + ::UpdateWindow(window); + + // Step 3: Signal that WinProc is up and running. + ::SetEvent(event); + + // Step 4: The Message Loop + // WM_QUIT results in a 0 value from GetMessageW, + // breaking the loop. + MSG message; + while (::GetMessageW(&message, NULL, 0, 0) > 0) { + ::TranslateMessage(&message); + ::DispatchMessageW(&message); + } + + ::SetEvent(event); + ::CloseHandle(event); + + return message.wParam; +}
diff --git a/sandbox/win/tests/integration_tests/integration_tests_common.h b/sandbox/win/tests/integration_tests/integration_tests_common.h new file mode 100644 index 0000000..841e6e4b --- /dev/null +++ b/sandbox/win/tests/integration_tests/integration_tests_common.h
@@ -0,0 +1,43 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SANDBOX_TESTS_INTEGRATION_TESTS_COMMON_H_ +#define SANDBOX_TESTS_INTEGRATION_TESTS_COMMON_H_ + +#include <windows.h> + +// Use the same header file for DLL and importers. +#ifdef _DLL_EXPORTING +#define DECLSPEC extern "C" __declspec(dllexport) +#else +#define DECLSPEC extern "C" __declspec(dllimport) +#endif + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ +const wchar_t* g_extension_point_test_mutex = L"ChromeExtensionTestMutex"; + +//------------------------------------------------------------------------------ +// Hooking WinProc exe. +//------------------------------------------------------------------------------ +const wchar_t* g_winproc_file = L"sbox_integration_test_win_proc.exe "; +const wchar_t* g_winproc_class_name = L"myWindowClass"; +const wchar_t* g_winproc_window_name = L"ChromeMitigationTests"; +const wchar_t* g_winproc_event = L"ChromeExtensionTestEvent"; + +//------------------------------------------------------------------------------ +// Hooking dll. +//------------------------------------------------------------------------------ +const wchar_t* g_hook_dll_file = L"sbox_integration_test_hook_dll.dll"; +const wchar_t* g_hook_event = L"ChromeExtensionTestHookEvent"; +const char* g_hook_handler_func = "HookProc"; +const char* g_was_hook_called_func = "WasHookCalled"; +const char* g_set_hook_func = "SetHook"; + +DECLSPEC LRESULT HookProc(int code, WPARAM wParam, LPARAM lParam); +DECLSPEC bool WasHookCalled(); +DECLSPEC void SetHook(HHOOK hook_handle); + +#endif // SANDBOX_TESTS_INTEGRATION_TESTS_COMMON_H_
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process index 99e2076..a8e09d2 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process +++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -4,9 +4,6 @@ # https://crbug.com/611838 - regression when geolocation tests use JS mock. http/tests/security/powerfulFeatureRestrictions/geolocation-on-secure-origin-in-insecure-origin.html [ Timeout ] -# https://crbug.com/344348 - No POST data support in FrameHostMsg_OpenURL. -http/tests/navigation/form-targets-cross-site-frame-post.html [ Failure ] - # https://crbug.com/611154 - DCHECK in NavigatorImpl::DidStartProvisionalLoad. http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ] http/tests/security/upgrade-insecure-requests/iframe-upgrade-csp.https.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations index c9488b6..0638d28f 100644 --- a/third_party/WebKit/LayoutTests/LeakExpectations +++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -36,8 +36,6 @@ crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html [ Leak ] crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/scrollstate-distribute-to-scroll-chain-descendant.html [ Leak ] -crbug.com/616775 http/tests/inspector-enabled/dedicated-workers-list.html [ Crash ] - # ----------------------------------------------------------------- # Untriaged but known real leaks. # -----------------------------------------------------------------
diff --git a/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-at-unique-origin-denied.php b/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-at-unique-origin-denied.php index 629b65f..413ece6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-at-unique-origin-denied.php +++ b/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-at-unique-origin-denied.php
@@ -4,17 +4,37 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script> +var orginURL = document.URL; test(function () { assert_throws('SecurityError', function () { - history.pushState(null, null, document.URL + "/path"); + history.pushState(null, null, orginURL + "/path"); }); }, 'pushState to a new path in unique origin should fail with SecurityError'); + test(function () { try { - history.pushState(null, null, document.URL + "#hash"); + history.pushState(null, null, orginURL + "#hash"); done(); } catch (e) { - assert_unreached("pushState to a new hash should not fail."); + assert_unreached("pushState #hash should not fail."); } -}, 'pushState to new hash in unique origin should not fail with SecurityError'); +}, 'pushState #hash in unique origin should not fail with SecurityError'); + +test(function () { + try { + history.pushState(null, null, orginURL + "?hash"); + done(); + } catch (e) { + assert_unreached("pushState ?hash should not fail."); + } +}, 'pushState ?hash in unique origin should not fail with SecurityError'); + +test(function () { + try { + history.pushState(null, null, orginURL + "?hash#base"); + done(); + } catch (e) { + assert_unreached("pushState ?hash#base should not fail."); + } +}, 'pushState ?hash#base in unique origin should not fail with SecurityError'); </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-whitelisted-at-unique-origin-denied.php b/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-whitelisted-at-unique-origin-denied.php index 612162a..164d9f6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-whitelisted-at-unique-origin-denied.php +++ b/third_party/WebKit/LayoutTests/http/tests/navigation/pushstate-whitelisted-at-unique-origin-denied.php
@@ -4,22 +4,41 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script> +var orginURL = document.URL; test(function () { testRunner.addOriginAccessWhitelistEntry(location.origin, location.protocol, '', false); }, 'testRunner.addOriginAccessWhitelistEntry is required for this test'); test(function () { assert_throws('SecurityError', function () { - history.pushState(null, null, document.URL + "/path"); + history.pushState(null, null, orginURL + "/path"); }); }, 'pushState at unique origin should fail with SecurityError (even with whitelisted origins)'); test(function () { try { - history.pushState(null, null, document.URL + "#hash"); + history.pushState(null, null, orginURL + "#hash"); done(); } catch (e) { - assert_unreached("pushState to a new hash should not fail."); + assert_unreached("pushState #hash should not fail."); } -}, 'pushState to new hash in unique origin should not fail with SecurityError'); +}, 'pushState #hash in unique origin should not fail with SecurityError'); + +test(function () { + try { + history.pushState(null, null, orginURL + "?hash"); + done(); + } catch (e) { + assert_unreached("pushState ?hash should not fail."); + } +}, 'pushState ?hash in unique origin should not fail with SecurityError'); + +test(function () { + try { + history.pushState(null, null, orginURL + "?hash#base"); + done(); + } catch (e) { + assert_unreached("pushState ?hash#base should not fail."); + } +}, 'pushState ?hash#base in unique origin should not fail with SecurityError'); </script>
diff --git a/third_party/WebKit/LayoutTests/payments/promises-keep-request-alive.html b/third_party/WebKit/LayoutTests/payments/promises-keep-request-alive.html index db250f3..80187b5 100644 --- a/third_party/WebKit/LayoutTests/payments/promises-keep-request-alive.html +++ b/third_party/WebKit/LayoutTests/payments/promises-keep-request-alive.html
@@ -30,7 +30,7 @@ return result; }) .then(response => { - completeResult = response.complete(true); + completeResult = response.complete("success"); // Return before calling gc() to make sure reference to response // is gone. })
diff --git a/third_party/WebKit/Source/core/frame/History.cpp b/third_party/WebKit/Source/core/frame/History.cpp index 393394f..dc78024 100644 --- a/third_party/WebKit/Source/core/frame/History.cpp +++ b/third_party/WebKit/Source/core/frame/History.cpp
@@ -59,6 +59,23 @@ return true; } +bool equalIgnoringQueryAndFragment(const KURL& a, const KURL& b) +{ + int aLength = a.pathEnd(); + int bLength = b.pathEnd(); + + if (aLength != bLength) + return false; + + const String& aString = a.getString(); + const String& bString = b.getString(); + for (int i = 0; i < aLength; ++i) { + if (aString[i] != bString[i]) + return false; + } + return true; +} + } // namespace History::History(LocalFrame* frame) @@ -196,7 +213,7 @@ // 'pushState'/'replaceState' to modify the URL fragment: see // https://crbug.com/528681 for the compatibility concerns. if (documentOrigin->isUnique() || documentOrigin->isLocal()) - return equalIgnoringFragmentIdentifier(url, documentURL); + return equalIgnoringQueryAndFragment(url, documentURL); if (!equalIgnoringPathQueryAndFragment(url, documentURL)) return false;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp index 8ba59de..f33a86d9 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp
@@ -153,11 +153,12 @@ SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); + m_isLayoutSizeChanged = selfNeedsLayout() || (svg->hasRelativeLengths() && oldSize != size()); // When hasRelativeLengths() is false, no descendants have relative lengths // (hence no one is interested in viewport size changes). - m_isLayoutSizeChanged = svg->hasRelativeLengths() && (selfNeedsLayout() || oldSize != size()); + bool layoutSizeChanged = m_isLayoutSizeChanged && svg->hasRelativeLengths(); - SVGLayoutSupport::layoutChildren(firstChild(), false, m_didScreenScaleFactorChange, m_isLayoutSizeChanged); + SVGLayoutSupport::layoutChildren(firstChild(), false, m_didScreenScaleFactorChange, layoutSizeChanged); if (m_needsBoundariesOrTransformUpdate) { updateCachedBoundaries();
diff --git a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp index 5f04775..0c7ae4e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
@@ -61,30 +61,6 @@ WorkerBackingThread::~WorkerBackingThread() { -#if DCHECK_IS_ON() - MutexLocker locker(m_mutex); - DCHECK_EQ(0u, m_workerScriptCount); -#endif -} - -void WorkerBackingThread::attach() -{ - { - MutexLocker locker(m_mutex); - if (++m_workerScriptCount > 1) - return; - } - initialize(); -} - -void WorkerBackingThread::detach() -{ - { - MutexLocker locker(m_mutex); - if (--m_workerScriptCount > 0) - return; - } - shutdown(); } void WorkerBackingThread::initialize()
diff --git a/third_party/WebKit/Source/core/workers/WorkerBackingThread.h b/third_party/WebKit/Source/core/workers/WorkerBackingThread.h index afbc4a0..389586706 100644 --- a/third_party/WebKit/Source/core/workers/WorkerBackingThread.h +++ b/third_party/WebKit/Source/core/workers/WorkerBackingThread.h
@@ -18,8 +18,8 @@ class WebThreadSupportingGC; // WorkerBackingThread represents a WebThread with Oilpan and V8 potentially -// shared by multiple WebWorker scripts. A WebWorker needs to call attach() when -// attaching itself to the backing thread, and call detach() when the script +// shared by multiple WebWorker scripts. A WebWorker needs to call initialize() +// to using V8 and Oilpan functionalities, and call detach() when the script // no longer needs the thread. // A WorkerBackingThread represents a WebThread while a WorkerThread corresponds // to a web worker. There is one-to-one correspondence between WorkerThread and @@ -37,21 +37,12 @@ ~WorkerBackingThread(); - // attach() and detach() attaches and detaches Oilpan and V8 to / from - // the caller worker script, respectively. attach() and detach() increments - // and decrements m_workerScriptCount. attach() initializes Oilpan and V8 - // when m_workerScriptCount is 0. detach() terminates Oilpan and V8 when - // m_workerScriptCount is 1. A worker script must not call any function - // after calling detach(). + // initialize() and shutdown() attaches and detaches Oilpan and V8 to / from + // the caller worker script, respectively. A worker script must not call + // any function after calling shutdown(). // They should be called from |this| thread. - void attach(); - void detach(); - - unsigned workerScriptCount() - { - MutexLocker locker(m_mutex); - return m_workerScriptCount; - } + void initialize(); + void shutdown(); WebThreadSupportingGC& backingThread() { @@ -67,14 +58,9 @@ private: WorkerBackingThread(const char* name, bool shouldCallGCOnShutdown); WorkerBackingThread(WebThread*, bool shouldCallGCOnSHutdown); - void initialize(); - void shutdown(); - // Protects |m_workerScriptCount|. - Mutex m_mutex; OwnPtr<WebThreadSupportingGC> m_backingThread; v8::Isolate* m_isolate = nullptr; - unsigned m_workerScriptCount = 0; bool m_isOwningThread; bool m_shouldCallGCOnShutdown; };
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp index 27ff8425..4c9fd41 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -398,17 +398,10 @@ // scope is already disposed, so we don't have to explicitly terminate the // worker execution. // - // (2) |workerScriptCount() == 1|: If other WorkerGlobalScopes are running - // on the worker thread, we should not terminate the worker execution. This - // condition is not entirely correct because other scripts can be being - // initialized or terminated simuletaneously. Though this function itself is - // protected by a mutex, it is possible that |workerScriptCount()| here is - // not consistent with that in |initialize| and |shutdown|. - // - // (3) |m_runningDebuggerTask|: Terminating during debugger task may lead to + // (2) |m_runningDebuggerTask|: Terminating during debugger task may lead to // crash due to heavy use of v8 api in debugger. Any debugger task is // guaranteed to finish, so we can wait for the completion. - bool shouldScheduleToTerminateExecution = !m_readyToShutdown && (workerBackingThread().workerScriptCount() == 1) && !m_runningDebuggerTask; + bool shouldScheduleToTerminateExecution = !m_readyToShutdown && !m_runningDebuggerTask; if (shouldScheduleToTerminateExecution) { if (mode == TerminationMode::Forcible) { @@ -461,7 +454,8 @@ return; } - workerBackingThread().attach(); + if (isOwningBackingThread()) + workerBackingThread().initialize(); if (shouldAttachThreadDebugger()) V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new WorkerThreadDebugger(this, isolate()))); @@ -546,7 +540,8 @@ m_workerGlobalScope->notifyContextDestroyed(); m_workerGlobalScope = nullptr; - workerBackingThread().detach(); + if (isOwningBackingThread()) + workerBackingThread().shutdown(); // We must not touch workerBackingThread() from now on. m_microtaskRunner = nullptr;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.h b/third_party/WebKit/Source/core/workers/WorkerThread.h index d31ff1f..556c934 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.h +++ b/third_party/WebKit/Source/core/workers/WorkerThread.h
@@ -161,6 +161,13 @@ // Called on the worker thread. virtual WorkerGlobalScope* createWorkerGlobalScope(PassOwnPtr<WorkerThreadStartupData>) = 0; + // Returns true when this WorkerThread owns the associated + // WorkerBackingThread exclusively. If this function returns true, the + // WorkerThread initializes / shutdowns the backing thread. Otherwise + // workerBackingThread() should be initialized / shutdown properly + // out of this class. + virtual bool isOwningBackingThread() const { return true; } + // Called on the worker thread. virtual void postInitialize() { }
diff --git a/third_party/WebKit/Source/modules/ModulesInitializer.cpp b/third_party/WebKit/Source/modules/ModulesInitializer.cpp index 7aabb48..b04f7fca 100644 --- a/third_party/WebKit/Source/modules/ModulesInitializer.cpp +++ b/third_party/WebKit/Source/modules/ModulesInitializer.cpp
@@ -65,7 +65,6 @@ { ASSERT(isInitialized()); DatabaseManager::terminateDatabaseThread(); - CompositorWorkerThread::terminateExecution(); CoreInitializer::shutdown(); CompositorWorkerThread::clearSharedBackingThread(); }
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp index 2458e8af..de797ad 100644 --- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
@@ -15,6 +15,7 @@ #include "platform/WaitableEvent.h" #include "platform/WebThreadSupportingGC.h" #include "public/platform/Platform.h" +#include "wtf/Assertions.h" namespace blink { @@ -39,20 +40,10 @@ s_instance = new BackingThreadHolder; } - static void terminateExecution() - { - MutexLocker locker(holderInstanceMutex()); - if (s_instance && s_instance->m_initialized) { - s_instance->thread()->isolate()->TerminateExecution(); - s_instance->m_terminatingExecution = true; - } - } - static void clear() { MutexLocker locker(holderInstanceMutex()); if (s_instance) { - DCHECK(!s_instance->m_initialized || s_instance->m_terminatingExecution); s_instance->shutdownAndWait(); delete s_instance; s_instance = nullptr; @@ -85,8 +76,8 @@ void initializeOnThread() { MutexLocker locker(holderInstanceMutex()); - DCHECK_EQ(0u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the first to attach to WorkerBackingThread"; - m_thread->attach(); + DCHECK(!m_initialized); + m_thread->initialize(); m_initialized = true; } @@ -100,13 +91,11 @@ void shutdownOnThread(WaitableEvent* doneEvent) { - DCHECK_EQ(1u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the last to detach from WorkerBackingThread"; - m_thread->detach(); + m_thread->shutdown(); doneEvent->signal(); } OwnPtr<WorkerBackingThread> m_thread; - bool m_terminatingExecution = false; bool m_initialized = false; static BackingThreadHolder* s_instance; @@ -151,12 +140,6 @@ BackingThreadHolder::ensureInstance(); } -void CompositorWorkerThread::terminateExecution() -{ - DCHECK(isMainThread()); - BackingThreadHolder::terminateExecution(); -} - void CompositorWorkerThread::clearSharedBackingThread() { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h index 9e349071..b72fe9c 100644 --- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h +++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h
@@ -12,7 +12,6 @@ class InProcessWorkerObjectProxy; -// This class is overridden in unit-tests. class MODULES_EXPORT CompositorWorkerThread final : public WorkerThread { public: static PassOwnPtr<CompositorWorkerThread> create(PassRefPtr<WorkerLoaderProxy>, InProcessWorkerObjectProxy&, double timeOrigin); @@ -25,15 +24,13 @@ static void ensureSharedBackingThread(); static void createSharedBackingThreadForTest(); - // This is called before CoreInitializer::shutdown as shutdown waits for - // worker threads that can be blocked by scripts. - static void terminateExecution(); static void clearSharedBackingThread(); protected: CompositorWorkerThread(PassRefPtr<WorkerLoaderProxy>, InProcessWorkerObjectProxy&, double timeOrigin); WorkerGlobalScope* createWorkerGlobalScope(PassOwnPtr<WorkerThreadStartupData>) override; + bool isOwningBackingThread() const override { return false; } private: InProcessWorkerObjectProxy& m_workerObjectProxy;
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp index 947cf80..1b3c0d83 100644 --- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
@@ -106,7 +106,6 @@ void TearDown() override { m_page.reset(); - CompositorWorkerThread::terminateExecution(); CompositorWorkerThread::clearSharedBackingThread(); } @@ -142,7 +141,6 @@ private: void executeScriptInWorker(WorkerThread* worker, WaitableEvent* waitEvent) { - EXPECT_GT(worker->workerBackingThread().workerScriptCount(), 0u); WorkerOrWorkletScriptController* scriptController = worker->workerGlobalScope()->scriptController(); bool evaluateResult = scriptController->evaluate(ScriptSourceCode("var counter = 0; ++counter;")); ASSERT_UNUSED(evaluateResult, evaluateResult); @@ -174,7 +172,9 @@ // Create the second worker and immediately destroy the first worker. OwnPtr<CompositorWorkerThread> secondWorker = createCompositorWorker(); - firstWorker->terminateAndWait(); + // We don't use terminateAndWait here to avoid forcible termination. + firstWorker->terminate(); + firstWorker->waitForShutdownForTesting(); // Wait until the second worker is initialized. Verify that the second worker is using the same // thread and Isolate as the first worker. @@ -196,21 +196,18 @@ { // Create the first worker, wait until it is initialized, and terminate it. OwnPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(); - WorkerBackingThread* workerBackingThread = &compositorWorker->workerBackingThread(); WebThreadSupportingGC* firstThread = &compositorWorker->workerBackingThread().backingThread(); checkWorkerCanExecuteScript(compositorWorker.get()); - ASSERT_EQ(2u, workerBackingThread->workerScriptCount()); - compositorWorker->terminateAndWait(); - - ASSERT_EQ(1u, workerBackingThread->workerScriptCount()); + // We don't use terminateAndWait here to avoid forcible termination. + compositorWorker->terminate(); + compositorWorker->waitForShutdownForTesting(); // Create the second worker. The backing thread is same. compositorWorker = createCompositorWorker(); WebThreadSupportingGC* secondThread = &compositorWorker->workerBackingThread().backingThread(); EXPECT_EQ(firstThread, secondThread); checkWorkerCanExecuteScript(compositorWorker.get()); - ASSERT_EQ(2u, workerBackingThread->workerScriptCount()); compositorWorker->terminateAndWait(); } @@ -225,7 +222,6 @@ // Request termination of the first worker and create the second worker // as soon as possible. - EXPECT_EQ(2u, firstWorker->workerBackingThread().workerScriptCount()); firstWorker->terminate(); // We don't wait for its termination. // Note: We rely on the assumption that the termination steps don't run
diff --git a/third_party/WebKit/Source/modules/payments/PaymentCompleter.h b/third_party/WebKit/Source/modules/payments/PaymentCompleter.h index 284d2a1..70e5c80 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentCompleter.h +++ b/third_party/WebKit/Source/modules/payments/PaymentCompleter.h
@@ -11,11 +11,17 @@ namespace blink { +enum PaymentComplete { + Success, + Fail, + Unknown +}; + class ScriptState; class MODULES_EXPORT PaymentCompleter : public GarbageCollectedMixin { public: - virtual ScriptPromise complete(ScriptState*, bool success) = 0; + virtual ScriptPromise complete(ScriptState*, PaymentComplete result) = 0; protected: virtual ~PaymentCompleter() {}
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp index de2c800..e1a1812 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -318,13 +318,13 @@ return ContextLifecycleObserver::getExecutionContext(); } -ScriptPromise PaymentRequest::complete(ScriptState* scriptState, bool success) +ScriptPromise PaymentRequest::complete(ScriptState* scriptState, PaymentComplete result) { if (m_completeResolver) return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Already called complete() once")); // The payment provider should respond in PaymentRequest::OnComplete(). - m_paymentProvider->Complete(success); + m_paymentProvider->Complete(mojom::blink::PaymentComplete(result)); m_completeResolver = ScriptPromiseResolver::create(scriptState); return m_completeResolver->promise();
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.h b/third_party/WebKit/Source/modules/payments/PaymentRequest.h index c150a99c..eaedaf2 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequest.h +++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.h
@@ -64,7 +64,7 @@ ExecutionContext* getExecutionContext() const override; // PaymentCompleter: - ScriptPromise complete(ScriptState*, bool success) override; + ScriptPromise complete(ScriptState*, PaymentComplete result) override; // PaymentUpdater: void onUpdatePaymentDetails(const ScriptValue& detailsScriptValue) override;
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp index 7984615..be38125 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp
@@ -361,9 +361,9 @@ EXPECT_FALSE(scope.getExceptionState().hadException()); request->show(scope.getScriptState()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnPaymentResponse(buildPaymentResponseForTest()); - request->complete(scope.getScriptState(), false); + request->complete(scope.getScriptState(), Fail); - request->complete(scope.getScriptState(), true).then(funcs.expectNoCall(), funcs.expectCall()); + request->complete(scope.getScriptState(), Success).then(funcs.expectNoCall(), funcs.expectCall()); } TEST(PaymentRequestTest, RejectShowPromiseOnError) @@ -389,7 +389,7 @@ request->show(scope.getScriptState()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnPaymentResponse(buildPaymentResponseForTest()); - request->complete(scope.getScriptState(), true).then(funcs.expectNoCall(), funcs.expectCall()); + request->complete(scope.getScriptState(), Success).then(funcs.expectNoCall(), funcs.expectCall()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnError(); } @@ -404,7 +404,7 @@ request->show(scope.getScriptState()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnPaymentResponse(buildPaymentResponseForTest()); - request->complete(scope.getScriptState(), true).then(funcs.expectCall(), funcs.expectNoCall()); + request->complete(scope.getScriptState(), Success).then(funcs.expectCall(), funcs.expectNoCall()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnComplete(); } @@ -432,7 +432,7 @@ request->show(scope.getScriptState()).then(funcs.expectCall(), funcs.expectNoCall()); static_cast<mojom::blink::PaymentRequestClient*>(request)->OnPaymentResponse(buildPaymentResponseForTest()); - request->complete(scope.getScriptState(), true).then(funcs.expectNoCall(), funcs.expectCall()); + request->complete(scope.getScriptState(), Success).then(funcs.expectNoCall(), funcs.expectCall()); request->onUpdatePaymentDetailsFailure(ScriptValue::from(scope.getScriptState(), "oops")); }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentResponse.cpp b/third_party/WebKit/Source/modules/payments/PaymentResponse.cpp index e79a75d..a2e498f 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentResponse.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentResponse.cpp
@@ -47,9 +47,14 @@ return ScriptValue(scriptState, fromJSONString(scriptState, m_stringifiedDetails, exceptionState)); } -ScriptPromise PaymentResponse::complete(ScriptState* scriptState, bool success) +ScriptPromise PaymentResponse::complete(ScriptState* scriptState, const String& result) { - return m_paymentCompleter->complete(scriptState, success); + PaymentComplete convertedResult = Unknown; + if (result == "success") + convertedResult = Success; + if (result == "fail") + convertedResult = Fail; + return m_paymentCompleter->complete(scriptState, convertedResult); } DEFINE_TRACE(PaymentResponse)
diff --git a/third_party/WebKit/Source/modules/payments/PaymentResponse.h b/third_party/WebKit/Source/modules/payments/PaymentResponse.h index 5f1e70511..8548b617 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentResponse.h +++ b/third_party/WebKit/Source/modules/payments/PaymentResponse.h
@@ -37,7 +37,7 @@ const String& payerEmail() const { return m_payerEmail; } const String& payerPhone() const { return m_payerPhone; } - ScriptPromise complete(ScriptState*, bool success); + ScriptPromise complete(ScriptState*, const String& result = ""); DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/modules/payments/PaymentResponse.idl b/third_party/WebKit/Source/modules/payments/PaymentResponse.idl index ce9b80d..a24427e 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentResponse.idl +++ b/third_party/WebKit/Source/modules/payments/PaymentResponse.idl
@@ -2,6 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// https://w3c.github.io/browser-payment-api/#idl-def-paymentcomplete + +enum PaymentComplete { + "success", + "fail", + "" +}; + // https://w3c.github.io/browser-payment-api/specs/paymentrequest.html#paymentresponse-interface [ @@ -14,5 +22,5 @@ [CallWith=ScriptState, RaisesException] readonly attribute object details; readonly attribute PaymentAddress? shippingAddress; - [CallWith=ScriptState] Promise<void> complete(boolean success); + [CallWith=ScriptState] Promise<void> complete(optional PaymentComplete paymentResult = ""); };
diff --git a/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp index 026fd103..ae633dca 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentResponseTest.cpp
@@ -32,7 +32,7 @@ ~MockPaymentCompleter() override {} - MOCK_METHOD2(complete, ScriptPromise(ScriptState*, bool success)); + MOCK_METHOD2(complete, ScriptPromise(ScriptState*, PaymentComplete result)); DEFINE_INLINE_TRACE() {} @@ -83,9 +83,9 @@ MockPaymentCompleter* completeCallback = new MockPaymentCompleter; PaymentResponse output(std::move(input), completeCallback); - EXPECT_CALL(*completeCallback, complete(scope.getScriptState(), true)); + EXPECT_CALL(*completeCallback, complete(scope.getScriptState(), Success)); - output.complete(scope.getScriptState(), true); + output.complete(scope.getScriptState(), "success"); } TEST(PaymentResponseTest, CompleteCalledWithFailure) @@ -97,9 +97,9 @@ MockPaymentCompleter* completeCallback = new MockPaymentCompleter; PaymentResponse output(std::move(input), completeCallback); - EXPECT_CALL(*completeCallback, complete(scope.getScriptState(), false)); + EXPECT_CALL(*completeCallback, complete(scope.getScriptState(), Fail)); - output.complete(scope.getScriptState(), false); + output.complete(scope.getScriptState(), "fail"); } } // namespace
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/python.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/python.py index 6356e4a6..dc9cf16 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/python.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/python.py
@@ -67,7 +67,6 @@ def _check_pylint(self): output = self._run_pylint(self._file_path) - print output errors = self._parse_pylint_output(output) for line_number, category, message in errors: self._handle_style_error(line_number, category, 5, message)
diff --git a/third_party/WebKit/public/platform/modules/payments/payment_request.mojom b/third_party/WebKit/public/platform/modules/payments/payment_request.mojom index c21a38a..0f07092 100644 --- a/third_party/WebKit/public/platform/modules/payments/payment_request.mojom +++ b/third_party/WebKit/public/platform/modules/payments/payment_request.mojom
@@ -109,6 +109,12 @@ string stringified_data; }; +enum PaymentComplete { + SUCCESS, + FAIL, + UNKNOWN +}; + interface PaymentRequest { SetClient(PaymentRequestClient client); Show(array<PaymentMethodData> methodData, @@ -116,5 +122,5 @@ PaymentOptions options); UpdateWith(PaymentDetails details); Abort(); - Complete(bool success); + Complete(PaymentComplete result); };
diff --git a/tools/perf/benchmarks/battor.py b/tools/perf/benchmarks/battor.py index b39d7c7..41c259e 100644 --- a/tools/perf/benchmarks/battor.py +++ b/tools/perf/benchmarks/battor.py
@@ -40,7 +40,7 @@ @classmethod def Name(cls): - return 'BattOr.BattOrCases' + return 'battor.power_cases' @benchmark.Disabled('android') # crbug.com/618330 class BattOrPowerMobileSitesNoChromeTrace(_BattOrBenchmark): @@ -56,4 +56,4 @@ @classmethod def Name(cls): - return 'battor.battor_cases.no_chrome_trace' + return 'battor.power_cases.no_chrome_trace'
diff --git a/tools/perf/benchmarks/page_cycler_v2.py b/tools/perf/benchmarks/page_cycler_v2.py index 9678ade..3319c9d6 100644 --- a/tools/perf/benchmarks/page_cycler_v2.py +++ b/tools/perf/benchmarks/page_cycler_v2.py
@@ -22,13 +22,17 @@ cat_filter = tracing_category_filter.TracingCategoryFilter( filter_string='blink.console,navigation,blink.user_timing,loading') + # Below categories are needed for first-meaningful-paint computation. + cat_filter.AddDisabledByDefault('disabled-by-default-blink.debug.layout') + cat_filter.AddIncludedCategory('devtools.timeline') + tbm_options = timeline_based_measurement.Options( overhead_level=cat_filter) tbm_options.SetTimelineBasedMetric('firstPaintMetric') return tbm_options -@benchmark.Disabled('win') # crbug.com/615178 +@benchmark.Disabled('win', 'reference') # crbug.com/615178, crbug.com/619254 class PageCyclerV2Typical25(_PageCyclerV2): """Page load time benchmark for a 25 typical web pages.
diff --git a/ui/accelerated_widget_mac/window_resize_helper_mac.cc b/ui/accelerated_widget_mac/window_resize_helper_mac.cc index b64e09b..a3b61836 100644 --- a/ui/accelerated_widget_mac/window_resize_helper_mac.cc +++ b/ui/accelerated_widget_mac/window_resize_helper_mac.cc
@@ -301,10 +301,6 @@ base::Bind(&WindowResizeHelperMac::EventTimedWait), target_task_runner); } -void WindowResizeHelperMac::ShutdownForTests() { - task_runner_ = nullptr; -} - bool WindowResizeHelperMac::WaitForSingleTaskToRun( const base::TimeDelta& max_delay) { PumpableTaskRunner* pumpable_task_runner =
diff --git a/ui/accelerated_widget_mac/window_resize_helper_mac.h b/ui/accelerated_widget_mac/window_resize_helper_mac.h index a83034f..f81cdc4 100644 --- a/ui/accelerated_widget_mac/window_resize_helper_mac.h +++ b/ui/accelerated_widget_mac/window_resize_helper_mac.h
@@ -53,10 +53,6 @@ void Init( const scoped_refptr<base::SingleThreadTaskRunner>& target_task_runner); - // Because this class is global, many tests may want to do this setup - // repeatedly, so need some way to uninitialize as well. - void ShutdownForTests(); - scoped_refptr<base::SingleThreadTaskRunner> task_runner() const; // UI THREAD ONLY -----------------------------------------------------------
diff --git a/ui/arc/OWNERS b/ui/arc/OWNERS index f068aeb..d7d81e7 100644 --- a/ui/arc/OWNERS +++ b/ui/arc/OWNERS
@@ -1,3 +1,4 @@ elijahtaylor@chromium.org hidehiko@chromium.org lhchavez@chromium.org +yusukes@chromium.org
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc index 924c9cf..03c912751 100644 --- a/ui/base/ime/input_method_chromeos.cc +++ b/ui/base/ime/input_method_chromeos.cc
@@ -25,6 +25,8 @@ #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/dom/dom_key.h" #include "ui/gfx/geometry/rect.h" namespace { @@ -361,9 +363,9 @@ } ui::KeyEvent fabricated_event(ET_KEY_PRESSED, VKEY_PROCESSKEY, - event->code(), + ui::DomCode::NONE, event->flags(), - event->GetDomKey(), + ui::DomKey::NONE, event->time_stamp()); ignore_result(DispatchKeyEventPostIME(&fabricated_event)); if (fabricated_event.stopped_propagation())
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/input_method_chromeos_unittest.cc index 83ae4df..7777d44 100644 --- a/ui/base/ime/input_method_chromeos_unittest.cc +++ b/ui/base/ime/input_method_chromeos_unittest.cc
@@ -969,9 +969,7 @@ EXPECT_EQ(ET_KEY_PRESSED, key_event.type()); EXPECT_EQ(VKEY_PROCESSKEY, key_event.key_code()); - EXPECT_EQ(eventA.code(), key_event.code()); EXPECT_EQ(eventA.flags(), key_event.flags()); - EXPECT_EQ(eventA.GetDomKey(), key_event.GetDomKey()); EXPECT_EQ(eventA.time_stamp(), key_event.time_stamp()); }
diff --git a/ui/events/devices/mojo/input_device.typemap b/ui/events/devices/mojo/input_device.typemap index 1207467..2296d7a 100644 --- a/ui/events/devices/mojo/input_device.typemap +++ b/ui/events/devices/mojo/input_device.typemap
@@ -3,11 +3,23 @@ # found in the LICENSE file. mojom = "//ui/events/devices/mojo/input_devices.mojom" -public_headers = [ "//ui/events/devices/input_device.h" ] -traits_headers = [ - "//ui/events/devices/mojo/input_device_struct_traits.h" - ] +public_headers = [ + "//ui/events/devices/input_device.h", + "//ui/events/devices/touchscreen_device.h", +] +traits_headers = [ "//ui/events/devices/mojo/input_device_struct_traits.h" ] +sources = [ + "//ui/events/devices/mojo/input_device_struct_traits.cc", +] public_deps = [ "//ui/events/devices", ] -type_mappings = [ "ui.mojom.InputDevice=ui::InputDevice" ] +deps = [ + "//ui/gfx/geometry", +] + +type_mappings = [ + "ui.mojom.InputDeviceType=ui::InputDeviceType", + "ui.mojom.InputDevice=ui::InputDevice", + "ui.mojom.TouchscreenDevice=ui::TouchscreenDevice", +]
diff --git a/ui/events/devices/mojo/input_device_struct_traits.cc b/ui/events/devices/mojo/input_device_struct_traits.cc new file mode 100644 index 0000000..afab820 --- /dev/null +++ b/ui/events/devices/mojo/input_device_struct_traits.cc
@@ -0,0 +1,83 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/events/devices/mojo/input_device_struct_traits.h" + +#include "base/logging.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" + +namespace mojo { + +ui::mojom::InputDeviceType +EnumTraits<ui::mojom::InputDeviceType, ui::InputDeviceType>::ToMojom( + ui::InputDeviceType type) { + switch (type) { + case ui::INPUT_DEVICE_INTERNAL: + return ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL; + case ui::INPUT_DEVICE_EXTERNAL: + return ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL; + case ui::INPUT_DEVICE_UNKNOWN: + return ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN; + } + NOTREACHED(); + return ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN; +} + +bool EnumTraits<ui::mojom::InputDeviceType, ui::InputDeviceType>::FromMojom( + ui::mojom::InputDeviceType type, + ui::InputDeviceType* output) { + switch (type) { + case ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL: + *output = ui::INPUT_DEVICE_INTERNAL; + break; + case ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL: + *output = ui::INPUT_DEVICE_EXTERNAL; + break; + case ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN: + *output = ui::INPUT_DEVICE_UNKNOWN; + break; + default: + // Who knows what values might come over the wire, fail if invalid. + return false; + } + return true; +} + +bool StructTraits<ui::mojom::InputDevice, ui::InputDevice>::Read( + ui::mojom::InputDeviceDataView data, + ui::InputDevice* out) { + out->id = data.id(); + + if (!data.ReadType(&out->type)) + return false; + + if (!data.ReadName(&out->name)) + return false; + + base::StringPiece sys_path_string; + if (!data.ReadSysPath(&sys_path_string)) + return false; + out->sys_path = base::FilePath::FromUTF8Unsafe(sys_path_string); + + out->vendor_id = data.vendor_id(); + out->product_id = data.product_id(); + + return true; +} + +bool StructTraits<ui::mojom::TouchscreenDevice, ui::TouchscreenDevice>::Read( + ui::mojom::TouchscreenDeviceDataView data, + ui::TouchscreenDevice* out) { + if (!data.ReadInputDevice(static_cast<ui::InputDevice*>(out))) + return false; + + if (!data.ReadSize(&out->size)) + return false; + + out->touch_points = data.touch_points(); + + return true; +} + +} // namespace mojo
diff --git a/ui/events/devices/mojo/input_device_struct_traits.h b/ui/events/devices/mojo/input_device_struct_traits.h index d2945bb..c4f890a 100644 --- a/ui/events/devices/mojo/input_device_struct_traits.h +++ b/ui/events/devices/mojo/input_device_struct_traits.h
@@ -16,18 +16,18 @@ namespace mojo { template <> +struct EnumTraits<ui::mojom::InputDeviceType, ui::InputDeviceType> { + static ui::mojom::InputDeviceType ToMojom(ui::InputDeviceType type); + static bool FromMojom(ui::mojom::InputDeviceType type, + ui::InputDeviceType* output); +}; + +template <> struct StructTraits<ui::mojom::InputDevice, ui::InputDevice> { static int32_t id(const ui::InputDevice& device) { return device.id; } - static ui::mojom::InputDeviceType type(const ui::InputDevice& device) { - switch (device.type) { - case ui::INPUT_DEVICE_INTERNAL: - return ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL; - case ui::INPUT_DEVICE_EXTERNAL: - return ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL; - case ui::INPUT_DEVICE_UNKNOWN: - return ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN; - } + static ui::InputDeviceType type(const ui::InputDevice& device) { + return device.type; } static const std::string& name(const ui::InputDevice& device) { @@ -46,37 +46,7 @@ return device.product_id; } - static bool Read(ui::mojom::InputDeviceDataView data, ui::InputDevice* out) { - out->id = data.id(); - - switch (data.type()) { - case ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL: - out->type = ui::INPUT_DEVICE_INTERNAL; - break; - case ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL: - out->type = ui::INPUT_DEVICE_EXTERNAL; - break; - case ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN: - out->type = ui::INPUT_DEVICE_UNKNOWN; - break; - default: - // Who knows what values might come over the wire, fail if invalid. - return false; - } - - if (!data.ReadName(&out->name)) - return false; - - base::StringPiece sys_path_string; - if (!data.ReadSysPath(&sys_path_string)) - return false; - out->sys_path = base::FilePath::FromUTF8Unsafe(sys_path_string); - - out->vendor_id = data.vendor_id(); - out->product_id = data.product_id(); - - return true; - } + static bool Read(ui::mojom::InputDeviceDataView data, ui::InputDevice* out); }; template <> @@ -95,17 +65,7 @@ } static bool Read(ui::mojom::TouchscreenDeviceDataView data, - ui::TouchscreenDevice* out) { - if (!data.ReadInputDevice(static_cast<ui::InputDevice*>(out))) - return false; - - if (!data.ReadSize(&out->size)) - return false; - - out->touch_points = data.touch_points(); - - return true; - } + ui::TouchscreenDevice* out); }; } // namespace mojo
diff --git a/ui/events/devices/mojo/touchscreen_device.typemap b/ui/events/devices/mojo/touchscreen_device.typemap deleted file mode 100644 index 589312f..0000000 --- a/ui/events/devices/mojo/touchscreen_device.typemap +++ /dev/null
@@ -1,16 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//ui/events/devices/mojo/input_devices.mojom" -public_headers = [ "//ui/events/devices/touchscreen_device.h" ] -traits_headers = [ - "//ui/events/devices/mojo/input_device_struct_traits.h" - ] -public_deps = [ - "//ui/events/devices", -] -deps = [ - "//ui/gfx/geometry", -] -type_mappings = [ "ui.mojom.TouchscreenDevice=ui::TouchscreenDevice" ]
diff --git a/ui/events/devices/mojo/typemaps.gni b/ui/events/devices/mojo/typemaps.gni index 996a8a5d..7ce719a 100644 --- a/ui/events/devices/mojo/typemaps.gni +++ b/ui/events/devices/mojo/typemaps.gni
@@ -2,7 +2,4 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -typemaps = [ - "//ui/events/devices/mojo/input_device.typemap", - "//ui/events/devices/mojo/touchscreen_device.typemap", -] +typemaps = [ "//ui/events/devices/mojo/input_device.typemap" ]
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 31030c4e..23fc099 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -93,6 +93,11 @@ // Disables specified comma separated GL Extensions if found. const char kDisableGLExtensions[] = "disable-gl-extensions"; +// Enables GL_INTEL_framebuffer_CMAA via shaders. Will be used if the platform +// does not support GL_INTEL_framebuffer_CMAA and the context is at least +// OpenGL ES 3.1 or OpenGL 3.0 with the required extensions. +const char kEnableCMAAShaders[] = "enable-cmaa-shaders"; + // This is the list of switches passed from this file that are passed from the // GpuProcessHost to the GPU Process. Add your switch to this list if you need // to read it in the GPU process, else don't add it. @@ -107,6 +112,7 @@ kOverrideUseGLWithOSMesaForTests, kUseANGLE, kDisableDirectComposition, + kEnableCMAAShaders, }; const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches = arraysize(kGLSwitchesCopiedFromGpuProcessHost);
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h index 6136460b..8f9dd26e 100644 --- a/ui/gl/gl_switches.h +++ b/ui/gl/gl_switches.h
@@ -54,6 +54,8 @@ GL_EXPORT extern const char* kGLSwitchesCopiedFromGpuProcessHost[]; GL_EXPORT extern const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches; +GL_EXPORT extern const char kEnableCMAAShaders[]; + } // namespace switches #endif // UI_GL_GL_SWITCHES_H_